├── .eslintrc ├── .gitignore ├── History.md ├── LICENSE ├── README.md ├── example.js ├── index.js ├── lib ├── agenda │ └── index.js ├── config │ ├── defaults.json │ └── index.js ├── db │ ├── connection.js │ └── index.js ├── jobs │ ├── index.js │ └── lib │ │ ├── comment-reply.js │ │ ├── forgot-password.js │ │ ├── new-comment.js │ │ ├── topic-published.js │ │ └── welcome-email.js ├── mailer │ ├── index.js │ └── transporter.js ├── templates │ ├── index.js │ └── lib │ │ ├── comment-reply.js │ │ ├── forgot-password.js │ │ ├── new-comment.js │ │ ├── topic-published.js │ │ └── welcome-email.js ├── translations │ ├── index.js │ └── lib │ │ ├── ca.json │ │ ├── de.json │ │ ├── en.json │ │ ├── es.json │ │ ├── fi.json │ │ ├── fr.json │ │ ├── gl.json │ │ ├── it.json │ │ ├── nl.json │ │ ├── pt.json │ │ ├── ru.json │ │ └── uk.json └── utils │ ├── graceful-exit.js │ ├── index.js │ └── listen-once-of.js ├── package-lock.json ├── package.json └── test └── index.js /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["democracyos"], 3 | "rules": { 4 | "promise/no-nesting": 0 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.sublime-* 3 | node_modules 4 | npm-debug.log 5 | /sandbox.js 6 | -------------------------------------------------------------------------------- /History.md: -------------------------------------------------------------------------------- 1 | 2 | 2.1.2 / 2017-07-27 3 | ================== 4 | 5 | * fix emtpy mailer configuration error 6 | 7 | 2.1.0 / 2017-07-10 8 | ================== 9 | 10 | * Fix replies query 11 | * Add new comment notification 12 | * Expose templates 13 | 14 | 2.0.3 / 2017-07-09 15 | ================== 16 | 17 | * Fix double initialization 18 | 19 | 2.0.2 / 2017-07-09 20 | ================== 21 | 22 | * Fix graceful exit 23 | 24 | 2.0.1 / 2017-07-09 25 | ================== 26 | 27 | * Fix node-graceful for agenda 28 | * Update author comparison 29 | 30 | 2.0.0 / 2017-07-09 31 | ================== 32 | 33 | * Complete notifier refactor 34 | 35 | 1.5.0 / 2017-06-02 36 | ================== 37 | 38 | * Remove timing function with moment dependency 39 | * Remove feeds collection connection 40 | * Remove update-feed, topic-voted, and topic-commented Jobs 41 | * Add eslint-config-democracyos 42 | 43 | 1.4.0 / 2017-05-25 44 | ================== 45 | 46 | * Add jobs.define method and refactor 47 | * Add cache for DB connection 48 | 49 | 1.3.1 / 2017-04-21 50 | ================== 51 | 52 | * Fix topic-published multiple calling to done() function DemocracyOS/democracyos#1393 53 | * Fix error messages Closes #30 54 | 55 | 1.3.0 / 2017-01-26 56 | ================== 57 | 58 | * Update agenda dependency to ~0.9.0 59 | 60 | 1.2.0 / 2017-01-25 61 | ================== 62 | 63 | * Update dependencies 64 | 65 | 1.1.3 / 2016-11-04 66 | ================== 67 | 68 | * fix defaulting to directTransport email sender 69 | * Fix for the ReDOS vulnerability #29 70 | 71 | 1.1.2 / 2016-10-24 72 | ================== 73 | 74 | * Fix notifier crash because of authMechanism 75 | 76 | 1.1.1 / 2016-10-19 77 | ================== 78 | 79 | * Update dependencies 80 | 81 | 1.1.0 / 2016-10-18 82 | ================== 83 | 84 | * Add generic config for nodemailer 85 | * Add availableLocales config option 86 | * Refactor configuration on its own module 87 | * Add unit tests #25 thanks @SebastienDaniel! 88 | 89 | 1.0.1 / 2016-03-02 90 | ================== 91 | 92 | * Correctly fallback missing translations to English 93 | 94 | 0.0.16 / 2016-02-03 95 | =================== 96 | 97 | * Re-add topic-published job 98 | 99 | 0.0.15 / 2015-11-03 100 | =================== 101 | 102 | * Fix locale on comment-reply email 103 | * Added ability to send notifications in the language of the target user 104 | 105 | 0.0.14 / 2015-10-29 106 | ================== 107 | 108 | * Force disable the topic-published action treatment 109 | * update mongojs and authentication method 110 | * update agenda 111 | 112 | 0.0.12 / 2015-10-02 113 | =================== 114 | 115 | * Using democracyos/agenda because npm version is outdated and does not work with MongoLab 116 | 117 | 0.0.10 / 2015-08-25 118 | =================== 119 | 120 | * Replace mailchimp for nodemailer #6 121 | * Fix missing opts reference 122 | * Fix default options & add default sender 123 | 124 | 0.0.9 / 2015-08-06 125 | ================== 126 | 127 | * Remove second parameter from done callback 128 | 129 | 0.0.8 / 2015-08-06 130 | ================== 131 | 132 | * Remove checking for 'done' being defined before calling it 133 | 134 | 0.0.7 / 2015-08-06 135 | ================== 136 | 137 | * Add topic-published job handler 138 | * Add topic voted job handler 139 | * Add topic commented job handler 140 | * Add .eslintrc file 141 | 142 | 0.0.6 / 2015-08-01 143 | ================== 144 | 145 | * Add topic-published event 146 | 147 | 0.0.5 / 2015-07-30 148 | ================== 149 | 150 | * Add comment-reply job 151 | 152 | 0.0.4 / 2015-07-30 153 | ================== 154 | 155 | * Update log usage 156 | * Fix `data` parameter missusage 157 | 158 | 0.0.3 / 2015-07-30 159 | ================== 160 | 161 | * Fix relative require paths 162 | 163 | 0.0.2 / 2015-07-30 164 | ================== 165 | 166 | * Add welcome-email job for events `signup` and `resend-validation` 167 | * Refactor part of events/jobs tier 168 | * Refactor forgot-password semantics to reset-password 169 | * Update debug log labels 170 | 171 | 0.0.1 / 2015-07-29 172 | ================== 173 | 174 | * Notifications engine and support for `forgot-password` event 175 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 DemocracyOS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DemocracyOS Notifier 2 | Embeddable notifications engine that relies on MongoDB for job queuing and scheduling. Powered by rschmukler/agenda 3 | 4 | ## Mailer Configuration 5 | 6 | Uses [NodeMailer](https://www.npmjs.com/package/nodemailer) package for email handling. Available services are the ones listed on the [nodemailer-wellknown](https://github.com/andris9/nodemailer-wellknown#supported-services) repo. 7 | 8 | ### SendGrid Example 9 | 10 | ```javascript 11 | var notifier = require('democracyos-notifier')({ 12 | mailer: { 13 | service: 'sendgrid', 14 | auth: { 15 | user: 'fake-sendgrid-user!@sendgrid.com', 16 | pass: 'fake-sendgrid-pass' 17 | } 18 | } 19 | }) 20 | ``` 21 | 22 | ### Gmail Example 23 | 24 | ```javascript 25 | var notifier = require('democracyos-notifier')({ 26 | mailer: { 27 | service: 'gmail', 28 | auth: { 29 | user: 'fake-gmail-user!@gmail.com', 30 | pass: 'fake-gmail-pass' 31 | } 32 | } 33 | }) 34 | ``` 35 | 36 | ### Direct Transport Example 37 | 38 | Not recommended for `production`. Using direct transport is not reliable as outgoing port 25 used is often blocked by default. Additionally mail sent from dynamic addresses is often flagged as spam. You should really consider using a SMTP provider. 39 | 40 | ```javascript 41 | var notifier = require('democracyos-notifier')() 42 | ``` 43 | 44 | ### Testing the code 45 | First install packages with `npm install` 46 | 47 | Then modify [`example.js`](./example.js) from and to mails. 48 | 49 | Test running `node example.js` -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable no-process-exit */ 2 | 3 | const config = require('./lib/config') 4 | const notifier = require('.') 5 | 6 | config.set({ 7 | "mongoUrl": 'mongodb://localhost/DemocracyOS-dev', 8 | "defaultLocale": "es", 9 | "mailer": { 10 | "service": "gmail", // can be other provider 11 | "auth": { 12 | "user": "my-send-email@gmail.com", 13 | "pass": "dont-commit-me!" 14 | } 15 | } 16 | }) 17 | 18 | notifier.start() 19 | .then(() => { 20 | console.log('Executing job welcome-email') 21 | 22 | return notifier.now('welcome-email', { 23 | to: 'test-to-mail@whatever.com', 24 | validateUrl: 'https://app.democracyos.org' 25 | }) 26 | }) 27 | .then(() => { 28 | return new Promise((resolve, reject) => { 29 | notifier.agenda.once('success:welcome-email', (job) => { 30 | resolve(job) 31 | }) 32 | 33 | notifier.agenda.once('fail:welcome-email', (err, job) => { 34 | reject(err) 35 | }) 36 | }) 37 | }) 38 | .then((job) => { 39 | console.log('User notified!', job.attrs) 40 | process.exit(0) 41 | }) 42 | .catch((err) => { 43 | console.error('Error!', err) 44 | process.exit(1) 45 | }) 46 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const pify = require('pify') 2 | const config = require('./lib/config') 3 | const templates = require('./lib/templates') 4 | 5 | // Load translations 6 | require('./lib/translations') 7 | 8 | const notifier = module.exports = {} 9 | 10 | /** 11 | * Notifier Init 12 | * Initialize async dependencies, including DB connection, jobs, etc 13 | * 14 | * @method init 15 | * @return {Notifier} 16 | */ 17 | 18 | let initialization = null 19 | 20 | notifier.init = function init () { 21 | if (initialization) return initialization 22 | 23 | initialization = Promise.all([ 24 | require('./lib/db'), 25 | require('./lib/mailer'), 26 | require('./lib/agenda') 27 | ]).then(([db, mailer, agenda]) => { 28 | notifier.db = db 29 | notifier.mailer = mailer 30 | notifier.agenda = agenda 31 | 32 | /** 33 | * Promisified verions of Agenda#every, Agenda#schedule and 34 | * Agenda#now methods 35 | */ 36 | ;['every', 'schedule', 'now'].forEach((method) => { 37 | notifier[method] = pify(agenda[method].bind(agenda)) 38 | }) 39 | 40 | return Promise.resolve(notifier) 41 | }).then((notifier) => { 42 | return require('./lib/jobs').init(notifier) 43 | }).catch((err) => { throw err }) 44 | 45 | return initialization 46 | } 47 | 48 | /** 49 | * Notifier Server Start 50 | * Start processing jobs 51 | * 52 | * @method start 53 | * @return {Notifier} 54 | */ 55 | 56 | notifier.start = function start () { 57 | return notifier.init().then(() => { 58 | notifier.agenda.start() 59 | return Promise.resolve(notifier) 60 | }).catch((err) => { throw err }) 61 | } 62 | 63 | /** 64 | * Expose config, this allows the overriding of any config option. 65 | * @return {Config} 66 | */ 67 | 68 | notifier.config = config 69 | 70 | /** 71 | * Expose templates, this allows the overriding of any template. 72 | * @return {Object} 73 | */ 74 | 75 | notifier.templates = templates 76 | 77 | /** 78 | * Expose db connection using mongojs 79 | * Will be defined after the call of init() 80 | * @return {MongoJS} 81 | */ 82 | 83 | notifier.db = null 84 | 85 | /** 86 | * Expose Agenda instance 87 | * Will be defined after the call of init() 88 | * @return {Agenda} 89 | */ 90 | 91 | notifier.agenda = null 92 | 93 | /** 94 | * Email sender utility 95 | * Will be defined after the call of init() 96 | * @return {Mailer} 97 | */ 98 | 99 | notifier.mailer = null 100 | -------------------------------------------------------------------------------- /lib/agenda/index.js: -------------------------------------------------------------------------------- 1 | const Agenda = require('agenda') 2 | const gracefulExit = require('../utils/graceful-exit') 3 | const config = require('../config') 4 | const connection = require('../db/connection') 5 | 6 | module.exports = connection.then((db) => { 7 | return new Promise((resolve, reject) => { 8 | const agenda = new Agenda({ 9 | mongo: db, 10 | db: { collection: config.get('collection') } 11 | }) 12 | 13 | agenda.on('error', reject) 14 | agenda.on('ready', () => resolve(agenda)) 15 | 16 | gracefulExit((done) => { 17 | agenda.stop(done) 18 | }) 19 | }) 20 | }).catch((err) => { throw err }) 21 | -------------------------------------------------------------------------------- /lib/config/defaults.json: -------------------------------------------------------------------------------- 1 | { 2 | "mongoUrl": "mongodb://localhost/DemocracyOS-dev", 3 | "collection": "notifierJobs", 4 | "defaultLocale": "en", 5 | "availableLocales": [ 6 | "ca", 7 | "de", 8 | "en", 9 | "es", 10 | "fi", 11 | "fr", 12 | "gl", 13 | "it", 14 | "nl", 15 | "pt", 16 | "ru", 17 | "uk" 18 | ], 19 | "organizationName": "The DemocracyOS team", 20 | "organizationEmail": "noreply@democracyos.org", 21 | "mailer": { 22 | "service": "", 23 | "auth": { 24 | "user": "", 25 | "pass": "" 26 | } 27 | }, 28 | "nodemailer": {} 29 | } 30 | -------------------------------------------------------------------------------- /lib/config/index.js: -------------------------------------------------------------------------------- 1 | var defaults = require('defaults-deep') 2 | var defaultConfig = require('./defaults.json') 3 | 4 | var config = defaults({}, defaultConfig) 5 | 6 | /** 7 | * Function to set new configuration values 8 | * @method set 9 | * @param {Object} newConfig new values to set on config 10 | */ 11 | module.exports.set = function configSet (newConfig) { 12 | config = defaults({}, newConfig, defaultConfig) 13 | } 14 | 15 | /** 16 | * Get a configuration value 17 | * @method get 18 | * @param {String} key dot notation key, e.g.: 'mailer.service' 19 | * @return {Mixed} current config value 20 | */ 21 | module.exports.get = function configGet (key) { 22 | if (typeof key !== 'string') throw new Error('"key" should be a string') 23 | 24 | return key.split('.').reduce(function (val, k) { 25 | return val[k] 26 | }, config) 27 | } 28 | -------------------------------------------------------------------------------- /lib/db/connection.js: -------------------------------------------------------------------------------- 1 | const db = require('.') 2 | 3 | module.exports = db.then((db) => { 4 | return db._db 5 | }).catch((err) => { throw err }) 6 | -------------------------------------------------------------------------------- /lib/db/index.js: -------------------------------------------------------------------------------- 1 | const monk = require('monk') 2 | const gracefulExit = require('../utils/graceful-exit') 3 | const listenOnceOf = require('../utils/listen-once-of') 4 | const config = require('../config') 5 | 6 | module.exports = monk(config.get('mongoUrl')).then((db) => { 7 | db.catch = db.then = new Promise((resolve, reject) => { 8 | switch (db._state) { 9 | case 'closed': 10 | reject(new Error('Connection closed')) 11 | break 12 | case 'open': 13 | resolve(db) 14 | break 15 | default: 16 | listenOnceOf(db, { 17 | open: resolve, 18 | 'error-opening': reject 19 | }) 20 | } 21 | }) 22 | 23 | gracefulExit((done) => { 24 | db.close(done) 25 | }) 26 | 27 | return db 28 | }).catch((err) => { throw err }) 29 | -------------------------------------------------------------------------------- /lib/jobs/index.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var requireAll = require('require-all') 3 | 4 | module.exports.init = function init (notifier) { 5 | const jobs = requireAll({ 6 | dirname: path.join(__dirname, '/lib'), 7 | resolve: (job) => typeof job === 'function' && job(notifier) 8 | }) 9 | 10 | return Promise.all(Object.keys(jobs).map((name) => jobs[name])) 11 | } 12 | -------------------------------------------------------------------------------- /lib/jobs/lib/comment-reply.js: -------------------------------------------------------------------------------- 1 | const monk = require('monk') 2 | const t = require('t-component') 3 | const templates = require('../../templates') 4 | const utils = require('../../utils') 5 | 6 | const jobName = 'comment-reply' 7 | const jobNameForSingleUser = 'comment-reply-single-recipient' 8 | 9 | module.exports = function topicPublished (notifier) { 10 | const { db, agenda, mailer } = notifier 11 | const users = db.get('users') 12 | const comments = db.get('comments') 13 | 14 | agenda.define(jobName, (job, done) => { 15 | const { topic, comment, reply, url } = job.attrs.data 16 | 17 | comments.distinct('replies.author', { 18 | _id: monk.id(comment.id) 19 | }).then((usersToNotify) => { 20 | usersToNotify.push(monk.id(comment.author.id)) 21 | 22 | return users.find({ 23 | $and: [ 24 | { 25 | _id: { $in: usersToNotify }, 26 | 'notifications.replies': true 27 | }, 28 | { _id: { $ne: monk.id(reply.author.id) } } 29 | ] 30 | }).each((user, { pause, resume }) => { 31 | pause() 32 | 33 | agenda.now(jobNameForSingleUser, { 34 | topicTitle: topic.mediaTitle, 35 | comment, 36 | reply, 37 | url, 38 | to: utils.emailAddress(user), 39 | locale: user.locale 40 | }, (err) => { 41 | if (err) return done(err) 42 | resume() 43 | }) 44 | }) 45 | }).then(() => { done() }).catch(done) 46 | }) 47 | 48 | agenda.define(jobNameForSingleUser, (job, done) => { 49 | const { 50 | topicTitle, 51 | comment, 52 | reply, 53 | url, 54 | to, 55 | locale 56 | } = job.attrs.data 57 | 58 | const html = templates[jobName]({ 59 | userName: to.name, 60 | topicTitle, 61 | comment, 62 | reply, 63 | url 64 | }, { 65 | lang: locale 66 | }) 67 | 68 | return mailer.send({ 69 | to, 70 | subject: t(`templates.${jobName}.subject`), 71 | html 72 | }).then(() => { done() }).catch(done) 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /lib/jobs/lib/forgot-password.js: -------------------------------------------------------------------------------- 1 | const t = require('t-component') 2 | const utils = require('../../utils') 3 | const templates = require('../../templates') 4 | 5 | const jobName = 'forgot-password' 6 | 7 | module.exports = function forgotPassword (notifier) { 8 | const { db, agenda, mailer } = notifier 9 | const users = db.get('users') 10 | 11 | agenda.define(jobName, { priority: 'high' }, (job, done) => { 12 | const data = job.attrs.data 13 | 14 | users.findOne({ email: data.to }).then((user) => { 15 | if (!user) throw new Error(`User not found for email "${data.to}"`) 16 | 17 | const html = templates[jobName]({ 18 | userName: user.firstName, 19 | resetPasswordUrl: data.resetUrl 20 | }, { 21 | lang: user.locale 22 | }) 23 | 24 | return mailer.send({ 25 | to: utils.emailAddress(user), 26 | subject: t(`templates.${jobName}.subject`), 27 | html 28 | }) 29 | }).then(() => { done() }).catch(done) 30 | }) 31 | } 32 | -------------------------------------------------------------------------------- /lib/jobs/lib/new-comment.js: -------------------------------------------------------------------------------- 1 | const monk = require('monk') 2 | const t = require('t-component') 3 | const templates = require('../../templates') 4 | const utils = require('../../utils') 5 | 6 | const jobName = 'new-comment' 7 | const jobNameForSingleUser = 'new-comment-single-recipient' 8 | 9 | module.exports = function topicPublished (notifier) { 10 | const { db, agenda, mailer } = notifier 11 | const users = db.get('users') 12 | const comments = db.get('comments') 13 | const forums = db.get('forums') 14 | 15 | agenda.define(jobName, (job, done) => { 16 | const { topic, comment, url } = job.attrs.data 17 | forums.findOne({_id: topic.forum}) 18 | .then((forum) => { 19 | const moderators = forum.permissions && forum.permissions 20 | .filter((p) => p.role === 'moderator') 21 | .map((r) => r.user) 22 | if (!moderators || moderators.length === 0) return 23 | 24 | return users.find({ 25 | $and: [ 26 | { _id: { $in: moderators } }, 27 | { _id: { $ne: monk.id(comment.author.id) } } 28 | ] 29 | }).each((user, { pause, resume }) => { 30 | pause() 31 | 32 | agenda.now(jobNameForSingleUser, { 33 | topicTitle: topic.mediaTitle, 34 | comment, 35 | url, 36 | to: utils.emailAddress(user), 37 | locale: user.locale 38 | }, (err) => { 39 | if (err) return done(err) 40 | resume() 41 | }) 42 | }) 43 | }).then(() => { done() }).catch(done) 44 | }) 45 | 46 | agenda.define(jobNameForSingleUser, (job, done) => { 47 | const { 48 | topicTitle, 49 | comment, 50 | url, 51 | to, 52 | locale 53 | } = job.attrs.data 54 | 55 | const html = templates[jobName]({ 56 | userName: to.name, 57 | topicTitle, 58 | comment, 59 | url 60 | }, { 61 | lang: locale 62 | }) 63 | 64 | return mailer.send({ 65 | to, 66 | subject: t(`templates.${jobName}.subject`, { topicTitle }), 67 | html 68 | }).then(() => { done() }).catch(done) 69 | }) 70 | } 71 | -------------------------------------------------------------------------------- /lib/jobs/lib/topic-published.js: -------------------------------------------------------------------------------- 1 | const t = require('t-component') 2 | const templates = require('../../templates') 3 | const utils = require('../../utils') 4 | 5 | const jobName = 'topic-published' 6 | const jobNameForSingleUser = 'topic-published-single-recipient' 7 | 8 | module.exports = function topicPublished (notifier) { 9 | const { db, agenda, mailer } = notifier 10 | const users = db.get('users') 11 | 12 | agenda.define(jobName, (job, done) => { 13 | const { topic, url } = job.attrs.data 14 | 15 | users.find({ 'notifications.new-topic': true }).each((user) => { 16 | return new Promise((resolve, reject) => { 17 | agenda.now(jobNameForSingleUser, { 18 | topic, 19 | url, 20 | to: utils.emailAddress(user), 21 | locale: user.locale 22 | }, (err) => { 23 | if (err) return reject(err) 24 | resolve() 25 | }) 26 | }) 27 | }).then(() => { done() }).catch(done) 28 | }) 29 | 30 | agenda.define(jobNameForSingleUser, (job, done) => { 31 | const { to, topic, url, locale } = job.attrs.data 32 | 33 | const html = templates[jobName]({ 34 | userName: to.name, 35 | topic: topic.mediaTitle, 36 | url 37 | }, { 38 | lang: locale 39 | }) 40 | 41 | return mailer.send({ 42 | to, 43 | subject: t(`templates.${jobName}.subject`), 44 | html 45 | }).then(() => { done() }).catch(done) 46 | }) 47 | } 48 | -------------------------------------------------------------------------------- /lib/jobs/lib/welcome-email.js: -------------------------------------------------------------------------------- 1 | const t = require('t-component') 2 | const utils = require('../../utils') 3 | const templates = require('../../templates') 4 | 5 | const jobName = 'welcome-email' 6 | 7 | module.exports = function welcomeEmail (notifier) { 8 | const { db, agenda, mailer } = notifier 9 | const users = db.get('users') 10 | 11 | agenda.define(jobName, { priority: 'high' }, welcomeEmailJob) 12 | agenda.define('signup', { priority: 'high' }, welcomeEmailJob) 13 | agenda.define('resend-validation', { priority: 'high' }, welcomeEmailJob) 14 | 15 | function welcomeEmailJob (job, done) { 16 | const data = job.attrs.data 17 | 18 | users.findOne({ email: data.to }).then((user) => { 19 | if (!user) throw new Error(`User not found for email "${data.to}"`) 20 | 21 | const html = templates[jobName]({ 22 | userName: user.firstName, 23 | validateUrl: data.validateUrl 24 | }, { 25 | lang: user.locale 26 | }) 27 | 28 | return mailer.send({ 29 | to: utils.emailAddress(user), 30 | subject: t(`templates.${jobName}.subject`), 31 | html 32 | }) 33 | }).then(() => { done() }).catch(done) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /lib/mailer/index.js: -------------------------------------------------------------------------------- 1 | const pify = require('pify') 2 | const config = require('../config') 3 | const transporter = require('./transporter') 4 | 5 | const sendMail = pify(transporter.sendMail.bind(transporter)) 6 | 7 | const defaultSender = { 8 | name: config.get('organizationName'), 9 | address: config.get('organizationEmail') 10 | } 11 | 12 | module.exports.send = function send (opts) { 13 | if (!opts.from) opts.from = defaultSender 14 | return sendMail(opts) 15 | } 16 | -------------------------------------------------------------------------------- /lib/mailer/transporter.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require('nodemailer') 2 | const config = require('../config') 3 | 4 | let opts = config.get('mailer.service') 5 | ? config.get('mailer') 6 | : config.get('nodemailer') 7 | 8 | // Use directTransport when nothing is configured 9 | if (opts && Object.keys(opts).length === 0) { 10 | opts = undefined 11 | } 12 | 13 | const transport = opts ? 14 | nodemailer.createTransport(opts) : 15 | nodemailer.createTransport({}) 16 | 17 | module.exports = transport 18 | -------------------------------------------------------------------------------- /lib/templates/index.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var requireAll = require('require-all') 3 | 4 | module.exports = requireAll(path.join(__dirname, '/lib')) 5 | -------------------------------------------------------------------------------- /lib/templates/lib/comment-reply.js: -------------------------------------------------------------------------------- 1 | const html = require('es6-string-html-template').html 2 | const raw = require('es6-string-html-template').raw 3 | 4 | module.exports = function welcomeEmail (vars, { lang }) { 5 | const t = translations[lang] || translations.en 6 | return t(vars) 7 | } 8 | 9 | const styles = raw(` 10 | 13 | `) 14 | 15 | const translations = module.exports.translations = { 16 | en: ({ userName, topicTitle, reply, comment, url }) => html` 17 | ${styles} 18 |

Hi! ${userName},

19 |
20 |

${reply.author.fullName} replied to a comment on "${topicTitle}".

21 |
22 |

Original comment by ${comment.author.fullName}:

23 |

${comment.text}

24 |
25 |

Reply by ${reply.author.fullName}:

26 |

${reply.text}

27 |
28 |

${raw(`Please click here to see it.`)}

29 | `.toString(), 30 | 31 | es: ({ userName, topicTitle, reply, comment, url }) => html` 32 | ${styles} 33 |

Hola ${userName},

34 |

${reply.author.fullName} respondió un comentario en "${topicTitle}".

35 |

Comentario original por ${comment.author.fullName}:

36 |

${comment.text}

37 |
38 |

Respuesta por ${reply.author.fullName}:

39 |

${reply.text}

40 |
41 |

${raw(`Por favor, cliquea aquí para verla.`)}

42 | `.toString() 43 | } 44 | -------------------------------------------------------------------------------- /lib/templates/lib/forgot-password.js: -------------------------------------------------------------------------------- 1 | const html = require('es6-string-html-template').html 2 | const raw = require('es6-string-html-template').raw 3 | const t = require('t-component') 4 | 5 | module.exports = function welcomeEmail (vars, opts) { 6 | t.lang(opts.lang) 7 | const _t = (key) => t(key, vars) 8 | 9 | return html` 10 |

${_t('templates.email.greeting')}

11 |

${raw(_t('templates.forgot-password.body'))}

12 |

${raw(_t('templates.email.signature'))}

13 |

${_t('templates.forgot-password.ps')}

14 | `.toString() 15 | } 16 | -------------------------------------------------------------------------------- /lib/templates/lib/new-comment.js: -------------------------------------------------------------------------------- 1 | const html = require('es6-string-html-template').html 2 | const raw = require('es6-string-html-template').raw 3 | 4 | module.exports = function welcomeEmail (vars, { lang }) { 5 | const t = translations[lang] || translations.en 6 | return t(vars) 7 | } 8 | 9 | const styles = raw(` 10 | 13 | `) 14 | 15 | const translations = module.exports.translations = { 16 | en: ({ userName, topicTitle, comment, url }) => html` 17 | ${styles} 18 |

Hi! ${userName},

19 |
20 |

${comment.author.fullName} commented the topic: "${topicTitle}":

21 |
22 |

${comment.text}

23 |
24 |

${raw(`Please click here to see it.`)}

25 | `.toString(), 26 | 27 | es: ({ userName, topicTitle, comment, url }) => html` 28 | ${styles} 29 |

Hola ${userName},

30 |

${comment.author.fullName} comentó en "${topicTitle}":

31 |
32 |

${comment.text}

33 |
34 |

${raw(`Por favor, cliquea aquí para verlo.`)}

35 | `.toString() 36 | } 37 | -------------------------------------------------------------------------------- /lib/templates/lib/topic-published.js: -------------------------------------------------------------------------------- 1 | const html = require('es6-string-html-template').html 2 | const raw = require('es6-string-html-template').raw 3 | const t = require('t-component') 4 | 5 | module.exports = function welcomeEmail (vars, opts) { 6 | t.lang(opts.lang) 7 | const _t = (key) => t(key, vars) 8 | 9 | return html` 10 |

${_t('templates.email.greeting')}

11 |

${_t('templates.topic-published.body')}

12 |

${vars.topic}

13 |

${raw(_t('templates.topic-published.body2'))}

14 |

${raw(_t('templates.email.signature'))}

15 | `.toString() 16 | } 17 | -------------------------------------------------------------------------------- /lib/templates/lib/welcome-email.js: -------------------------------------------------------------------------------- 1 | const html = require('es6-string-html-template').html 2 | const raw = require('es6-string-html-template').raw 3 | const t = require('t-component') 4 | 5 | module.exports = function welcomeEmail (vars, opts) { 6 | t.lang(opts.lang) 7 | const _t = (key) => t(key, vars) 8 | 9 | return html` 10 |

${_t('templates.email.greeting')}

11 |

${raw(_t('templates.welcome-email.body'))}

12 |

${raw(_t('templates.email.signature'))}

13 |

${_t('templates.welcome-email.ps')}

14 | `.toString() 15 | } 16 | -------------------------------------------------------------------------------- /lib/translations/index.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs') 2 | var path = require('path') 3 | var defaults = require('defaults-deep') 4 | var t = require('t-component') 5 | var config = require('../config') 6 | 7 | /** 8 | * Generate an Array with all the translated localizations 9 | */ 10 | var translated = fs.readdirSync(path.join(__dirname, 'lib')).map(function (p) { 11 | return p.replace('.json', '') 12 | }) 13 | 14 | var defaultTranslations = require('./lib/en') 15 | 16 | /** 17 | * Load localization dictionaries to translation application 18 | */ 19 | translated.forEach(function (locale) { 20 | var translation = require('./lib/' + locale) 21 | defaults(translation, defaultTranslations) 22 | t[locale] = translation 23 | }) 24 | 25 | t.lang = (function () { 26 | var original = t.lang 27 | 28 | function getLangCode (code) { 29 | if (!code) return config.get('defaultLocale') 30 | 31 | var isAvailable = config.get('availableLocales').indexOf(code) !== -1 32 | var isTranslated = translated.indexOf(code) !== -1 33 | 34 | if (isAvailable && isTranslated) { 35 | return code 36 | } else { 37 | return config.get('defaultLocale') 38 | } 39 | } 40 | 41 | return function lang (code) { 42 | code = getLangCode(code) 43 | original(code) 44 | return code 45 | } 46 | })() 47 | 48 | module.exports.t = t 49 | -------------------------------------------------------------------------------- /lib/translations/lib/ca.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Hola, {userName}.", 3 | "templates.email.signature": " L'equip de DemocracyOS.", 4 | 5 | "templates.welcome-email.subject": "Benvinguts/des a DemocracyOS!", 6 | "templates.welcome-email.body": "Si us plau cliqui aquí per validar la teva adreça de correu electrònic.", 7 | "templates.welcome-email.ps": "P.D.: Si no has creat un compte a DemocracyOS, si us plau ignora aquest correu.", 8 | 9 | "templates.forgot-password.subject": "Generar una nova contrasenya", 10 | "templates.forgot-password.body": "Si us plau, cliqui aquí per generar la teva contrasenya", 11 | "templates.forgot-password.ps": "P.D.: Si no has generat la teva contrasenya, si us plau ignora aquest correu", 12 | 13 | "templates.topic-published.subject": "Nova llei publicada", 14 | "templates.topic-published.body": "Una nova llei va ser publicada:", 15 | "templates.topic-published.body2": "Si us plau, cliqui aquí per veure-ho" 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/de.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Hallo, {userName},", 3 | "templates.email.signature": " Das DemocracyOS-Team.", 4 | 5 | "templates.welcome-email.subject": "Willkommen bei DemocracyOS!", 6 | "templates.welcome-email.body": "Bitte hier klicken, um deine E-Mail-Adresse zu bestätigen.", 7 | "templates.welcome-email.ps": "Bitte diese E-Mail ignorieren, falls du dich nicht bei DemocracyOS angemeldet hast.", 8 | 9 | "templates.forgot-password.subject": "Zurücksetzen des Passworts wurde angefordert", 10 | "templates.forgot-password.body": "Bitte hier klicken, um das Passwort zurückzusetzen.", 11 | "templates.forgot-password.ps": "Bitte diese E-Mail ignorieren, falls kein Zurücksetzen des Passwortes angefordert wurde.", 12 | 13 | "templates.topic-published.subject": "Neues Gesetz veröffentlicht", 14 | "templates.topic-published.body": "Ein neues Gesetz wurde veröffentlicht:", 15 | "templates.topic-published.body2": "Bitte hier klicken, um es zu sehen." 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/en.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Hi, {userName},", 3 | "templates.email.signature": " The DemocracyOS team.", 4 | 5 | "templates.welcome-email.subject": "Welcome to DemocracyOS!", 6 | "templates.welcome-email.body": "Please click here to validate your email address.", 7 | "templates.welcome-email.ps": "PS: if you didn't sign up, please ignore this email.", 8 | 9 | "templates.forgot-password.subject": "Password reset requested", 10 | "templates.forgot-password.body": "Please click here to reset your password", 11 | "templates.forgot-password.ps": "PS: if you haven't requested to reset your password, please ignore this email", 12 | 13 | "templates.comment-reply.subject": "Someone replied to your argument", 14 | "templates.new-comment.subject": "New comment on \"{topicTitle}\"", 15 | 16 | "templates.topic-published.subject": "New topic published", 17 | "templates.topic-published.body": "A new topic has been published:", 18 | "templates.topic-published.body2": "Please click here to see it." 19 | } 20 | -------------------------------------------------------------------------------- /lib/translations/lib/es.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Hola, {userName}", 3 | "templates.email.signature": " El equipo de DemocracyOS.", 4 | 5 | "templates.welcome-email.subject": "¡Bienvenid@ a DemocracyOS!", 6 | "templates.welcome-email.body": "Por favor cliquea aquí para validar tu dirección de correo electrónico.", 7 | "templates.welcome-email.ps": "P.D.: si no creaste una cuenta, por favor ignora este correo.", 8 | 9 | "templates.forgot-password.subject": "Reestablecer contraseña", 10 | "templates.forgot-password.body": "Por favor cliquea aquí para reestablecer tu contraseña", 11 | "templates.forgot-password.ps": "P.D.: si no solicitaste reestablecer tu contraseña, por favor ignora este correo", 12 | 13 | "templates.comment-reply.subject": "Alguien respondió a tu argumento", 14 | "templates.new-comment.subject": "Un comentario en \"{topicTitle}\"", 15 | 16 | "templates.topic-published.subject": "Nuevo tema publicado", 17 | "templates.topic-published.body": "Un nuevo tema fue publicado:", 18 | "templates.topic-published.body2": "Por favor cliquea aquí para verlo." 19 | } 20 | -------------------------------------------------------------------------------- /lib/translations/lib/fi.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Hei, {userName},", 3 | "templates.email.signature": " DemocracyOS tiimi.", 4 | 5 | "templates.welcome-email.subject": "Tervetuloa DemocracyOS!", 6 | "templates.welcome-email.body": "Ole hyvä klikkaa tästä vahvistaaksesi email-osoitteesi.", 7 | "templates.welcome-email.ps": "Jos et rekisteröitynyt, älä huomioi tätä viestiä.", 8 | 9 | "templates.forgot-password.subject": "Vaaditaan salasanan päivitys", 10 | "templates.forgot-password.body": "Ole hyvä klikkaa tästä vaihtaaksesi salasanasi", 11 | "templates.forgot-password.ps": "Jos et pyytänyt salasanan uusintaa, älä huomioi tätä viestiä.", 12 | 13 | "templates.topic-published.subject": "Uusi laki julkaistiin", 14 | "templates.topic-published.body": "Uusi laki julkaistiin:", 15 | "templates.topic-published.body2": "Ole hyvä ja klikkaa tästä nähdä sen" 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/fr.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Salut, {userName},", 3 | "templates.email.signature": " L' équipe de DemocracyOS.", 4 | 5 | "templates.welcome-email.subject": "Bienvenue à DemocracyOS!", 6 | "templates.welcome-email.body": "Cliquez s' il vous plaît sur ici pour valider votre adresse de courriel.", 7 | "templates.welcome-email.ps": "Si vous n' avez pas creé un compte sur DemocracyOS, ignorez s' il vous plaît ce courriel.", 8 | 9 | "templates.forgot-password.subject": "DemocracyOS - Rétablir mot de passe", 10 | "templates.forgot-password.body": "Cliquez s' il vous plaît sur ici pour rétablir ton mot de passe", 11 | "templates.forgot-password.ps": "Si vous n' avez pas demandé le rétablissement de votre mot de passe, ignorez s' il vous plaît ce courriel", 12 | 13 | "templates.topic-published.subject": "La nouvelle loi publiée", 14 | "templates.topic-published.body": "Une nouvelle loi a été publiée:", 15 | "templates.topic-published.body2": "Cliquez s'il vous plaît sur ici pour voir" 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/gl.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Ola, {userName}", 3 | "templates.email.signature": " O equipo de DemocracyOS.", 4 | 5 | "templates.welcome-email.subject": "Benvinda a DemocracyOS!", 6 | "templates.welcome-email.body": "Por favor fai click para validar o teu enderezo de correo electrónico.", 7 | "templates.welcome-email.ps": "P.D.: se non creaches unha conta, por favor ignora esta mensaxe.", 8 | 9 | "templates.forgot-password.subject": "Recuperar contrasinal", 10 | "templates.forgot-password.body": "Por favor fai click para reestablecer o teu contrasinal", 11 | "templates.forgot-password.ps": "P.D.: se non solicitaches recuperar o teu contrasinal, por favor ignora esta mensaxe", 12 | 13 | "templates.topic-published.subject": "Nova proposta publicada", 14 | "templates.topic-published.body": "Unha nova proposta foi publicada:", 15 | "templates.topic-published.body2": "Por favor fai click para vela." 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/it.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Ciao, {userName},", 3 | "templates.email.signature": " La squadra di DemocracyOS.", 4 | 5 | "templates.welcome-email.subject": "Benvenuto a DemocracyOS!", 6 | "templates.welcome-email.body": "Per favore clicca qui per convalidare l'email.", 7 | "templates.welcome-email.ps": "P.S.: se non hai firmato in Democracyos preghiamo di ignorare questa email.", 8 | 9 | "templates.forgot-password.subject": "Reimpostare la password", 10 | "templates.forgot-password.body": "Per favore clicca qui per reimpostare la password", 11 | "templates.forgot-password.ps": "P.S.: se non hai richiesto di reimpostare la password, ignorare questa email", 12 | 13 | "templates.topic-published.subject": "Nuova legge pubblicato", 14 | "templates.topic-published.body": "Una nuova legge è stata pubblicata:", 15 | "templates.topic-published.body2": "Si prega di cliccare qui per vederlo" 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/nl.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Hoi, {userName},", 3 | "templates.email.signature": " De DemocracyOS groep.", 4 | 5 | "templates.welcome-email.subject": "Welkom bij DemocracyOS!", 6 | "templates.welcome-email.body": "Klik hier om je e-mail adres te bevestigen.", 7 | "templates.welcome-email.ps": "Als je je niet hebt aangemeld, kun je deze e-mail negeren.", 8 | 9 | "templates.forgot-password.subject": "Wachtwoord herstellen aangevraagd", 10 | "templates.forgot-password.body": "Klik hier om je wachtwoord opnieuw in te stellen.", 11 | "templates.forgot-password.ps": "Als je niet gevraagd hebt om je wachtwoord opnieuw in te stellen, kun je deze e-mail negeren.", 12 | 13 | "templates.topic-published.subject": "Nieuwe wet gepubliceerd", 14 | "templates.topic-published.body": "Een nieuwe wet werd gepubliceerd:", 15 | "templates.topic-published.body2": "Klik hier om het te zien." 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/pt.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Olá, {userName},", 3 | "templates.email.signature": " Time - DemocracyOS.", 4 | 5 | "templates.welcome-email.subject": "Bem-vindo(a) ao DemocracyOS!", 6 | "templates.welcome-email.body": "Por favor clique aqui para validar seu endereço de e-mail.", 7 | "templates.welcome-email.ps": "Se você não se cadastrou, por favor ignore este e-mail.", 8 | 9 | "templates.forgot-password.subject": "Configurar nova senha", 10 | "templates.forgot-password.body": "Por favor, clique aqui para configurar nova senha.", 11 | "templates.forgot-password.ps": "Se você não solicitou criar uma nova senha, por favor ignore este e-mail", 12 | 13 | "templates.topic-published.subject": "Nova lei publicada", 14 | "templates.topic-published.body": "A nova lei foi publicada:", 15 | "templates.topic-published.body2": "Por favor, clique aqui para vê-la." 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/ru.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Здравствуйте, {userName},", 3 | "templates.email.signature": " Администрация DemocracyOS.", 4 | 5 | "templates.welcome-email.subject": "Добро пожаловать!", 6 | "templates.welcome-email.body": "Пожалуйста нажмите сюда чтобы подтвердить адрес Вашей электронной почты.", 7 | "templates.welcome-email.ps": "PS: Если Вы не регистрировались, пожалуйста не обращайте внимания на это сообщение.", 8 | 9 | "templates.forgot-password.subject": "Изменение пароля", 10 | "templates.forgot-password.body": "Пожалуйста нажмите сюда чтобы изменить Ваш пароль", 11 | "templates.forgot-password.ps": "PS: если Вы не пытались изменить Ваш пароль, пожалуйста не обращайте внимания на это сообщение.", 12 | 13 | "templates.topic-published.subject": "Опубликован новый закон", 14 | "templates.topic-published.body": "Новый закон был опубликован:", 15 | "templates.topic-published.body2": "Пожалуйста нажмите сюда чтобы увидеть его." 16 | } 17 | -------------------------------------------------------------------------------- /lib/translations/lib/uk.json: -------------------------------------------------------------------------------- 1 | { 2 | "templates.email.greeting": "Добрий день, {userName},", 3 | "templates.email.signature": " Адміністрація DemocracyOS.", 4 | 5 | "templates.welcome-email.subject": "Вітаємо!", 6 | "templates.welcome-email.body": "Будь ласка натисніть сюди щоб підтвердити адресу Вашої електронної пошти.", 7 | "templates.welcome-email.ps": "PS: Якщо Ви не реєструвалися, будь ласка не звертайте уваги на це повідомлення.", 8 | 9 | "templates.forgot-password.subject": "Зміна пароля", 10 | "templates.forgot-password.body": "Будь ласка натисніть сюди щоб змінити Ваш пароль", 11 | "templates.forgot-password.ps": "PS: якщо Ви не намагалися змінити Ваш пароль, будь ласка не звертайте уваги на це повідомлення.", 12 | 13 | "templates.topic-published.subject": "Опубліковано новий закон", 14 | "templates.topic-published.body": "Новий закон був опублікований:", 15 | "templates.topic-published.body2": "Будь ласка натисніть сюди щоб побачити його." 16 | } 17 | -------------------------------------------------------------------------------- /lib/utils/graceful-exit.js: -------------------------------------------------------------------------------- 1 | module.exports = function gracefulExit (callback) { 2 | function graceful() { 3 | callback((err) => { 4 | if (err) { 5 | console.error(err) 6 | process.exit(1) 7 | } 8 | 9 | process.exit(0) 10 | }) 11 | } 12 | 13 | process.on('SIGTERM', graceful) 14 | process.on('SIGINT' , graceful) 15 | } 16 | -------------------------------------------------------------------------------- /lib/utils/index.js: -------------------------------------------------------------------------------- 1 | module.exports.emailAddress = function emailAddress (user) { 2 | return { 3 | name: user.lastName ? user.firstName + ' ' + user.lastName : user.firstName, 4 | address: user.email 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /lib/utils/listen-once-of.js: -------------------------------------------------------------------------------- 1 | module.exports = function listenOnceOf (emitter, callbacks) { 2 | const events = Object.keys(callbacks) 3 | const listeners = {} 4 | 5 | const removeListeners = () => { 6 | events.forEach((event) => { 7 | emitter.removeListener(event, listeners[event]) 8 | }) 9 | } 10 | 11 | events.forEach((event) => { 12 | const listener = listeners[event] = (...args) => { 13 | removeListeners() 14 | callbacks[event](...args) 15 | } 16 | 17 | emitter.once(event, listener) 18 | }) 19 | } 20 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "democracyos-notifier", 3 | "version": "2.1.4", 4 | "lockfileVersion": 1, 5 | "requires": true, 6 | "dependencies": { 7 | "acorn": { 8 | "version": "5.7.3", 9 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", 10 | "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", 11 | "dev": true 12 | }, 13 | "acorn-jsx": { 14 | "version": "3.0.1", 15 | "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-3.0.1.tgz", 16 | "integrity": "sha1-r9+UiPsezvyDSPb7IvRk4ypYs2s=", 17 | "dev": true, 18 | "requires": { 19 | "acorn": "^3.0.4" 20 | }, 21 | "dependencies": { 22 | "acorn": { 23 | "version": "3.3.0", 24 | "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz", 25 | "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo=", 26 | "dev": true 27 | } 28 | } 29 | }, 30 | "agenda": { 31 | "version": "0.9.1", 32 | "resolved": "https://registry.npmjs.org/agenda/-/agenda-0.9.1.tgz", 33 | "integrity": "sha1-JRg4EZvl3mMIpvFcOD97rMHMtPY=", 34 | "requires": { 35 | "cron": "~1.1.0", 36 | "date.js": "~0.3.1", 37 | "human-interval": "~0.1.3", 38 | "moment-timezone": "^0.5.0", 39 | "mongodb": "^2.2.10" 40 | } 41 | }, 42 | "ajv": { 43 | "version": "4.11.8", 44 | "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", 45 | "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", 46 | "dev": true, 47 | "requires": { 48 | "co": "^4.6.0", 49 | "json-stable-stringify": "^1.0.1" 50 | } 51 | }, 52 | "ajv-keywords": { 53 | "version": "1.5.1", 54 | "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", 55 | "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", 56 | "dev": true 57 | }, 58 | "ansi-escapes": { 59 | "version": "1.4.0", 60 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-1.4.0.tgz", 61 | "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", 62 | "dev": true 63 | }, 64 | "ansi-regex": { 65 | "version": "2.1.1", 66 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", 67 | "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", 68 | "dev": true 69 | }, 70 | "ansi-styles": { 71 | "version": "2.2.1", 72 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", 73 | "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", 74 | "dev": true 75 | }, 76 | "argparse": { 77 | "version": "1.0.10", 78 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", 79 | "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", 80 | "dev": true, 81 | "requires": { 82 | "sprintf-js": "~1.0.2" 83 | } 84 | }, 85 | "array.prototype.find": { 86 | "version": "2.1.0", 87 | "resolved": "https://registry.npmjs.org/array.prototype.find/-/array.prototype.find-2.1.0.tgz", 88 | "integrity": "sha512-Wn41+K1yuO5p7wRZDl7890c3xvv5UBrfVXTVIe28rSQb6LS0fZMDrQB6PAcxQFRFy6vJTLDc3A2+3CjQdzVKRg==", 89 | "dev": true, 90 | "requires": { 91 | "define-properties": "^1.1.3", 92 | "es-abstract": "^1.13.0" 93 | } 94 | }, 95 | "assertion-error": { 96 | "version": "1.1.0", 97 | "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", 98 | "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", 99 | "dev": true 100 | }, 101 | "babel-code-frame": { 102 | "version": "6.26.0", 103 | "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", 104 | "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", 105 | "dev": true, 106 | "requires": { 107 | "chalk": "^1.1.3", 108 | "esutils": "^2.0.2", 109 | "js-tokens": "^3.0.2" 110 | } 111 | }, 112 | "babel-eslint": { 113 | "version": "7.1.1", 114 | "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-7.1.1.tgz", 115 | "integrity": "sha1-imqITwhapwYK9pz8dzQcL5k3D7I=", 116 | "dev": true, 117 | "requires": { 118 | "babel-code-frame": "^6.16.0", 119 | "babel-traverse": "^6.15.0", 120 | "babel-types": "^6.15.0", 121 | "babylon": "^6.13.0", 122 | "lodash.pickby": "^4.6.0" 123 | } 124 | }, 125 | "babel-messages": { 126 | "version": "6.23.0", 127 | "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", 128 | "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", 129 | "dev": true, 130 | "requires": { 131 | "babel-runtime": "^6.22.0" 132 | } 133 | }, 134 | "babel-runtime": { 135 | "version": "6.26.0", 136 | "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", 137 | "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", 138 | "dev": true, 139 | "requires": { 140 | "core-js": "^2.4.0", 141 | "regenerator-runtime": "^0.11.0" 142 | } 143 | }, 144 | "babel-traverse": { 145 | "version": "6.26.0", 146 | "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", 147 | "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", 148 | "dev": true, 149 | "requires": { 150 | "babel-code-frame": "^6.26.0", 151 | "babel-messages": "^6.23.0", 152 | "babel-runtime": "^6.26.0", 153 | "babel-types": "^6.26.0", 154 | "babylon": "^6.18.0", 155 | "debug": "^2.6.8", 156 | "globals": "^9.18.0", 157 | "invariant": "^2.2.2", 158 | "lodash": "^4.17.4" 159 | } 160 | }, 161 | "babel-types": { 162 | "version": "6.26.0", 163 | "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", 164 | "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", 165 | "dev": true, 166 | "requires": { 167 | "babel-runtime": "^6.26.0", 168 | "esutils": "^2.0.2", 169 | "lodash": "^4.17.4", 170 | "to-fast-properties": "^1.0.3" 171 | } 172 | }, 173 | "babylon": { 174 | "version": "6.18.0", 175 | "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", 176 | "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", 177 | "dev": true 178 | }, 179 | "balanced-match": { 180 | "version": "1.0.0", 181 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", 182 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", 183 | "dev": true 184 | }, 185 | "brace-expansion": { 186 | "version": "1.1.11", 187 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 188 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 189 | "dev": true, 190 | "requires": { 191 | "balanced-match": "^1.0.0", 192 | "concat-map": "0.0.1" 193 | } 194 | }, 195 | "browser-stdout": { 196 | "version": "1.3.0", 197 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.0.tgz", 198 | "integrity": "sha1-81HTKWnTL6XXpVZxVCY9korjvR8=", 199 | "dev": true 200 | }, 201 | "bson": { 202 | "version": "1.0.9", 203 | "resolved": "https://registry.npmjs.org/bson/-/bson-1.0.9.tgz", 204 | "integrity": "sha512-IQX9/h7WdMBIW/q/++tGd+emQr0XMdeZ6icnT/74Xk9fnabWn+gZgpE+9V+gujL3hhJOoNrnDVY7tWdzc7NUTg==" 205 | }, 206 | "buffer-from": { 207 | "version": "1.1.1", 208 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", 209 | "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", 210 | "dev": true 211 | }, 212 | "buffer-shims": { 213 | "version": "1.0.0", 214 | "resolved": "https://registry.npmjs.org/buffer-shims/-/buffer-shims-1.0.0.tgz", 215 | "integrity": "sha1-mXjOMXOIxkmth5MCjDR37wRKi1E=" 216 | }, 217 | "builtin-modules": { 218 | "version": "1.1.1", 219 | "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", 220 | "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=", 221 | "dev": true 222 | }, 223 | "caller-path": { 224 | "version": "0.1.0", 225 | "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", 226 | "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", 227 | "dev": true, 228 | "requires": { 229 | "callsites": "^0.2.0" 230 | } 231 | }, 232 | "callsites": { 233 | "version": "0.2.0", 234 | "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", 235 | "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", 236 | "dev": true 237 | }, 238 | "chai": { 239 | "version": "4.0.2", 240 | "resolved": "https://registry.npmjs.org/chai/-/chai-4.0.2.tgz", 241 | "integrity": "sha1-L3MnxN5vOF3XeHmZ4qsCaXoyuDs=", 242 | "dev": true, 243 | "requires": { 244 | "assertion-error": "^1.0.1", 245 | "check-error": "^1.0.1", 246 | "deep-eql": "^2.0.1", 247 | "get-func-name": "^2.0.0", 248 | "pathval": "^1.0.0", 249 | "type-detect": "^4.0.0" 250 | } 251 | }, 252 | "chalk": { 253 | "version": "1.1.3", 254 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", 255 | "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", 256 | "dev": true, 257 | "requires": { 258 | "ansi-styles": "^2.2.1", 259 | "escape-string-regexp": "^1.0.2", 260 | "has-ansi": "^2.0.0", 261 | "strip-ansi": "^3.0.0", 262 | "supports-color": "^2.0.0" 263 | } 264 | }, 265 | "check-error": { 266 | "version": "1.0.2", 267 | "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", 268 | "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", 269 | "dev": true 270 | }, 271 | "circular-json": { 272 | "version": "0.3.3", 273 | "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", 274 | "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", 275 | "dev": true 276 | }, 277 | "cli-cursor": { 278 | "version": "1.0.2", 279 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", 280 | "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", 281 | "dev": true, 282 | "requires": { 283 | "restore-cursor": "^1.0.1" 284 | } 285 | }, 286 | "cli-width": { 287 | "version": "2.2.0", 288 | "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", 289 | "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", 290 | "dev": true 291 | }, 292 | "co": { 293 | "version": "4.6.0", 294 | "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", 295 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", 296 | "dev": true 297 | }, 298 | "code-point-at": { 299 | "version": "1.1.0", 300 | "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", 301 | "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=", 302 | "dev": true 303 | }, 304 | "commander": { 305 | "version": "2.9.0", 306 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", 307 | "integrity": "sha1-nJkJQXbhIkDLItbFFGCYQA/g99Q=", 308 | "dev": true, 309 | "requires": { 310 | "graceful-readlink": ">= 1.0.0" 311 | } 312 | }, 313 | "concat-map": { 314 | "version": "0.0.1", 315 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 316 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", 317 | "dev": true 318 | }, 319 | "concat-stream": { 320 | "version": "1.6.2", 321 | "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", 322 | "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", 323 | "dev": true, 324 | "requires": { 325 | "buffer-from": "^1.0.0", 326 | "inherits": "^2.0.3", 327 | "readable-stream": "^2.2.2", 328 | "typedarray": "^0.0.6" 329 | } 330 | }, 331 | "contains-path": { 332 | "version": "0.1.0", 333 | "resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz", 334 | "integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=", 335 | "dev": true 336 | }, 337 | "core-js": { 338 | "version": "2.6.11", 339 | "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz", 340 | "integrity": "sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==", 341 | "dev": true 342 | }, 343 | "core-util-is": { 344 | "version": "1.0.2", 345 | "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", 346 | "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" 347 | }, 348 | "cron": { 349 | "version": "1.1.1", 350 | "resolved": "https://registry.npmjs.org/cron/-/cron-1.1.1.tgz", 351 | "integrity": "sha1-AnGdTvSA38juJNgaNgNGC6OQE84=", 352 | "requires": { 353 | "moment-timezone": "~0.5.5" 354 | } 355 | }, 356 | "d": { 357 | "version": "1.0.1", 358 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 359 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 360 | "dev": true, 361 | "requires": { 362 | "es5-ext": "^0.10.50", 363 | "type": "^1.0.1" 364 | } 365 | }, 366 | "date.js": { 367 | "version": "0.3.3", 368 | "resolved": "https://registry.npmjs.org/date.js/-/date.js-0.3.3.tgz", 369 | "integrity": "sha512-HgigOS3h3k6HnW011nAb43c5xx5rBXk8P2v/WIT9Zv4koIaVXiH2BURguI78VVp+5Qc076T7OR378JViCnZtBw==", 370 | "requires": { 371 | "debug": "~3.1.0" 372 | }, 373 | "dependencies": { 374 | "debug": { 375 | "version": "3.1.0", 376 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", 377 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", 378 | "requires": { 379 | "ms": "2.0.0" 380 | } 381 | } 382 | } 383 | }, 384 | "debug": { 385 | "version": "2.6.9", 386 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", 387 | "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", 388 | "requires": { 389 | "ms": "2.0.0" 390 | } 391 | }, 392 | "deep-eql": { 393 | "version": "2.0.2", 394 | "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-2.0.2.tgz", 395 | "integrity": "sha1-sbrAblbwp2d3aG1Qyf63XC7XZ5o=", 396 | "dev": true, 397 | "requires": { 398 | "type-detect": "^3.0.0" 399 | }, 400 | "dependencies": { 401 | "type-detect": { 402 | "version": "3.0.0", 403 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-3.0.0.tgz", 404 | "integrity": "sha1-RtDMhVOrt7E6NSsNbeov1Y8tm1U=", 405 | "dev": true 406 | } 407 | } 408 | }, 409 | "deep-is": { 410 | "version": "0.1.3", 411 | "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", 412 | "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", 413 | "dev": true 414 | }, 415 | "defaults-deep": { 416 | "version": "0.2.4", 417 | "resolved": "https://registry.npmjs.org/defaults-deep/-/defaults-deep-0.2.4.tgz", 418 | "integrity": "sha512-V6BtqzcMvn0EPOy7f+SfMhfmTawq+7UQdt9yZH0EBK89+IHo5f+Hse/qzTorAXOBrQpxpwb6cB/8OgtaMrT+Fg==", 419 | "requires": { 420 | "for-own": "^0.1.3", 421 | "is-extendable": "^0.1.1", 422 | "lazy-cache": "^0.2.3" 423 | } 424 | }, 425 | "define-properties": { 426 | "version": "1.1.3", 427 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", 428 | "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", 429 | "dev": true, 430 | "requires": { 431 | "object-keys": "^1.0.12" 432 | } 433 | }, 434 | "diff": { 435 | "version": "3.2.0", 436 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.2.0.tgz", 437 | "integrity": "sha1-yc45Okt8vQsFinJck98pkCeGj/k=", 438 | "dev": true 439 | }, 440 | "doctrine": { 441 | "version": "2.1.0", 442 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", 443 | "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", 444 | "dev": true, 445 | "requires": { 446 | "esutils": "^2.0.2" 447 | } 448 | }, 449 | "es-abstract": { 450 | "version": "1.17.0", 451 | "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.0.tgz", 452 | "integrity": "sha512-yYkE07YF+6SIBmg1MsJ9dlub5L48Ek7X0qz+c/CPCHS9EBXfESorzng4cJQjJW5/pB6vDF41u7F8vUhLVDqIug==", 453 | "dev": true, 454 | "requires": { 455 | "es-to-primitive": "^1.2.1", 456 | "function-bind": "^1.1.1", 457 | "has": "^1.0.3", 458 | "has-symbols": "^1.0.1", 459 | "is-callable": "^1.1.5", 460 | "is-regex": "^1.0.5", 461 | "object-inspect": "^1.7.0", 462 | "object-keys": "^1.1.1", 463 | "object.assign": "^4.1.0", 464 | "string.prototype.trimleft": "^2.1.1", 465 | "string.prototype.trimright": "^2.1.1" 466 | } 467 | }, 468 | "es-to-primitive": { 469 | "version": "1.2.1", 470 | "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", 471 | "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", 472 | "dev": true, 473 | "requires": { 474 | "is-callable": "^1.1.4", 475 | "is-date-object": "^1.0.1", 476 | "is-symbol": "^1.0.2" 477 | } 478 | }, 479 | "es5-ext": { 480 | "version": "0.10.53", 481 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", 482 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", 483 | "dev": true, 484 | "requires": { 485 | "es6-iterator": "~2.0.3", 486 | "es6-symbol": "~3.1.3", 487 | "next-tick": "~1.0.0" 488 | } 489 | }, 490 | "es6-iterator": { 491 | "version": "2.0.3", 492 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 493 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 494 | "dev": true, 495 | "requires": { 496 | "d": "1", 497 | "es5-ext": "^0.10.35", 498 | "es6-symbol": "^3.1.1" 499 | } 500 | }, 501 | "es6-map": { 502 | "version": "0.1.5", 503 | "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", 504 | "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", 505 | "dev": true, 506 | "requires": { 507 | "d": "1", 508 | "es5-ext": "~0.10.14", 509 | "es6-iterator": "~2.0.1", 510 | "es6-set": "~0.1.5", 511 | "es6-symbol": "~3.1.1", 512 | "event-emitter": "~0.3.5" 513 | } 514 | }, 515 | "es6-promise": { 516 | "version": "3.2.1", 517 | "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.2.1.tgz", 518 | "integrity": "sha1-7FYjOGgDKQkgcXDDlEjiREndH8Q=" 519 | }, 520 | "es6-set": { 521 | "version": "0.1.5", 522 | "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", 523 | "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", 524 | "dev": true, 525 | "requires": { 526 | "d": "1", 527 | "es5-ext": "~0.10.14", 528 | "es6-iterator": "~2.0.1", 529 | "es6-symbol": "3.1.1", 530 | "event-emitter": "~0.3.5" 531 | }, 532 | "dependencies": { 533 | "es6-symbol": { 534 | "version": "3.1.1", 535 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", 536 | "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", 537 | "dev": true, 538 | "requires": { 539 | "d": "1", 540 | "es5-ext": "~0.10.14" 541 | } 542 | } 543 | } 544 | }, 545 | "es6-string-html-template": { 546 | "version": "1.0.2", 547 | "resolved": "https://registry.npmjs.org/es6-string-html-template/-/es6-string-html-template-1.0.2.tgz", 548 | "integrity": "sha1-PISojbeIscMNLY7eGeYz5pXW3E0=" 549 | }, 550 | "es6-symbol": { 551 | "version": "3.1.3", 552 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 553 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 554 | "dev": true, 555 | "requires": { 556 | "d": "^1.0.1", 557 | "ext": "^1.1.2" 558 | } 559 | }, 560 | "es6-weak-map": { 561 | "version": "2.0.3", 562 | "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", 563 | "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", 564 | "dev": true, 565 | "requires": { 566 | "d": "1", 567 | "es5-ext": "^0.10.46", 568 | "es6-iterator": "^2.0.3", 569 | "es6-symbol": "^3.1.1" 570 | } 571 | }, 572 | "escape-string-regexp": { 573 | "version": "1.0.5", 574 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", 575 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", 576 | "dev": true 577 | }, 578 | "escope": { 579 | "version": "3.6.0", 580 | "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", 581 | "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", 582 | "dev": true, 583 | "requires": { 584 | "es6-map": "^0.1.3", 585 | "es6-weak-map": "^2.0.1", 586 | "esrecurse": "^4.1.0", 587 | "estraverse": "^4.1.1" 588 | } 589 | }, 590 | "eslint": { 591 | "version": "3.19.0", 592 | "resolved": "https://registry.npmjs.org/eslint/-/eslint-3.19.0.tgz", 593 | "integrity": "sha1-yPxiAcf0DdCJQbh8CFdnOGpnmsw=", 594 | "dev": true, 595 | "requires": { 596 | "babel-code-frame": "^6.16.0", 597 | "chalk": "^1.1.3", 598 | "concat-stream": "^1.5.2", 599 | "debug": "^2.1.1", 600 | "doctrine": "^2.0.0", 601 | "escope": "^3.6.0", 602 | "espree": "^3.4.0", 603 | "esquery": "^1.0.0", 604 | "estraverse": "^4.2.0", 605 | "esutils": "^2.0.2", 606 | "file-entry-cache": "^2.0.0", 607 | "glob": "^7.0.3", 608 | "globals": "^9.14.0", 609 | "ignore": "^3.2.0", 610 | "imurmurhash": "^0.1.4", 611 | "inquirer": "^0.12.0", 612 | "is-my-json-valid": "^2.10.0", 613 | "is-resolvable": "^1.0.0", 614 | "js-yaml": "^3.5.1", 615 | "json-stable-stringify": "^1.0.0", 616 | "levn": "^0.3.0", 617 | "lodash": "^4.0.0", 618 | "mkdirp": "^0.5.0", 619 | "natural-compare": "^1.4.0", 620 | "optionator": "^0.8.2", 621 | "path-is-inside": "^1.0.1", 622 | "pluralize": "^1.2.1", 623 | "progress": "^1.1.8", 624 | "require-uncached": "^1.0.2", 625 | "shelljs": "^0.7.5", 626 | "strip-bom": "^3.0.0", 627 | "strip-json-comments": "~2.0.1", 628 | "table": "^3.7.8", 629 | "text-table": "~0.2.0", 630 | "user-home": "^2.0.0" 631 | } 632 | }, 633 | "eslint-config-democracyos": { 634 | "version": "1.2.1", 635 | "resolved": "https://registry.npmjs.org/eslint-config-democracyos/-/eslint-config-democracyos-1.2.1.tgz", 636 | "integrity": "sha1-TTdaL2PhVlu33ENjKgt/U7QTD14=", 637 | "dev": true, 638 | "requires": { 639 | "babel-eslint": "~7.1.1", 640 | "eslint-config-standard": "~7.0.1", 641 | "eslint-config-standard-react": "~4.3.0", 642 | "eslint-plugin-babel": "~4.1.1", 643 | "eslint-plugin-import": "~2.2.0", 644 | "eslint-plugin-node": "~4.2.2", 645 | "eslint-plugin-promise": "~3.5.0", 646 | "eslint-plugin-react": "~6.10.0", 647 | "eslint-plugin-standard": "~2.1.1" 648 | } 649 | }, 650 | "eslint-config-standard": { 651 | "version": "7.0.3", 652 | "resolved": "https://registry.npmjs.org/eslint-config-standard/-/eslint-config-standard-7.0.3.tgz", 653 | "integrity": "sha1-FA97TxvgaI+xhXREwRTJJSMhzNY=", 654 | "dev": true 655 | }, 656 | "eslint-config-standard-jsx": { 657 | "version": "3.3.0", 658 | "resolved": "https://registry.npmjs.org/eslint-config-standard-jsx/-/eslint-config-standard-jsx-3.3.0.tgz", 659 | "integrity": "sha1-yrCAGhWjYL9j+suXqyL73YjYpeA=", 660 | "dev": true 661 | }, 662 | "eslint-config-standard-react": { 663 | "version": "4.3.0", 664 | "resolved": "https://registry.npmjs.org/eslint-config-standard-react/-/eslint-config-standard-react-4.3.0.tgz", 665 | "integrity": "sha1-fg01dfFaPAtmOcy2OUnftbo6Coo=", 666 | "dev": true, 667 | "requires": { 668 | "eslint-config-standard-jsx": "^3.0.0" 669 | } 670 | }, 671 | "eslint-import-resolver-node": { 672 | "version": "0.2.3", 673 | "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.2.3.tgz", 674 | "integrity": "sha1-Wt2BBujJKNssuiMrzZ76hG49oWw=", 675 | "dev": true, 676 | "requires": { 677 | "debug": "^2.2.0", 678 | "object-assign": "^4.0.1", 679 | "resolve": "^1.1.6" 680 | } 681 | }, 682 | "eslint-module-utils": { 683 | "version": "2.5.0", 684 | "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.5.0.tgz", 685 | "integrity": "sha512-kCo8pZaNz2dsAW7nCUjuVoI11EBXXpIzfNxmaoLhXoRDOnqXLC4iSGVRdZPhOitfbdEfMEfKOiENaK6wDPZEGw==", 686 | "dev": true, 687 | "requires": { 688 | "debug": "^2.6.9", 689 | "pkg-dir": "^2.0.0" 690 | } 691 | }, 692 | "eslint-plugin-babel": { 693 | "version": "4.1.2", 694 | "resolved": "https://registry.npmjs.org/eslint-plugin-babel/-/eslint-plugin-babel-4.1.2.tgz", 695 | "integrity": "sha1-eSAqDjV1fdkngJGbIzbx+i/lPB4=", 696 | "dev": true 697 | }, 698 | "eslint-plugin-import": { 699 | "version": "2.2.0", 700 | "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.2.0.tgz", 701 | "integrity": "sha1-crowb60wXWfEgWNIpGmaQimsi04=", 702 | "dev": true, 703 | "requires": { 704 | "builtin-modules": "^1.1.1", 705 | "contains-path": "^0.1.0", 706 | "debug": "^2.2.0", 707 | "doctrine": "1.5.0", 708 | "eslint-import-resolver-node": "^0.2.0", 709 | "eslint-module-utils": "^2.0.0", 710 | "has": "^1.0.1", 711 | "lodash.cond": "^4.3.0", 712 | "minimatch": "^3.0.3", 713 | "pkg-up": "^1.0.0" 714 | }, 715 | "dependencies": { 716 | "doctrine": { 717 | "version": "1.5.0", 718 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", 719 | "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", 720 | "dev": true, 721 | "requires": { 722 | "esutils": "^2.0.2", 723 | "isarray": "^1.0.0" 724 | } 725 | } 726 | } 727 | }, 728 | "eslint-plugin-node": { 729 | "version": "4.2.3", 730 | "resolved": "https://registry.npmjs.org/eslint-plugin-node/-/eslint-plugin-node-4.2.3.tgz", 731 | "integrity": "sha512-vIUQPuwbVYdz/CYnlTLsJrRy7iXHQjdEe5wz0XhhdTym3IInM/zZLlPf9nZ2mThsH0QcsieCOWs2vOeCy/22LQ==", 732 | "dev": true, 733 | "requires": { 734 | "ignore": "^3.0.11", 735 | "minimatch": "^3.0.2", 736 | "object-assign": "^4.0.1", 737 | "resolve": "^1.1.7", 738 | "semver": "5.3.0" 739 | }, 740 | "dependencies": { 741 | "semver": { 742 | "version": "5.3.0", 743 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", 744 | "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", 745 | "dev": true 746 | } 747 | } 748 | }, 749 | "eslint-plugin-promise": { 750 | "version": "3.5.0", 751 | "resolved": "https://registry.npmjs.org/eslint-plugin-promise/-/eslint-plugin-promise-3.5.0.tgz", 752 | "integrity": "sha1-ePu2/+BHIBYnVp6FpsU3OvKmj8o=", 753 | "dev": true 754 | }, 755 | "eslint-plugin-react": { 756 | "version": "6.10.3", 757 | "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-6.10.3.tgz", 758 | "integrity": "sha1-xUNb6wZ3ThLH2y9qut3L+QDNP3g=", 759 | "dev": true, 760 | "requires": { 761 | "array.prototype.find": "^2.0.1", 762 | "doctrine": "^1.2.2", 763 | "has": "^1.0.1", 764 | "jsx-ast-utils": "^1.3.4", 765 | "object.assign": "^4.0.4" 766 | }, 767 | "dependencies": { 768 | "doctrine": { 769 | "version": "1.5.0", 770 | "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz", 771 | "integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=", 772 | "dev": true, 773 | "requires": { 774 | "esutils": "^2.0.2", 775 | "isarray": "^1.0.0" 776 | } 777 | } 778 | } 779 | }, 780 | "eslint-plugin-standard": { 781 | "version": "2.1.1", 782 | "resolved": "https://registry.npmjs.org/eslint-plugin-standard/-/eslint-plugin-standard-2.1.1.tgz", 783 | "integrity": "sha1-l5YLFTfhcYu2M4d9CmUAUO//87A=", 784 | "dev": true 785 | }, 786 | "espree": { 787 | "version": "3.5.4", 788 | "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz", 789 | "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==", 790 | "dev": true, 791 | "requires": { 792 | "acorn": "^5.5.0", 793 | "acorn-jsx": "^3.0.0" 794 | } 795 | }, 796 | "esprima": { 797 | "version": "4.0.1", 798 | "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", 799 | "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", 800 | "dev": true 801 | }, 802 | "esquery": { 803 | "version": "1.0.1", 804 | "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", 805 | "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", 806 | "dev": true, 807 | "requires": { 808 | "estraverse": "^4.0.0" 809 | } 810 | }, 811 | "esrecurse": { 812 | "version": "4.2.1", 813 | "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", 814 | "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", 815 | "dev": true, 816 | "requires": { 817 | "estraverse": "^4.1.0" 818 | } 819 | }, 820 | "estraverse": { 821 | "version": "4.3.0", 822 | "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", 823 | "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", 824 | "dev": true 825 | }, 826 | "esutils": { 827 | "version": "2.0.3", 828 | "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", 829 | "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", 830 | "dev": true 831 | }, 832 | "event-emitter": { 833 | "version": "0.3.5", 834 | "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", 835 | "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", 836 | "dev": true, 837 | "requires": { 838 | "d": "1", 839 | "es5-ext": "~0.10.14" 840 | } 841 | }, 842 | "exit-hook": { 843 | "version": "1.1.1", 844 | "resolved": "https://registry.npmjs.org/exit-hook/-/exit-hook-1.1.1.tgz", 845 | "integrity": "sha1-8FyiM7SMBdVP/wd2XfhQfpXAL/g=", 846 | "dev": true 847 | }, 848 | "ext": { 849 | "version": "1.4.0", 850 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", 851 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", 852 | "dev": true, 853 | "requires": { 854 | "type": "^2.0.0" 855 | }, 856 | "dependencies": { 857 | "type": { 858 | "version": "2.0.0", 859 | "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", 860 | "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==", 861 | "dev": true 862 | } 863 | } 864 | }, 865 | "fast-levenshtein": { 866 | "version": "2.0.6", 867 | "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", 868 | "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", 869 | "dev": true 870 | }, 871 | "figures": { 872 | "version": "1.7.0", 873 | "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", 874 | "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", 875 | "dev": true, 876 | "requires": { 877 | "escape-string-regexp": "^1.0.5", 878 | "object-assign": "^4.1.0" 879 | } 880 | }, 881 | "file-entry-cache": { 882 | "version": "2.0.0", 883 | "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", 884 | "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", 885 | "dev": true, 886 | "requires": { 887 | "flat-cache": "^1.2.1", 888 | "object-assign": "^4.0.1" 889 | } 890 | }, 891 | "find-up": { 892 | "version": "2.1.0", 893 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", 894 | "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", 895 | "dev": true, 896 | "requires": { 897 | "locate-path": "^2.0.0" 898 | } 899 | }, 900 | "flat-cache": { 901 | "version": "1.3.4", 902 | "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.4.tgz", 903 | "integrity": "sha512-VwyB3Lkgacfik2vhqR4uv2rvebqmDvFu4jlN/C1RzWoJEo8I7z4Q404oiqYCkq41mni8EzQnm95emU9seckwtg==", 904 | "dev": true, 905 | "requires": { 906 | "circular-json": "^0.3.1", 907 | "graceful-fs": "^4.1.2", 908 | "rimraf": "~2.6.2", 909 | "write": "^0.2.1" 910 | } 911 | }, 912 | "for-in": { 913 | "version": "1.0.2", 914 | "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", 915 | "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" 916 | }, 917 | "for-own": { 918 | "version": "0.1.5", 919 | "resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz", 920 | "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", 921 | "requires": { 922 | "for-in": "^1.0.1" 923 | } 924 | }, 925 | "fs.realpath": { 926 | "version": "1.0.0", 927 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 928 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", 929 | "dev": true 930 | }, 931 | "function-bind": { 932 | "version": "1.1.1", 933 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 934 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 935 | "dev": true 936 | }, 937 | "generate-function": { 938 | "version": "2.3.1", 939 | "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", 940 | "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", 941 | "dev": true, 942 | "requires": { 943 | "is-property": "^1.0.2" 944 | } 945 | }, 946 | "generate-object-property": { 947 | "version": "1.2.0", 948 | "resolved": "https://registry.npmjs.org/generate-object-property/-/generate-object-property-1.2.0.tgz", 949 | "integrity": "sha1-nA4cQDCM6AT0eDYYuTf6iPmdUNA=", 950 | "dev": true, 951 | "requires": { 952 | "is-property": "^1.0.0" 953 | } 954 | }, 955 | "get-func-name": { 956 | "version": "2.0.0", 957 | "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", 958 | "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", 959 | "dev": true 960 | }, 961 | "glob": { 962 | "version": "7.1.6", 963 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", 964 | "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", 965 | "dev": true, 966 | "requires": { 967 | "fs.realpath": "^1.0.0", 968 | "inflight": "^1.0.4", 969 | "inherits": "2", 970 | "minimatch": "^3.0.4", 971 | "once": "^1.3.0", 972 | "path-is-absolute": "^1.0.0" 973 | } 974 | }, 975 | "globals": { 976 | "version": "9.18.0", 977 | "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", 978 | "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", 979 | "dev": true 980 | }, 981 | "graceful-fs": { 982 | "version": "4.2.3", 983 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", 984 | "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==", 985 | "dev": true 986 | }, 987 | "graceful-readlink": { 988 | "version": "1.0.1", 989 | "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", 990 | "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", 991 | "dev": true 992 | }, 993 | "growl": { 994 | "version": "1.9.2", 995 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.9.2.tgz", 996 | "integrity": "sha1-Dqd0NxXbjY3ixe3hd14bRayFwC8=", 997 | "dev": true 998 | }, 999 | "has": { 1000 | "version": "1.0.3", 1001 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1002 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1003 | "dev": true, 1004 | "requires": { 1005 | "function-bind": "^1.1.1" 1006 | } 1007 | }, 1008 | "has-ansi": { 1009 | "version": "2.0.0", 1010 | "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", 1011 | "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", 1012 | "dev": true, 1013 | "requires": { 1014 | "ansi-regex": "^2.0.0" 1015 | } 1016 | }, 1017 | "has-flag": { 1018 | "version": "1.0.0", 1019 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", 1020 | "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", 1021 | "dev": true 1022 | }, 1023 | "has-symbols": { 1024 | "version": "1.0.1", 1025 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", 1026 | "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", 1027 | "dev": true 1028 | }, 1029 | "human-interval": { 1030 | "version": "0.1.6", 1031 | "resolved": "https://registry.npmjs.org/human-interval/-/human-interval-0.1.6.tgz", 1032 | "integrity": "sha1-AFeXNFR2TDq8vrKu1hL8lkTmhIg=" 1033 | }, 1034 | "ignore": { 1035 | "version": "3.3.10", 1036 | "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", 1037 | "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", 1038 | "dev": true 1039 | }, 1040 | "imurmurhash": { 1041 | "version": "0.1.4", 1042 | "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", 1043 | "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", 1044 | "dev": true 1045 | }, 1046 | "inflight": { 1047 | "version": "1.0.6", 1048 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1049 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1050 | "dev": true, 1051 | "requires": { 1052 | "once": "^1.3.0", 1053 | "wrappy": "1" 1054 | } 1055 | }, 1056 | "inherits": { 1057 | "version": "2.0.4", 1058 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1059 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1060 | }, 1061 | "inquirer": { 1062 | "version": "0.12.0", 1063 | "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-0.12.0.tgz", 1064 | "integrity": "sha1-HvK/1jUE3wvHV4X/+MLEHfEvB34=", 1065 | "dev": true, 1066 | "requires": { 1067 | "ansi-escapes": "^1.1.0", 1068 | "ansi-regex": "^2.0.0", 1069 | "chalk": "^1.0.0", 1070 | "cli-cursor": "^1.0.1", 1071 | "cli-width": "^2.0.0", 1072 | "figures": "^1.3.5", 1073 | "lodash": "^4.3.0", 1074 | "readline2": "^1.0.1", 1075 | "run-async": "^0.1.0", 1076 | "rx-lite": "^3.1.2", 1077 | "string-width": "^1.0.1", 1078 | "strip-ansi": "^3.0.0", 1079 | "through": "^2.3.6" 1080 | } 1081 | }, 1082 | "interpret": { 1083 | "version": "1.2.0", 1084 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.2.0.tgz", 1085 | "integrity": "sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==", 1086 | "dev": true 1087 | }, 1088 | "invariant": { 1089 | "version": "2.2.4", 1090 | "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", 1091 | "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", 1092 | "dev": true, 1093 | "requires": { 1094 | "loose-envify": "^1.0.0" 1095 | } 1096 | }, 1097 | "is-callable": { 1098 | "version": "1.1.5", 1099 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", 1100 | "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", 1101 | "dev": true 1102 | }, 1103 | "is-date-object": { 1104 | "version": "1.0.2", 1105 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", 1106 | "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", 1107 | "dev": true 1108 | }, 1109 | "is-extendable": { 1110 | "version": "0.1.1", 1111 | "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", 1112 | "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" 1113 | }, 1114 | "is-fullwidth-code-point": { 1115 | "version": "1.0.0", 1116 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", 1117 | "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", 1118 | "dev": true, 1119 | "requires": { 1120 | "number-is-nan": "^1.0.0" 1121 | } 1122 | }, 1123 | "is-my-ip-valid": { 1124 | "version": "1.0.0", 1125 | "resolved": "https://registry.npmjs.org/is-my-ip-valid/-/is-my-ip-valid-1.0.0.tgz", 1126 | "integrity": "sha512-gmh/eWXROncUzRnIa1Ubrt5b8ep/MGSnfAUI3aRp+sqTCs1tv1Isl8d8F6JmkN3dXKc3ehZMrtiPN9eL03NuaQ==", 1127 | "dev": true 1128 | }, 1129 | "is-my-json-valid": { 1130 | "version": "2.20.0", 1131 | "resolved": "https://registry.npmjs.org/is-my-json-valid/-/is-my-json-valid-2.20.0.tgz", 1132 | "integrity": "sha512-XTHBZSIIxNsIsZXg7XB5l8z/OBFosl1Wao4tXLpeC7eKU4Vm/kdop2azkPqULwnfGQjmeDIyey9g7afMMtdWAA==", 1133 | "dev": true, 1134 | "requires": { 1135 | "generate-function": "^2.0.0", 1136 | "generate-object-property": "^1.1.0", 1137 | "is-my-ip-valid": "^1.0.0", 1138 | "jsonpointer": "^4.0.0", 1139 | "xtend": "^4.0.0" 1140 | } 1141 | }, 1142 | "is-property": { 1143 | "version": "1.0.2", 1144 | "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", 1145 | "integrity": "sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ=", 1146 | "dev": true 1147 | }, 1148 | "is-regex": { 1149 | "version": "1.0.5", 1150 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", 1151 | "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", 1152 | "dev": true, 1153 | "requires": { 1154 | "has": "^1.0.3" 1155 | } 1156 | }, 1157 | "is-resolvable": { 1158 | "version": "1.1.0", 1159 | "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", 1160 | "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", 1161 | "dev": true 1162 | }, 1163 | "is-symbol": { 1164 | "version": "1.0.3", 1165 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", 1166 | "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", 1167 | "dev": true, 1168 | "requires": { 1169 | "has-symbols": "^1.0.1" 1170 | } 1171 | }, 1172 | "isarray": { 1173 | "version": "1.0.0", 1174 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", 1175 | "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" 1176 | }, 1177 | "js-tokens": { 1178 | "version": "3.0.2", 1179 | "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", 1180 | "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", 1181 | "dev": true 1182 | }, 1183 | "js-yaml": { 1184 | "version": "3.13.1", 1185 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", 1186 | "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", 1187 | "dev": true, 1188 | "requires": { 1189 | "argparse": "^1.0.7", 1190 | "esprima": "^4.0.0" 1191 | } 1192 | }, 1193 | "json-stable-stringify": { 1194 | "version": "1.0.1", 1195 | "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz", 1196 | "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", 1197 | "dev": true, 1198 | "requires": { 1199 | "jsonify": "~0.0.0" 1200 | } 1201 | }, 1202 | "json3": { 1203 | "version": "3.3.2", 1204 | "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.2.tgz", 1205 | "integrity": "sha1-PAQ0dD35Pi9cQq7nsZvLSDV19OE=", 1206 | "dev": true 1207 | }, 1208 | "jsonify": { 1209 | "version": "0.0.0", 1210 | "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", 1211 | "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", 1212 | "dev": true 1213 | }, 1214 | "jsonpointer": { 1215 | "version": "4.0.1", 1216 | "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz", 1217 | "integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk=", 1218 | "dev": true 1219 | }, 1220 | "jsx-ast-utils": { 1221 | "version": "1.4.1", 1222 | "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-1.4.1.tgz", 1223 | "integrity": "sha1-OGchPo3Xm/Ho8jAMDPwe+xgsDfE=", 1224 | "dev": true 1225 | }, 1226 | "lazy-cache": { 1227 | "version": "0.2.7", 1228 | "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz", 1229 | "integrity": "sha1-f+3fLctu23fRHvHRF6tf/fCrG2U=" 1230 | }, 1231 | "levn": { 1232 | "version": "0.3.0", 1233 | "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", 1234 | "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", 1235 | "dev": true, 1236 | "requires": { 1237 | "prelude-ls": "~1.1.2", 1238 | "type-check": "~0.3.2" 1239 | } 1240 | }, 1241 | "locate-path": { 1242 | "version": "2.0.0", 1243 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", 1244 | "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", 1245 | "dev": true, 1246 | "requires": { 1247 | "p-locate": "^2.0.0", 1248 | "path-exists": "^3.0.0" 1249 | } 1250 | }, 1251 | "lodash": { 1252 | "version": "4.17.15", 1253 | "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", 1254 | "integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", 1255 | "dev": true 1256 | }, 1257 | "lodash._baseassign": { 1258 | "version": "3.2.0", 1259 | "resolved": "https://registry.npmjs.org/lodash._baseassign/-/lodash._baseassign-3.2.0.tgz", 1260 | "integrity": "sha1-jDigmVAPIVrQnlnxci/QxSv+Ck4=", 1261 | "dev": true, 1262 | "requires": { 1263 | "lodash._basecopy": "^3.0.0", 1264 | "lodash.keys": "^3.0.0" 1265 | } 1266 | }, 1267 | "lodash._basecopy": { 1268 | "version": "3.0.1", 1269 | "resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz", 1270 | "integrity": "sha1-jaDmqHbPNEwK2KVIghEd08XHyjY=", 1271 | "dev": true 1272 | }, 1273 | "lodash._basecreate": { 1274 | "version": "3.0.3", 1275 | "resolved": "https://registry.npmjs.org/lodash._basecreate/-/lodash._basecreate-3.0.3.tgz", 1276 | "integrity": "sha1-G8ZhYU2qf8MRt9A78WgGoCE8+CE=", 1277 | "dev": true 1278 | }, 1279 | "lodash._getnative": { 1280 | "version": "3.9.1", 1281 | "resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz", 1282 | "integrity": "sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U=", 1283 | "dev": true 1284 | }, 1285 | "lodash._isiterateecall": { 1286 | "version": "3.0.9", 1287 | "resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz", 1288 | "integrity": "sha1-UgOte6Ql+uhCRg5pbbnPPmqsBXw=", 1289 | "dev": true 1290 | }, 1291 | "lodash.cond": { 1292 | "version": "4.5.2", 1293 | "resolved": "https://registry.npmjs.org/lodash.cond/-/lodash.cond-4.5.2.tgz", 1294 | "integrity": "sha1-9HGh2khr5g9quVXRcRVSPdHSVdU=", 1295 | "dev": true 1296 | }, 1297 | "lodash.create": { 1298 | "version": "3.1.1", 1299 | "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", 1300 | "integrity": "sha1-1/KEnw29p+BGgruM1yqwIkYd6+c=", 1301 | "dev": true, 1302 | "requires": { 1303 | "lodash._baseassign": "^3.0.0", 1304 | "lodash._basecreate": "^3.0.0", 1305 | "lodash._isiterateecall": "^3.0.0" 1306 | } 1307 | }, 1308 | "lodash.isarguments": { 1309 | "version": "3.1.0", 1310 | "resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz", 1311 | "integrity": "sha1-L1c9hcaiQon/AGY7SRwdM4/zRYo=", 1312 | "dev": true 1313 | }, 1314 | "lodash.isarray": { 1315 | "version": "3.0.4", 1316 | "resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz", 1317 | "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", 1318 | "dev": true 1319 | }, 1320 | "lodash.keys": { 1321 | "version": "3.1.2", 1322 | "resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz", 1323 | "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", 1324 | "dev": true, 1325 | "requires": { 1326 | "lodash._getnative": "^3.0.0", 1327 | "lodash.isarguments": "^3.0.0", 1328 | "lodash.isarray": "^3.0.0" 1329 | } 1330 | }, 1331 | "lodash.pickby": { 1332 | "version": "4.6.0", 1333 | "resolved": "https://registry.npmjs.org/lodash.pickby/-/lodash.pickby-4.6.0.tgz", 1334 | "integrity": "sha1-feoh2MGNdwOifHBMFdO4SmfjOv8=", 1335 | "dev": true 1336 | }, 1337 | "loose-envify": { 1338 | "version": "1.4.0", 1339 | "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", 1340 | "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", 1341 | "dev": true, 1342 | "requires": { 1343 | "js-tokens": "^3.0.0 || ^4.0.0" 1344 | } 1345 | }, 1346 | "minimatch": { 1347 | "version": "3.0.4", 1348 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", 1349 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", 1350 | "dev": true, 1351 | "requires": { 1352 | "brace-expansion": "^1.1.7" 1353 | } 1354 | }, 1355 | "minimist": { 1356 | "version": "0.0.8", 1357 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", 1358 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", 1359 | "dev": true 1360 | }, 1361 | "mkdirp": { 1362 | "version": "0.5.1", 1363 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", 1364 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", 1365 | "dev": true, 1366 | "requires": { 1367 | "minimist": "0.0.8" 1368 | } 1369 | }, 1370 | "mocha": { 1371 | "version": "3.4.2", 1372 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-3.4.2.tgz", 1373 | "integrity": "sha1-0O9NMyEm2/GNDWQMmzgt1IvpdZQ=", 1374 | "dev": true, 1375 | "requires": { 1376 | "browser-stdout": "1.3.0", 1377 | "commander": "2.9.0", 1378 | "debug": "2.6.0", 1379 | "diff": "3.2.0", 1380 | "escape-string-regexp": "1.0.5", 1381 | "glob": "7.1.1", 1382 | "growl": "1.9.2", 1383 | "json3": "3.3.2", 1384 | "lodash.create": "3.1.1", 1385 | "mkdirp": "0.5.1", 1386 | "supports-color": "3.1.2" 1387 | }, 1388 | "dependencies": { 1389 | "debug": { 1390 | "version": "2.6.0", 1391 | "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.0.tgz", 1392 | "integrity": "sha1-vFlryr52F/Edn6FTYe3tVgi4SZs=", 1393 | "dev": true, 1394 | "requires": { 1395 | "ms": "0.7.2" 1396 | } 1397 | }, 1398 | "glob": { 1399 | "version": "7.1.1", 1400 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.1.tgz", 1401 | "integrity": "sha1-gFIR3wT6rxxjo2ADBs31reULLsg=", 1402 | "dev": true, 1403 | "requires": { 1404 | "fs.realpath": "^1.0.0", 1405 | "inflight": "^1.0.4", 1406 | "inherits": "2", 1407 | "minimatch": "^3.0.2", 1408 | "once": "^1.3.0", 1409 | "path-is-absolute": "^1.0.0" 1410 | } 1411 | }, 1412 | "ms": { 1413 | "version": "0.7.2", 1414 | "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.2.tgz", 1415 | "integrity": "sha1-riXPJRKziFodldfwN4aNhDESR2U=", 1416 | "dev": true 1417 | }, 1418 | "supports-color": { 1419 | "version": "3.1.2", 1420 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", 1421 | "integrity": "sha1-cqJiiU2dQIuVbKBf83su2KbiotU=", 1422 | "dev": true, 1423 | "requires": { 1424 | "has-flag": "^1.0.0" 1425 | } 1426 | } 1427 | } 1428 | }, 1429 | "moment": { 1430 | "version": "2.24.0", 1431 | "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", 1432 | "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" 1433 | }, 1434 | "moment-timezone": { 1435 | "version": "0.5.27", 1436 | "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.27.tgz", 1437 | "integrity": "sha512-EIKQs7h5sAsjhPCqN6ggx6cEbs94GK050254TIJySD1bzoM5JTYDwAU1IoVOeTOL6Gm27kYJ51/uuvq1kIlrbw==", 1438 | "requires": { 1439 | "moment": ">= 2.9.0" 1440 | } 1441 | }, 1442 | "mongodb": { 1443 | "version": "2.2.36", 1444 | "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-2.2.36.tgz", 1445 | "integrity": "sha512-P2SBLQ8Z0PVx71ngoXwo12+FiSfbNfGOClAao03/bant5DgLNkOPAck5IaJcEk4gKlQhDEURzfR3xuBG1/B+IA==", 1446 | "requires": { 1447 | "es6-promise": "3.2.1", 1448 | "mongodb-core": "2.1.20", 1449 | "readable-stream": "2.2.7" 1450 | } 1451 | }, 1452 | "mongodb-core": { 1453 | "version": "2.1.20", 1454 | "resolved": "https://registry.npmjs.org/mongodb-core/-/mongodb-core-2.1.20.tgz", 1455 | "integrity": "sha512-IN57CX5/Q1bhDq6ShAR6gIv4koFsZP7L8WOK1S0lR0pVDQaScffSMV5jxubLsmZ7J+UdqmykKw4r9hG3XQEGgQ==", 1456 | "requires": { 1457 | "bson": "~1.0.4", 1458 | "require_optional": "~1.0.0" 1459 | } 1460 | }, 1461 | "monk": { 1462 | "version": "6.0.6", 1463 | "resolved": "https://registry.npmjs.org/monk/-/monk-6.0.6.tgz", 1464 | "integrity": "sha512-bSuADQGwIxBcRzCzQaMoGmiGl30Dr+0iB1FQAQb3VwWwAKbtpDN2wkVHCjthzw/jXhPHWxTQFUtlSt/nSagojQ==", 1465 | "requires": { 1466 | "debug": "*", 1467 | "mongodb": "^2.1.18", 1468 | "monk-middleware-cast-ids": "^0.2.1", 1469 | "monk-middleware-fields": "^0.2.0", 1470 | "monk-middleware-handle-callback": "^0.2.0", 1471 | "monk-middleware-options": "^0.2.1", 1472 | "monk-middleware-query": "^0.2.0", 1473 | "monk-middleware-wait-for-connection": "^0.2.0", 1474 | "object-assign": "^4.1.1" 1475 | } 1476 | }, 1477 | "monk-middleware-cast-ids": { 1478 | "version": "0.2.1", 1479 | "resolved": "https://registry.npmjs.org/monk-middleware-cast-ids/-/monk-middleware-cast-ids-0.2.1.tgz", 1480 | "integrity": "sha1-QMQOWmyzPM7cKJIglDJ17ohhxSk=" 1481 | }, 1482 | "monk-middleware-fields": { 1483 | "version": "0.2.0", 1484 | "resolved": "https://registry.npmjs.org/monk-middleware-fields/-/monk-middleware-fields-0.2.0.tgz", 1485 | "integrity": "sha1-/2N6819ZSIecyyvhWpE2CRG+psE=" 1486 | }, 1487 | "monk-middleware-handle-callback": { 1488 | "version": "0.2.2", 1489 | "resolved": "https://registry.npmjs.org/monk-middleware-handle-callback/-/monk-middleware-handle-callback-0.2.2.tgz", 1490 | "integrity": "sha512-5hBynb7asZ2uw9XVze7C3XH0zXT51yFDvYydk/5HnWWzh2NLglDSiKDcX0yLKPHzFgiq+5Z4Laq5fFVnFsmm8w==" 1491 | }, 1492 | "monk-middleware-options": { 1493 | "version": "0.2.1", 1494 | "resolved": "https://registry.npmjs.org/monk-middleware-options/-/monk-middleware-options-0.2.1.tgz", 1495 | "integrity": "sha1-WNrhxRjUZjbr3/UG+t/Hc7tEKIY=" 1496 | }, 1497 | "monk-middleware-query": { 1498 | "version": "0.2.0", 1499 | "resolved": "https://registry.npmjs.org/monk-middleware-query/-/monk-middleware-query-0.2.0.tgz", 1500 | "integrity": "sha1-qSbGd9SlYgxiFRsKVtDAwVFnWHQ=" 1501 | }, 1502 | "monk-middleware-wait-for-connection": { 1503 | "version": "0.2.0", 1504 | "resolved": "https://registry.npmjs.org/monk-middleware-wait-for-connection/-/monk-middleware-wait-for-connection-0.2.0.tgz", 1505 | "integrity": "sha1-MSlY0w5Yi1fQl1TdfJe0hDMWg1o=" 1506 | }, 1507 | "ms": { 1508 | "version": "2.0.0", 1509 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", 1510 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" 1511 | }, 1512 | "mute-stream": { 1513 | "version": "0.0.5", 1514 | "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.5.tgz", 1515 | "integrity": "sha1-j7+rsKmKJT0xhDMfno3rc3L6xsA=", 1516 | "dev": true 1517 | }, 1518 | "natural-compare": { 1519 | "version": "1.4.0", 1520 | "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", 1521 | "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", 1522 | "dev": true 1523 | }, 1524 | "next-tick": { 1525 | "version": "1.0.0", 1526 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 1527 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", 1528 | "dev": true 1529 | }, 1530 | "nodemailer": { 1531 | "version": "4.0.1", 1532 | "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.0.1.tgz", 1533 | "integrity": "sha1-uVhksH+s7oKH6CMu/9bx1W7HWrI=" 1534 | }, 1535 | "number-is-nan": { 1536 | "version": "1.0.1", 1537 | "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", 1538 | "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=", 1539 | "dev": true 1540 | }, 1541 | "object-assign": { 1542 | "version": "4.1.1", 1543 | "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", 1544 | "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" 1545 | }, 1546 | "object-inspect": { 1547 | "version": "1.7.0", 1548 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", 1549 | "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", 1550 | "dev": true 1551 | }, 1552 | "object-keys": { 1553 | "version": "1.1.1", 1554 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1555 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1556 | "dev": true 1557 | }, 1558 | "object.assign": { 1559 | "version": "4.1.0", 1560 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", 1561 | "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", 1562 | "dev": true, 1563 | "requires": { 1564 | "define-properties": "^1.1.2", 1565 | "function-bind": "^1.1.1", 1566 | "has-symbols": "^1.0.0", 1567 | "object-keys": "^1.0.11" 1568 | } 1569 | }, 1570 | "once": { 1571 | "version": "1.4.0", 1572 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1573 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1574 | "dev": true, 1575 | "requires": { 1576 | "wrappy": "1" 1577 | } 1578 | }, 1579 | "onetime": { 1580 | "version": "1.1.0", 1581 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", 1582 | "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", 1583 | "dev": true 1584 | }, 1585 | "optionator": { 1586 | "version": "0.8.3", 1587 | "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz", 1588 | "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==", 1589 | "dev": true, 1590 | "requires": { 1591 | "deep-is": "~0.1.3", 1592 | "fast-levenshtein": "~2.0.6", 1593 | "levn": "~0.3.0", 1594 | "prelude-ls": "~1.1.2", 1595 | "type-check": "~0.3.2", 1596 | "word-wrap": "~1.2.3" 1597 | } 1598 | }, 1599 | "os-homedir": { 1600 | "version": "1.0.2", 1601 | "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", 1602 | "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=", 1603 | "dev": true 1604 | }, 1605 | "p-limit": { 1606 | "version": "1.3.0", 1607 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", 1608 | "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", 1609 | "dev": true, 1610 | "requires": { 1611 | "p-try": "^1.0.0" 1612 | } 1613 | }, 1614 | "p-locate": { 1615 | "version": "2.0.0", 1616 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", 1617 | "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", 1618 | "dev": true, 1619 | "requires": { 1620 | "p-limit": "^1.1.0" 1621 | } 1622 | }, 1623 | "p-try": { 1624 | "version": "1.0.0", 1625 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", 1626 | "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", 1627 | "dev": true 1628 | }, 1629 | "path-exists": { 1630 | "version": "3.0.0", 1631 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", 1632 | "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", 1633 | "dev": true 1634 | }, 1635 | "path-is-absolute": { 1636 | "version": "1.0.1", 1637 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1638 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 1639 | "dev": true 1640 | }, 1641 | "path-is-inside": { 1642 | "version": "1.0.2", 1643 | "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", 1644 | "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", 1645 | "dev": true 1646 | }, 1647 | "path-parse": { 1648 | "version": "1.0.6", 1649 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", 1650 | "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==", 1651 | "dev": true 1652 | }, 1653 | "pathval": { 1654 | "version": "1.1.0", 1655 | "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz", 1656 | "integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA=", 1657 | "dev": true 1658 | }, 1659 | "pify": { 1660 | "version": "3.0.0", 1661 | "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", 1662 | "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=" 1663 | }, 1664 | "pinkie": { 1665 | "version": "2.0.4", 1666 | "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", 1667 | "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", 1668 | "dev": true 1669 | }, 1670 | "pinkie-promise": { 1671 | "version": "2.0.1", 1672 | "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", 1673 | "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", 1674 | "dev": true, 1675 | "requires": { 1676 | "pinkie": "^2.0.0" 1677 | } 1678 | }, 1679 | "pkg-dir": { 1680 | "version": "2.0.0", 1681 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-2.0.0.tgz", 1682 | "integrity": "sha1-9tXREJ4Z1j7fQo4L1X4Sd3YVM0s=", 1683 | "dev": true, 1684 | "requires": { 1685 | "find-up": "^2.1.0" 1686 | } 1687 | }, 1688 | "pkg-up": { 1689 | "version": "1.0.0", 1690 | "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-1.0.0.tgz", 1691 | "integrity": "sha1-Pgj7RhUlxEIWJKM7n35tCvWwWiY=", 1692 | "dev": true, 1693 | "requires": { 1694 | "find-up": "^1.0.0" 1695 | }, 1696 | "dependencies": { 1697 | "find-up": { 1698 | "version": "1.1.2", 1699 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", 1700 | "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", 1701 | "dev": true, 1702 | "requires": { 1703 | "path-exists": "^2.0.0", 1704 | "pinkie-promise": "^2.0.0" 1705 | } 1706 | }, 1707 | "path-exists": { 1708 | "version": "2.1.0", 1709 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", 1710 | "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", 1711 | "dev": true, 1712 | "requires": { 1713 | "pinkie-promise": "^2.0.0" 1714 | } 1715 | } 1716 | } 1717 | }, 1718 | "pluralize": { 1719 | "version": "1.2.1", 1720 | "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-1.2.1.tgz", 1721 | "integrity": "sha1-0aIUg/0iu0HlihL6NCGCMUCJfEU=", 1722 | "dev": true 1723 | }, 1724 | "prelude-ls": { 1725 | "version": "1.1.2", 1726 | "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", 1727 | "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", 1728 | "dev": true 1729 | }, 1730 | "process-nextick-args": { 1731 | "version": "1.0.7", 1732 | "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", 1733 | "integrity": "sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M=" 1734 | }, 1735 | "progress": { 1736 | "version": "1.1.8", 1737 | "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", 1738 | "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", 1739 | "dev": true 1740 | }, 1741 | "readable-stream": { 1742 | "version": "2.2.7", 1743 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.7.tgz", 1744 | "integrity": "sha1-BwV6y+JGeyIELTb5jFrVBwVOlbE=", 1745 | "requires": { 1746 | "buffer-shims": "~1.0.0", 1747 | "core-util-is": "~1.0.0", 1748 | "inherits": "~2.0.1", 1749 | "isarray": "~1.0.0", 1750 | "process-nextick-args": "~1.0.6", 1751 | "string_decoder": "~1.0.0", 1752 | "util-deprecate": "~1.0.1" 1753 | } 1754 | }, 1755 | "readline2": { 1756 | "version": "1.0.1", 1757 | "resolved": "https://registry.npmjs.org/readline2/-/readline2-1.0.1.tgz", 1758 | "integrity": "sha1-QQWWCP/BVHV7cV2ZidGZ/783LjU=", 1759 | "dev": true, 1760 | "requires": { 1761 | "code-point-at": "^1.0.0", 1762 | "is-fullwidth-code-point": "^1.0.0", 1763 | "mute-stream": "0.0.5" 1764 | } 1765 | }, 1766 | "rechoir": { 1767 | "version": "0.6.2", 1768 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 1769 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 1770 | "dev": true, 1771 | "requires": { 1772 | "resolve": "^1.1.6" 1773 | } 1774 | }, 1775 | "regenerator-runtime": { 1776 | "version": "0.11.1", 1777 | "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", 1778 | "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", 1779 | "dev": true 1780 | }, 1781 | "require-all": { 1782 | "version": "2.2.0", 1783 | "resolved": "https://registry.npmjs.org/require-all/-/require-all-2.2.0.tgz", 1784 | "integrity": "sha1-tEIMIzrAKC0P9Jsnf7iAqLXeCJQ=" 1785 | }, 1786 | "require-uncached": { 1787 | "version": "1.0.3", 1788 | "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", 1789 | "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", 1790 | "dev": true, 1791 | "requires": { 1792 | "caller-path": "^0.1.0", 1793 | "resolve-from": "^1.0.0" 1794 | }, 1795 | "dependencies": { 1796 | "resolve-from": { 1797 | "version": "1.0.1", 1798 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", 1799 | "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", 1800 | "dev": true 1801 | } 1802 | } 1803 | }, 1804 | "require_optional": { 1805 | "version": "1.0.1", 1806 | "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", 1807 | "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", 1808 | "requires": { 1809 | "resolve-from": "^2.0.0", 1810 | "semver": "^5.1.0" 1811 | } 1812 | }, 1813 | "resolve": { 1814 | "version": "1.14.2", 1815 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.2.tgz", 1816 | "integrity": "sha512-EjlOBLBO1kxsUxsKjLt7TAECyKW6fOh1VRkykQkKGzcBbjjPIxBqGh0jf7GJ3k/f5mxMqW3htMD3WdTUVtW8HQ==", 1817 | "dev": true, 1818 | "requires": { 1819 | "path-parse": "^1.0.6" 1820 | } 1821 | }, 1822 | "resolve-from": { 1823 | "version": "2.0.0", 1824 | "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", 1825 | "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" 1826 | }, 1827 | "restore-cursor": { 1828 | "version": "1.0.1", 1829 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", 1830 | "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", 1831 | "dev": true, 1832 | "requires": { 1833 | "exit-hook": "^1.0.0", 1834 | "onetime": "^1.0.0" 1835 | } 1836 | }, 1837 | "rimraf": { 1838 | "version": "2.6.3", 1839 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", 1840 | "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", 1841 | "dev": true, 1842 | "requires": { 1843 | "glob": "^7.1.3" 1844 | } 1845 | }, 1846 | "run-async": { 1847 | "version": "0.1.0", 1848 | "resolved": "https://registry.npmjs.org/run-async/-/run-async-0.1.0.tgz", 1849 | "integrity": "sha1-yK1KXhEGYeQCp9IbUw4AnyX444k=", 1850 | "dev": true, 1851 | "requires": { 1852 | "once": "^1.3.0" 1853 | } 1854 | }, 1855 | "rx-lite": { 1856 | "version": "3.1.2", 1857 | "resolved": "https://registry.npmjs.org/rx-lite/-/rx-lite-3.1.2.tgz", 1858 | "integrity": "sha1-Gc5QLKVyZl87ZHsQk5+X/RYV8QI=", 1859 | "dev": true 1860 | }, 1861 | "safe-buffer": { 1862 | "version": "5.1.2", 1863 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", 1864 | "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" 1865 | }, 1866 | "semver": { 1867 | "version": "5.7.1", 1868 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", 1869 | "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" 1870 | }, 1871 | "shelljs": { 1872 | "version": "0.7.8", 1873 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.7.8.tgz", 1874 | "integrity": "sha1-3svPh0sNHl+3LhSxZKloMEjprLM=", 1875 | "dev": true, 1876 | "requires": { 1877 | "glob": "^7.0.0", 1878 | "interpret": "^1.0.0", 1879 | "rechoir": "^0.6.2" 1880 | } 1881 | }, 1882 | "slice-ansi": { 1883 | "version": "0.0.4", 1884 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", 1885 | "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", 1886 | "dev": true 1887 | }, 1888 | "sprintf-js": { 1889 | "version": "1.0.3", 1890 | "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", 1891 | "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", 1892 | "dev": true 1893 | }, 1894 | "string-width": { 1895 | "version": "1.0.2", 1896 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", 1897 | "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", 1898 | "dev": true, 1899 | "requires": { 1900 | "code-point-at": "^1.0.0", 1901 | "is-fullwidth-code-point": "^1.0.0", 1902 | "strip-ansi": "^3.0.0" 1903 | } 1904 | }, 1905 | "string.prototype.trimleft": { 1906 | "version": "2.1.1", 1907 | "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz", 1908 | "integrity": "sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag==", 1909 | "dev": true, 1910 | "requires": { 1911 | "define-properties": "^1.1.3", 1912 | "function-bind": "^1.1.1" 1913 | } 1914 | }, 1915 | "string.prototype.trimright": { 1916 | "version": "2.1.1", 1917 | "resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz", 1918 | "integrity": "sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g==", 1919 | "dev": true, 1920 | "requires": { 1921 | "define-properties": "^1.1.3", 1922 | "function-bind": "^1.1.1" 1923 | } 1924 | }, 1925 | "string_decoder": { 1926 | "version": "1.0.3", 1927 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", 1928 | "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", 1929 | "requires": { 1930 | "safe-buffer": "~5.1.0" 1931 | } 1932 | }, 1933 | "strip-ansi": { 1934 | "version": "3.0.1", 1935 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", 1936 | "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", 1937 | "dev": true, 1938 | "requires": { 1939 | "ansi-regex": "^2.0.0" 1940 | } 1941 | }, 1942 | "strip-bom": { 1943 | "version": "3.0.0", 1944 | "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", 1945 | "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", 1946 | "dev": true 1947 | }, 1948 | "strip-json-comments": { 1949 | "version": "2.0.1", 1950 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", 1951 | "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", 1952 | "dev": true 1953 | }, 1954 | "supports-color": { 1955 | "version": "2.0.0", 1956 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", 1957 | "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", 1958 | "dev": true 1959 | }, 1960 | "t-component": { 1961 | "version": "1.0.0", 1962 | "resolved": "https://registry.npmjs.org/t-component/-/t-component-1.0.0.tgz", 1963 | "integrity": "sha1-LN5aTmLQTNNB/4GXaaXst4vbfpo=" 1964 | }, 1965 | "table": { 1966 | "version": "3.8.3", 1967 | "resolved": "https://registry.npmjs.org/table/-/table-3.8.3.tgz", 1968 | "integrity": "sha1-K7xULw/amGGnVdOUf+/Ys/UThV8=", 1969 | "dev": true, 1970 | "requires": { 1971 | "ajv": "^4.7.0", 1972 | "ajv-keywords": "^1.0.0", 1973 | "chalk": "^1.1.1", 1974 | "lodash": "^4.0.0", 1975 | "slice-ansi": "0.0.4", 1976 | "string-width": "^2.0.0" 1977 | }, 1978 | "dependencies": { 1979 | "ansi-regex": { 1980 | "version": "3.0.0", 1981 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", 1982 | "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", 1983 | "dev": true 1984 | }, 1985 | "is-fullwidth-code-point": { 1986 | "version": "2.0.0", 1987 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", 1988 | "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", 1989 | "dev": true 1990 | }, 1991 | "string-width": { 1992 | "version": "2.1.1", 1993 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", 1994 | "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", 1995 | "dev": true, 1996 | "requires": { 1997 | "is-fullwidth-code-point": "^2.0.0", 1998 | "strip-ansi": "^4.0.0" 1999 | } 2000 | }, 2001 | "strip-ansi": { 2002 | "version": "4.0.0", 2003 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", 2004 | "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", 2005 | "dev": true, 2006 | "requires": { 2007 | "ansi-regex": "^3.0.0" 2008 | } 2009 | } 2010 | } 2011 | }, 2012 | "text-table": { 2013 | "version": "0.2.0", 2014 | "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", 2015 | "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", 2016 | "dev": true 2017 | }, 2018 | "through": { 2019 | "version": "2.3.8", 2020 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2021 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", 2022 | "dev": true 2023 | }, 2024 | "to-fast-properties": { 2025 | "version": "1.0.3", 2026 | "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", 2027 | "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", 2028 | "dev": true 2029 | }, 2030 | "type": { 2031 | "version": "1.2.0", 2032 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 2033 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", 2034 | "dev": true 2035 | }, 2036 | "type-check": { 2037 | "version": "0.3.2", 2038 | "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", 2039 | "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", 2040 | "dev": true, 2041 | "requires": { 2042 | "prelude-ls": "~1.1.2" 2043 | } 2044 | }, 2045 | "type-detect": { 2046 | "version": "4.0.8", 2047 | "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", 2048 | "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", 2049 | "dev": true 2050 | }, 2051 | "typedarray": { 2052 | "version": "0.0.6", 2053 | "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", 2054 | "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", 2055 | "dev": true 2056 | }, 2057 | "user-home": { 2058 | "version": "2.0.0", 2059 | "resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz", 2060 | "integrity": "sha1-nHC/2Babwdy/SGBODwS4tJzenp8=", 2061 | "dev": true, 2062 | "requires": { 2063 | "os-homedir": "^1.0.0" 2064 | } 2065 | }, 2066 | "util-deprecate": { 2067 | "version": "1.0.2", 2068 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 2069 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 2070 | }, 2071 | "word-wrap": { 2072 | "version": "1.2.3", 2073 | "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", 2074 | "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", 2075 | "dev": true 2076 | }, 2077 | "wrappy": { 2078 | "version": "1.0.2", 2079 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 2080 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", 2081 | "dev": true 2082 | }, 2083 | "write": { 2084 | "version": "0.2.1", 2085 | "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", 2086 | "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", 2087 | "dev": true, 2088 | "requires": { 2089 | "mkdirp": "^0.5.1" 2090 | } 2091 | }, 2092 | "xtend": { 2093 | "version": "4.0.2", 2094 | "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", 2095 | "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", 2096 | "dev": true 2097 | } 2098 | } 2099 | } 2100 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "democracyos-notifier", 3 | "version": "2.1.4", 4 | "description": "Notifications engine with job queuing and scheduling backed by MongoDB.", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "mocha" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/DemocracyOS/notifier.git" 12 | }, 13 | "keywords": [ 14 | "notifier", 15 | "democracyos", 16 | "notifiations", 17 | "email" 18 | ], 19 | "author": "Democracia en Red (http://democraciaenred.org/)", 20 | "license": "MIT", 21 | "bugs": { 22 | "url": "https://github.com/DemocracyOS/notifier/issues" 23 | }, 24 | "homepage": "https://github.com/DemocracyOS/notifier", 25 | "dependencies": { 26 | "agenda": "~0.9.0", 27 | "debug": "~2.6.0", 28 | "defaults-deep": "0.2.4", 29 | "es6-string-html-template": "~1.0.2", 30 | "mongodb": "~2.2.28", 31 | "monk": "~6.0.0", 32 | "nodemailer": "~4.0.1", 33 | "pify": "~3.0.0", 34 | "require-all": "~2.2.0", 35 | "t-component": "1.0.0" 36 | }, 37 | "devDependencies": { 38 | "chai": "~4.0.2", 39 | "eslint": "~3.19.0", 40 | "eslint-config-democracyos": "~1.2.1", 41 | "mocha": "~3.4.2" 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | const chai = require('chai') 2 | 3 | const expect = chai.expect 4 | 5 | chai.should() 6 | 7 | const db = 'mongodb://localhost/notifier-test' 8 | 9 | describe('notifier', function () { 10 | it('should be properly initialised with its default values', function (done) { 11 | var notifier = require('../') 12 | notifier({ mongoUrl: db }, function () { 13 | expect(notifier.notify).to.be.a('function') 14 | done() 15 | }) 16 | }) 17 | }) 18 | 19 | describe('jobs', function () { 20 | // TODO: write tests for jobs module 21 | }) 22 | 23 | describe('templates', function () { 24 | // TODO: write tests for templates module 25 | }) 26 | 27 | describe('utils', function () { 28 | describe('.name.format()', function () { 29 | it('should generate full name based on presence of firstName and lastName props', function () { 30 | var name = require('../lib/utils/name').format 31 | 32 | expect(name({ firstName: 'bob' })).to.eql('bob') 33 | expect(name({ firstName: 'bob', lastName: 'builder' })).to.eql('bob builder') 34 | }) 35 | 36 | // unsure if checks are made elsewhere 37 | /* 38 | it("should throw exception on invalid input", function() { 39 | expect(function() { 40 | name({last_name: "builder"}); 41 | }).to.throw(Error); 42 | }) 43 | */ 44 | }) 45 | }) 46 | 47 | describe('translations', function () { 48 | var t = require('../lib/translations').t 49 | t.test = { 50 | 'templates.email.greeting': 'Hi, {USER_NAME},', 51 | 'templates.email.signature': 'The DemocracyOS team.' 52 | } 53 | 54 | t.test2 = { 55 | 'templates.email.greeting': 'Bonjour, {USER_NAME},', 56 | 'templates.email.signature': "L'équipe de DemocracyOS." 57 | } 58 | 59 | it('should return linguistic version of prop', function () { 60 | expect(t('templates.email.signature', 'test')).to.eql('The DemocracyOS team.') 61 | expect(t('templates.email.signature', 'test2')).to.eql("L'équipe de DemocracyOS.") 62 | }) 63 | 64 | it('should return placeholders as-is if no props match', function () { 65 | expect(t('templates.email.greeting', 'test')).to.eql('Hi, {USER_NAME},') 66 | expect(t('templates.email.greeting', 'test2')).to.eql('Bonjour, {USER_NAME},') 67 | 68 | expect(t('templates.email.greeting', { user: 'bobby' }, 'test')).to.eql('Hi, {USER_NAME},') 69 | expect(t('templates.email.greeting', { user: 'bobby' }, 'test2')).to.eql('Bonjour, {USER_NAME},') 70 | }) 71 | 72 | it('should swap placeholders with prop values', function () { 73 | expect(t('templates.email.greeting', { USER_NAME: 'Bob the builder' }, 'test')).to.eql('Hi, Bob the builder,') 74 | expect(t('templates.email.greeting', { USER_NAME: 'Bob the builder' }, 'test2')).to.eql('Bonjour, Bob the builder,') 75 | }) 76 | }) 77 | --------------------------------------------------------------------------------