From d7a33ef14935ccf7fa5ee8e71e1fe68df170c98d Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sat, 9 Mar 2019 18:57:30 -0800 Subject: linting --- index.js | 379 +++++++++++++++++++++++++++++++++++++---------------------- package.json | 6 + yarn.lock | 251 ++++++++++++++++++++++++++++++++++++++- 3 files changed, 487 insertions(+), 149 deletions(-) diff --git a/index.js b/index.js index bac5a534..36a0a38a 100644 --- a/index.js +++ b/index.js @@ -6,9 +6,8 @@ import bodyParser from 'body-parser' import bolt11 from 'bolt11' import compression from 'compression' import cookieParser from 'cookie-parser' -import core from 'bitcoin-core' +import BitcoinCore from 'bitcoin-core' import cors from 'cors' -import crypto from 'crypto-js' import express from 'express' import fb from 'fb' import fs from 'fs' @@ -28,10 +27,10 @@ import config from './config' import whitelist from './whitelist' const l = console.log -const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {}) -const authy = new Client({ key: config.authy.key }) - -;(async () => { +/* eslint-disable-next-line */ +const pick = (O, ...K) => K.reduce((o, k) => ((o[k] = O[k]), o), {}) +const authy = new Client({ key: config.authy.key }); +(async () => { const ln = async ({ server, tls, macaroon, channelpeers }) => { const ln = await require('lnrpc')({ server, tls }) ln.meta = new grpc.Metadata() @@ -43,7 +42,7 @@ const authy = new Client({ key: config.authy.key }) const lna = await ln(config.lna) const lnb = await ln(config.lnb) - const bc = new core(config.bitcoin) + const bc = new BitcoinCore(config.bitcoin) const app = express() app.enable('trust proxy') @@ -64,33 +63,41 @@ const authy = new Client({ key: config.authy.key }) app.use(passport.initialize()) - app.use('/graphql', auth, graphqlHTTP({ - schema: db.gqlschema, - graphiql: true - })) + app.use( + '/graphql', + auth, + graphqlHTTP({ + schema: db.gqlschema, + graphiql: true, + }) + ) socket.use((socket, next) => { try { let token = socket.handshake.query.token let user = jwt.decode(token).username socket.request.user = user - sids[user] ? sids[user].push(socket.id) : sids[user] = [socket.id] + sids[user] ? sids[user].push(socket.id) : (sids[user] = [socket.id]) sids[socket.id] = user - } catch (e) { l(e) } + } catch (e) { + l(e) + } next() }) socket.sockets.on('connect', async socket => { socket.emit('connected') - if (app.get('rates')) - socket.emit('rate', app.get('rates').ask) + if (app.get('rates')) socket.emit('rate', app.get('rates').ask) socket.on('getuser', async (data, callback) => { - callback(await db.User.findOne({ - where: { - username: socket.request.user, - } - })); - }); + /* eslint-disable-next-line */ + callback( + await db.User.findOne({ + where: { + username: socket.request.user, + }, + }) + ) + }) socket.on('disconnect', s => { let user = sids[socket.id] @@ -108,9 +115,9 @@ const authy = new Client({ key: config.authy.key }) socket.to(sid).emit(msg, data) } catch (e) { sids[username].splice(i, 1) - } + } }) - } + } const handlePayment = async msg => { if (!msg.settled) return @@ -118,8 +125,8 @@ const authy = new Client({ key: config.authy.key }) let payment = await db.Payment.findOne({ include: { model: db.User, as: 'user' }, where: { - hash: msg.payment_request - } + hash: msg.payment_request, + }, }) if (!payment) return @@ -131,10 +138,10 @@ const authy = new Client({ key: config.authy.key }) await payment.save() await payment.user.save() payments.push(msg.payment_request) - + emit(payment.user.username, 'invoice', msg) emit(payment.user.username, 'user', payment.user) - } + } const invoices = lna.subscribeInvoices({}) invoices.on('data', handlePayment) @@ -153,10 +160,12 @@ const authy = new Client({ key: config.authy.key }) const addresses = {} await db.User.findAll({ attributes: ['username', 'address'], - }).map(u => { addresses[u.address] = u.username }) + }).map(u => { + addresses[u.address] = u.username + }) - const payments = (await db.Payment.findAll({ - attributes: ['hash'] + const payments = (await db.Payment.findAll({ + attributes: ['hash'], })).map(p => p.hash) zmqRawTx.on('message', async (topic, message, sequence) => { @@ -166,17 +175,17 @@ const authy = new Client({ key: config.authy.key }) let hash = reverse(tx.getHash()).toString('hex') if (payments.includes(hash)) return - let total = tx.outs.reduce((a, b) => a + b.value, 0) + tx.outs.map(async o => { try { let network = config.bitcoin.network if (network === 'mainnet') { network = 'bitcoin' - } + } let address = bitcoin.address.fromOutputScript( - o.script, - bitcoin.networks[network], + o.script, + bitcoin.networks[network] ) if (Object.keys(addresses).includes(address)) { @@ -186,7 +195,7 @@ const authy = new Client({ key: config.authy.key }) let user = await db.User.findOne({ where: { username: addresses[address], - } + }, }) let invoices = await db.Payment.findAll({ @@ -195,10 +204,10 @@ const authy = new Client({ key: config.authy.key }) hash: address, received: null, amount: { - [Sequelize.Op.gt]: 0 - } + [Sequelize.Op.gt]: 0, + }, }, - order: [ [ 'createdAt', 'DESC' ]] + order: [['createdAt', 'DESC']], }) let tip = null @@ -215,7 +224,7 @@ const authy = new Client({ key: config.authy.key }) await user.save() emit(user.username, 'user', user) - + await db.Payment.create({ user_id: user.id, hash, @@ -228,9 +237,11 @@ const authy = new Client({ key: config.authy.key }) }) emit(user.username, 'tx', message) - } catch (e) { l(e) } - } - } catch(e) {} + } catch (e) { + l(e) + } + } + } catch (e) {} }) }) @@ -252,15 +263,15 @@ const authy = new Client({ key: config.authy.key }) p.confirmed = true user.balance += p.amount user.pending -= p.amount - await user.save() + await user.save() await p.save() emit(user.username, 'user', user) } }) - + socket.emit('block', message) break - } + } } }) @@ -282,34 +293,43 @@ const authy = new Client({ key: config.authy.key }) res.send(pick(user, ...whitelist)) }) - const requestEmail = async (user) => { + const requestEmail = async user => { user.emailToken = uuidv4() - await user.save() + await user.save() let mg = mailgun(config.mailgun) let msg = { from: 'CoinOS ', to: user.email, subject: 'CoinOS Email Verification', - html: `Visit https://coinos.io/verify/${user.username}/${user.emailToken} to verify your email address.` + html: `Visit https://coinos.io/verify/${user.username}/${ + user.emailToken + } to verify your email address.`, } try { mg.messages().send(msg) - } catch (e) { l(e) } - } + } catch (e) { + l(e) + } + } - const requestPhone = async (user) => { + const requestPhone = async user => { user.phoneToken = Math.floor(100000 + Math.random() * 900000) - await user.save() - const client = require('twilio')(config.twilio.sid, config.twilio.authToken); + await user.save() + const client = require('twilio')( + config.twilio.sid, + config.twilio.authToken + ) await client.messages.create({ - body: user.phoneToken, - from: config.twilio.number, - to: user.phone, - }) - } + body: user.phoneToken, + from: config.twilio.number, + to: user.phone, + }) + } app.post('/requestEmail', auth, async (req, res) => { req.user.email = req.body.email @@ -325,16 +345,24 @@ const authy = new Client({ key: config.authy.key }) app.post('/user', auth, async (req, res) => { let { user } = req - let { email, phone, twofa, pin, pinconfirm, password, passconfirm } = req.body - - if (user.email !== email && require("email-validator").validate(email)) { + let { + email, + phone, + twofa, + pin, + pinconfirm, + password, + passconfirm, + } = req.body + + if (user.email !== email && require('email-validator').validate(email)) { user.email = email user.emailVerified = false requestEmail(user) } if (user.phone !== phone) { - user.phone = phone + user.phone = phone user.phoneVerified = false requestPhone(user) } @@ -343,18 +371,24 @@ const authy = new Client({ key: config.authy.key }) user.phone = phone user.twofa = twofa - if (password && password === passconfirm) + console.log(user.twofa, email, phone) + + if (password && password === passconfirm) { user.password = await bcrypt.hash(password, 1) + } - if (pin && pin === pinconfirm) - user.pin = await bcrypt.hash(pin, 1) + if (pin && pin === pinconfirm) user.pin = await bcrypt.hash(pin, 1) if (twofa && !user.authyId && user.phoneVerified) { - let r = await authy.registerUser({ countryCode: 'CA', email, phone }) - user.authyId = r.user.id + try { + let r = await authy.registerUser({ countryCode: 'CA', email, phone }) + user.authyId = r.user.id + } catch (e) { + l(e) + } } - await user.save() + await user.save() emit(req.user.username, 'user', req.user) res.send(user) }) @@ -365,15 +399,20 @@ const authy = new Client({ key: config.authy.key }) from: 'CoinOS ', to: user.email, subject: 'CoinOS Password Reset', - html: `Visit https://localhost/reset/${user.username}/${user.token} to reset your password.` + html: `Visit https://localhost/reset/${user.username}/${ + user.token + } to reset your password.`, } }) app.get('/verifyEmail/:username/:token', auth, async (req, res) => { let user = await db.User.findOne({ where: { - username: req.params.username - } + username: req.params.username, + emailToken: req.params.token, + }, }) if (user) { @@ -382,54 +421,66 @@ const authy = new Client({ key: config.authy.key }) emit(user.username, 'user', user) emit(user.username, 'emailVerified', true) - } - res.end() + res.end() + } else { + res.status(500).send('invalid token or username') + } }) app.get('/verifyPhone/:username/:token', auth, async (req, res) => { let user = await db.User.findOne({ where: { - username: req.params.username - } + username: req.params.username, + phoneToken: req.params.token, + }, }) + console.log(user, req.params) + if (user) { user.phoneVerified = true await user.save() emit(user.username, 'user', user) emit(user.username, 'phoneVerified', true) + res.end() + } else { + res.status(500).send('invalid token or username') } - - res.end() }) app.post('/openchannel', auth, async (req, res) => { let err = m => res.status(500).send(m) - if (req.user.balance < 10000) return err('Need at least 10000 satoshis for channel opening') + if (req.user.balance < 10000) { + return err('Need at least 10000 satoshis for channel opening') + } let pending = await lna.pendingChannels({}, lna.meta) - let busypeers = pending.pending_open_channels.map(c => c.channel.remote_node_pub) + let busypeers = pending.pending_open_channels.map( + c => c.channel.remote_node_pub + ) let peer = lna.channelpeers.find(p => !busypeers.includes(p)) let sent = false l('channeling') - + if (!peer) { - res.status(500).send('All peers have pending channel requests, try again later') + res + .status(500) + .send('All peers have pending channel requests, try again later') return } - + try { let amount = Math.min(req.user.balance, 16777216) - + let openchannel = async (peer, amount) => { let channel = await lna.openChannel({ node_pubkey: new Buffer(peer, 'hex'), local_funding_amount: amount, }) - + channel.on('data', async data => { if (sent || !data.chan_pending) return req.user.balance += amount @@ -445,19 +496,27 @@ const authy = new Client({ key: config.authy.key }) l('channel error', peer, err) let msg = err.message - if (msg.startsWith('Multiple') || msg.startsWith('You gave') || msg.startsWith('peer')) { + if ( + msg.startsWith('Multiple') || + msg.startsWith('You gave') || + msg.startsWith('peer') + ) { busypeers.push(peer) peer = lna.channelpeers.find(p => !busypeers.includes(p)) if (peer) { return openchannel(peer, amount) } else { - return res.status(500).send('All peers are busy, couldn\'t open a channel, wait a few blocks and try again') - } - } + return res + .status(500) + .send( + "All peers are busy, couldn't open a channel, wait a few blocks and try again" + ) + } + } if (msg.startsWith('not enough')) { msg = 'Server wallet is busy. Wait for a block and try again' - } + } return res.status(500).send(msg) }) @@ -467,7 +526,7 @@ const authy = new Client({ key: config.authy.key }) } catch (err) { l('rpc error', peer, err) return res.status(500).send(err) - } + } }) app.get('/channels', auth, async (req, res) => { @@ -483,13 +542,13 @@ const authy = new Client({ key: config.authy.key }) let payreq = bolt11.decode(hash) if (seen.includes(hash)) { - return res.status(500).send('Invoice has been paid, can\'t pay again') - } + return res.status(500).send("Invoice has been paid, can't pay again") + } if (req.user.balance < payreq.satoshis) { return res.status(500).send('Not enough satoshis') - } - + } + const stream = lna.sendPayment(lna.meta, {}) stream.write({ payment_request: req.body.payreq }) @@ -517,7 +576,9 @@ const authy = new Client({ key: config.authy.key }) if (payreq.payeeNodeKey === config.lnb.id) { let invoice = await lna.addInvoice({ value: payreq.satoshis }) let payback = lnb.sendPayment(lnb.meta, {}) + /* eslint-disable-next-line */ let { payment_request } = invoice + /* eslint-disable-next-line */ payback.write({ payment_request }) } @@ -531,33 +592,47 @@ const authy = new Client({ key: config.authy.key }) res.status(500).send(msg) }) - }) + }) app.get('/friends', auth, async (req, res) => { try { - let friends = (await fb.api(`/${req.user.username}/friends?access_token=${req.user.fbtoken}`)).data - friends = await Promise.all(friends.map(async f => { - let pic = (await fb.api(`/${f.id}/picture?redirect=false&type=small&access_token=${req.user.fbtoken}`)).data - f.pic = pic.url - return f - })) + let friends = (await fb.api( + `/${req.user.username}/friends?access_token=${req.user.fbtoken}` + )).data + friends = await Promise.all( + friends.map(async f => { + let pic = (await fb.api( + `/${f.id}/picture?redirect=false&type=small&access_token=${ + req.user.fbtoken + }` + )).data + f.pic = pic.url + return f + }) + ) res.send(friends) } catch (e) { - res.status(500).send('There was a problem getting your facebook friends: ', e) + res + .status(500) + .send('There was a problem getting your facebook friends: ', e) } - }) + }) app.post('/payUser', auth, async (req, res) => { let { payuser, amount } = req.body let user = await db.User.findOne({ where: { - username: payuser - } + username: payuser, + }, }) - if (!user) return res.status(401).send("Couldn't find the user you're trying to pay") + if (!user) { + return res + .status(401) + .send("Couldn't find the user you're trying to pay") + } let err = m => res.status(500).send(m) let invoice @@ -565,10 +640,10 @@ const authy = new Client({ key: config.authy.key }) invoice = await lnb.addInvoice({ value: amount }) } catch (e) { return err(e.message) - } + } let hash = invoice.payment_request - + await db.Payment.create({ user_id: user.id, hash, @@ -590,24 +665,28 @@ const authy = new Client({ key: config.authy.key }) if (amount === req.user.balance) { amount = req.user.balance - MINFEE - } + } - if (amount > req.user.balance) + if (amount > req.user.balance) { return res.status(401).send('Insufficient funds') + } try { await bc.walletPassphrase(config.bitcoin.walletpass, 300) - let txid = await bc.sendToAddress(address, (amount / 100000000).toFixed(8)) + let txid = await bc.sendToAddress( + address, + (amount / 100000000).toFixed(8) + ) let txhex = await bc.getRawTransaction(txid) let tx = bitcoin.Transaction.fromHex(txhex) - let input_total = await tx.ins.reduce(async (a, input) => { + let inputTotal = await tx.ins.reduce(async (a, input) => { let h = await bc.getRawTransaction(reverse(input.hash).toString('hex')) return a + bitcoin.Transaction.fromHex(h).outs[input.index].value }, 0) - let output_total = tx.outs.reduce((a, b) => a + b.value, 0) + let outputTotal = tx.outs.reduce((a, b) => a + b.value, 0) - let fees = input_total - output_total + let fees = inputTotal - outputTotal let total = Math.min(parseInt(amount) + fees, req.user.balance) req.user.balance -= total await req.user.save() @@ -625,8 +704,8 @@ const authy = new Client({ key: config.authy.key }) } catch (e) { l(e) res.status(500).send(e.message) - } - }) + } + }) app.post('/addInvoice', auth, async (req, res) => { let err = m => res.status(500).send(m) @@ -637,11 +716,11 @@ const authy = new Client({ key: config.authy.key }) invoice = await lnb.addInvoice({ value: amount }) } catch (e) { return err(e.message) - } + } let hash = invoice.payment_request if (address) hash = address - + await db.Payment.create({ user_id: req.user.id, hash, @@ -654,17 +733,21 @@ const authy = new Client({ key: config.authy.key }) res.send(invoice) }) - let fetchRates + let fetchRates; (fetchRates = async () => { try { - let res = await axios.get('https://api.kraken.com/0/public/Ticker?pair=XBTCAD') + let res = await axios.get( + 'https://api.kraken.com/0/public/Ticker?pair=XBTCAD' + ) let ask = res.data.result.XXBTZCAD.c[0] let now = new Date() let ts = `${now.getHours()}:${now.getMinutes()}:${now.getSeconds()}` l(ts, 'ask price:', ask) app.set('rates', { ask }) socket.emit('rate', ask) - } catch (e) { l(e) } + } catch (e) { + l(e) + } setTimeout(fetchRates, 3000) })() @@ -677,15 +760,17 @@ const authy = new Client({ key: config.authy.key }) try { let user = await db.User.findOne({ where: { - username: req.body.username - } + username: req.body.username, + }, }) if ( - !user || - !(await bcrypt.compare(req.body.password, user.password)) || + !user || + !(await bcrypt.compare(req.body.password, user.password)) || (user.twofa && !(await authyVerify(user))) - ) return res.status(401).end() + ) { + return res.status(401).end() + } let payload = { username: user.username } let token = jwt.sign(payload, config.jwt) @@ -693,7 +778,7 @@ const authy = new Client({ key: config.authy.key }) user = pick(user, ...whitelist) res.send({ user, token }) - } catch(err) { + } catch (err) { res.status(401).end() } }) @@ -701,35 +786,41 @@ const authy = new Client({ key: config.authy.key }) app.post('/facebookLogin', async (req, res) => { let { accessToken, userID } = req.body - let url = `https://graph.facebook.com/debug_token?input_token=${accessToken}&access_token=${config.facebook.appToken}` + let url = `https://graph.facebook.com/debug_token?input_token=${accessToken}&access_token=${ + config.facebook.appToken + }` let check = await axios.get(url) if (!check.data.data.is_valid) return res.status(401).end() try { let user = await db.User.findOne({ where: { - username: req.body.userID - } + username: req.body.userID, + }, }) if (!user) { user = await db.User.create(user) user.username = userID user.name = (await fb.api(`/me?access_token=${accessToken}`)).name - user.pic = (await fb.api(`/me/picture?access_token=${accessToken}&redirect=false`)).data.url + user.pic = (await fb.api( + `/me/picture?access_token=${accessToken}&redirect=false` + )).data.url user.fbtoken = accessToken user.address = (await lna.newAddress({ type: 1 }, lna.meta)).address user.password = await bcrypt.hash(accessToken, 1) user.balance = 0 user.pending = 0 - let friends = (await fb.api(`/${userID}/friends?access_token=${accessToken}`)).data + let friends = (await fb.api( + `/${userID}/friends?access_token=${accessToken}` + )).data if (friends.find(f => f.id === config.facebook.specialFriend)) { user.friend = true user.limit = 200 } await user.save() addresses[user.address] = user.username - } + } user.fbtoken = accessToken await user.save() @@ -740,15 +831,15 @@ const authy = new Client({ key: config.authy.key }) let token = jwt.sign(payload, config.jwt) res.cookie('token', token, { expires: new Date(Date.now() + 432000000) }) res.send({ user, token }) - } catch(err) { + } catch (err) { l(err) res.status(401).end() } }) app.post('/buy', auth, async (req, res) => { - const stripe = require('stripe')(config.stripe); - const { token, amount, sat } = req.body + const stripe = require('stripe')(config.stripe) + const { token, amount, sats } = req.body let dollarAmount = parseInt(amount / 100) if (dollarAmount > req.user.limit) return res.status(401).end() @@ -761,7 +852,7 @@ const authy = new Client({ key: config.authy.key }) source: token, }) - req.user.balance += parseInt(sat) + req.user.balance += parseInt(sats) req.user.limit -= dollarAmount await req.user.save() emit(req.user.username, 'user', req.user) @@ -769,18 +860,18 @@ const authy = new Client({ key: config.authy.key }) await db.Payment.create({ user_id: req.user.id, hash: charge.balance_transaction, - amount: parseInt(sat), + amount: parseInt(sats), currency: 'CAD', rate: app.get('rates').ask, received: true, - tip: 0 + tip: 0, }) res.send(`Bought ${amount}`) } catch (e) { - console.log(e); + console.log(e) res.status(500).send(e) - } + } }) app.post('/order', auth, async (req, res) => { @@ -792,8 +883,10 @@ const authy = new Client({ key: config.authy.key }) }) }) - app.get('/me', async(req, res) => { - let data = (await fb.api('/me/picture?access_token=EAAEIFqWk3ZAwBAEUfxQdH3T5CBKXmU8d7jQ5OTJBJZBiU1ZAp76lO26nh57WolM4R4JoKks9BCc49s8VrlEm2Ub1GlZCEzVD9fGxzUiranXDErDmR5gDUPKX3BhCsGA649a4hmbldRwKFTsmZCGZCergm9ACspKdTZB0WgFgA9wEdemIRIXuwCygNrymmKDh0Wd8nmoT4Hj3wZDZD&redirect=false')).data + app.get('/me', async (req, res) => { + let data = (await fb.api( + '/me/picture?access_token=EAAEIFqWk3ZAwBAEUfxQdH3T5CBKXmU8d7jQ5OTJBJZBiU1ZAp76lO26nh57WolM4R4JoKks9BCc49s8VrlEm2Ub1GlZCEzVD9fGxzUiranXDErDmR5gDUPKX3BhCsGA649a4hmbldRwKFTsmZCGZCergm9ACspKdTZB0WgFgA9wEdemIRIXuwCygNrymmKDh0Wd8nmoT4Hj3wZDZD&redirect=false' + )).data res.send(data.url) }) diff --git a/package.json b/package.json index 6c8fa81f..081b3afd 100644 --- a/package.json +++ b/package.json @@ -74,8 +74,14 @@ "zeromq": "^4.6.0" }, "devDependencies": { + "babel-eslint": "^10.0.1", "babel-preset-es2015": "^6.24.1", + "eslint-config-standard": "^12.0.0", "eslint-plugin-html": "^5.0.0", + "eslint-plugin-import": "^2.16.0", + "eslint-plugin-node": "^8.0.1", + "eslint-plugin-promise": "^4.0.1", + "eslint-plugin-standard": "^4.0.0", "pm2": "^2.10.4" } } diff --git a/yarn.lock b/yarn.lock index 80fffb08..ee71be5e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,94 @@ # yarn lockfile v1 +"@babel/code-frame@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.0.0.tgz#06e2ab19bdb535385559aabb5ba59729482800f8" + integrity sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/generator@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.3.4.tgz#9aa48c1989257877a9d971296e5b73bfe72e446e" + integrity sha512-8EXhHRFqlVVWXPezBW5keTiQi/rJMQTg/Y9uVCEZ0CAF3PKtCCaVRnp64Ii1ujhkoDhhF1fVsImoN4yJ2uz4Wg== + dependencies: + "@babel/types" "^7.3.4" + jsesc "^2.5.1" + lodash "^4.17.11" + source-map "^0.5.0" + trim-right "^1.0.1" + +"@babel/helper-function-name@^7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.1.0.tgz#a0ceb01685f73355d4360c1247f582bfafc8ff53" + integrity sha512-A95XEoCpb3TO+KZzJ4S/5uW5fNe26DjBGqf1o9ucyLyCmi1dXq/B3c8iaWTfBk3VvetUxl16e8tIrd5teOCfGw== + dependencies: + "@babel/helper-get-function-arity" "^7.0.0" + "@babel/template" "^7.1.0" + "@babel/types" "^7.0.0" + +"@babel/helper-get-function-arity@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.0.0.tgz#83572d4320e2a4657263734113c42868b64e49c3" + integrity sha512-r2DbJeg4svYvt3HOS74U4eWKsUAMRH01Z1ds1zx8KNTPtpTL5JAsdFv8BNyOpVqdFhHkkRDIg5B4AsxmkjAlmQ== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/helper-split-export-declaration@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.0.0.tgz#3aae285c0311c2ab095d997b8c9a94cad547d813" + integrity sha512-MXkOJqva62dfC0w85mEf/LucPPS/1+04nmmRMPEBUB++hiiThQ2zPtX/mEWQ3mtzCEjIJvPY8nuwxXtQeQwUag== + dependencies: + "@babel/types" "^7.0.0" + +"@babel/highlight@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.0.0.tgz#f710c38c8d458e6dd9a201afb637fcb781ce99e4" + integrity sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.0.0", "@babel/parser@^7.2.2", "@babel/parser@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.3.4.tgz#a43357e4bbf4b92a437fb9e465c192848287f27c" + integrity sha512-tXZCqWtlOOP4wgCp6RjRvLmfuhnqTLy9VHwRochJBCP2nDm27JnnuFEnXFASVyQNHk36jD1tAammsCEEqgscIQ== + +"@babel/template@^7.1.0": + version "7.2.2" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.2.2.tgz#005b3fdf0ed96e88041330379e0da9a708eb2907" + integrity sha512-zRL0IMM02AUDwghf5LMSSDEz7sBCO2YnNmpg3uWTZj/v1rcG2BmQUvaGU8GhU8BvfMh1k2KIAYZ7Ji9KXPUg7g== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.2.2" + "@babel/types" "^7.2.2" + +"@babel/traverse@^7.0.0": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.3.4.tgz#1330aab72234f8dea091b08c4f8b9d05c7119e06" + integrity sha512-TvTHKp6471OYEcE/91uWmhR6PrrYywQntCHSaZ8CM8Vmp+pjAusal4nGB2WCCQd0rvI7nOMKn9GnbcvTUz3/ZQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/generator" "^7.3.4" + "@babel/helper-function-name" "^7.1.0" + "@babel/helper-split-export-declaration" "^7.0.0" + "@babel/parser" "^7.3.4" + "@babel/types" "^7.3.4" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.11" + +"@babel/types@^7.0.0", "@babel/types@^7.2.2", "@babel/types@^7.3.4": + version "7.3.4" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.3.4.tgz#bf482eaeaffb367a28abbf9357a94963235d90ed" + integrity sha512-WEkp8MsLftM7O/ty580wAmZzN1nDmCACc5+jFzUt+GUFNNIi3LdRlueYz0YIlmJhlZx1QYDMZL5vdWCL0fNjFQ== + dependencies: + esutils "^2.0.2" + lodash "^4.17.11" + to-fast-properties "^2.0.0" + "@types/body-parser@*": version "1.17.0" resolved "https://registry.yarnpkg.com/@types/body-parser/-/body-parser-1.17.0.tgz#9f5c9d9bd04bb54be32d5eb9fc0d8c974e6cf58c" @@ -623,6 +711,18 @@ babel-core@^6.26.0: slash "^1.0.0" source-map "^0.5.6" +babel-eslint@^10.0.1: + version "10.0.1" + resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.0.1.tgz#919681dc099614cd7d31d45c8908695092a1faed" + integrity sha512-z7OT1iNV+TjOwHNLLyJk+HN+YVWX+CLE6fPD2SymJZOZQBs+QIexFjhm4keGTm8MW9xr4EC9Q0PbaLB24V5GoQ== + dependencies: + "@babel/code-frame" "^7.0.0" + "@babel/parser" "^7.0.0" + "@babel/traverse" "^7.0.0" + "@babel/types" "^7.0.0" + eslint-scope "3.7.1" + eslint-visitor-keys "^1.0.0" + babel-generator@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.0.tgz#ac1ae20070b79f6e3ca1d3269613053774f20dc5" @@ -2091,6 +2191,11 @@ consolidate@0.14.1: dependencies: bluebird "^3.1.1" +contains-path@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" + integrity sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo= + content-disposition@0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.1.tgz#87476c6a67c8daa87e32e87616df883ba7fb071b" @@ -2514,6 +2619,14 @@ dev-ip@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0" +doctrine@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-1.5.0.tgz#379dce730f6166f76cefa4e6707a159b02c5a6fa" + integrity sha1-N53Ocw9hZvds76TmcHoVmwLFpvo= + dependencies: + esutils "^2.0.2" + isarray "^1.0.0" + doctrine@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" @@ -2886,6 +2999,35 @@ escodegen@1.x.x: optionalDependencies: source-map "~0.6.1" +eslint-config-standard@^12.0.0: + version "12.0.0" + resolved "https://registry.yarnpkg.com/eslint-config-standard/-/eslint-config-standard-12.0.0.tgz#638b4c65db0bd5a41319f96bba1f15ddad2107d9" + integrity sha512-COUz8FnXhqFitYj4DTqHzidjIL/t4mumGZto5c7DrBpvWoie+Sn3P4sLEzUGeYhRElWuFEf8K1S1EfvD1vixCQ== + +eslint-import-resolver-node@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.2.tgz#58f15fb839b8d0576ca980413476aab2472db66a" + integrity sha512-sfmTqJfPSizWu4aymbPr4Iidp5yKm8yDkHp+Ir3YiTHiiDfxh69mOUsmiqW6RZ9zRXFaF64GtYmN7e+8GHBv6Q== + dependencies: + debug "^2.6.9" + resolve "^1.5.0" + +eslint-module-utils@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz#546178dab5e046c8b562bbb50705e2456d7bda49" + integrity sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w== + dependencies: + debug "^2.6.8" + pkg-dir "^2.0.0" + +eslint-plugin-es@^1.3.1: + version "1.4.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-es/-/eslint-plugin-es-1.4.0.tgz#475f65bb20c993fc10e8c8fe77d1d60068072da6" + integrity sha512-XfFmgFdIUDgvaRAlaXUkxrRg5JSADoRC8IkKLc/cISeR3yHVMefFHQZpcyXXEUUPHfy5DwviBcrfqlyqEwlQVw== + dependencies: + eslint-utils "^1.3.0" + regexpp "^2.0.1" + eslint-plugin-html@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/eslint-plugin-html/-/eslint-plugin-html-5.0.0.tgz#396e30a60dedee0122fe08f11d13c5ab22f20d32" @@ -2893,13 +3035,56 @@ eslint-plugin-html@^5.0.0: dependencies: htmlparser2 "^3.10.0" -eslint-scope@^3.7.1: +eslint-plugin-import@^2.16.0: + version "2.16.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz#97ac3e75d0791c4fac0e15ef388510217be7f66f" + integrity sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A== + dependencies: + contains-path "^0.1.0" + debug "^2.6.9" + doctrine "1.5.0" + eslint-import-resolver-node "^0.3.2" + eslint-module-utils "^2.3.0" + has "^1.0.3" + lodash "^4.17.11" + minimatch "^3.0.4" + read-pkg-up "^2.0.0" + resolve "^1.9.0" + +eslint-plugin-node@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-node/-/eslint-plugin-node-8.0.1.tgz#55ae3560022863d141fa7a11799532340a685964" + integrity sha512-ZjOjbjEi6jd82rIpFSgagv4CHWzG9xsQAVp1ZPlhRnnYxcTgENUVBvhYmkQ7GvT1QFijUSo69RaiOJKhMu6i8w== + dependencies: + eslint-plugin-es "^1.3.1" + eslint-utils "^1.3.1" + ignore "^5.0.2" + minimatch "^3.0.4" + resolve "^1.8.1" + semver "^5.5.0" + +eslint-plugin-promise@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-4.0.1.tgz#2d074b653f35a23d1ba89d8e976a985117d1c6a2" + integrity sha512-Si16O0+Hqz1gDHsys6RtFRrW7cCTB6P7p3OJmKp3Y3dxpQE2qwOA7d3xnV+0mBmrPoi0RBnxlCKvqu70te6wjg== + +eslint-plugin-standard@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-standard/-/eslint-plugin-standard-4.0.0.tgz#f845b45109c99cd90e77796940a344546c8f6b5c" + integrity sha512-OwxJkR6TQiYMmt1EsNRMe5qG3GsbjlcOhbGUBY4LtavF9DsLaTcoR+j2Tdjqi23oUwKNUqX7qcn5fPStafMdlA== + +eslint-scope@3.7.1, eslint-scope@^3.7.1: version "3.7.1" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-3.7.1.tgz#3d63c3edfda02e06e01a452ad88caacc7cdcb6e8" dependencies: esrecurse "^4.1.0" estraverse "^4.1.1" +eslint-utils@^1.3.0, eslint-utils@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-1.3.1.tgz#9a851ba89ee7c460346f97cf8939c7298827e512" + integrity sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q== + eslint-visitor-keys@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" @@ -3498,6 +3683,11 @@ ftp@~0.3.10: readable-stream "1.1.x" xregexp "2.0.0" +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + functional-red-black-tree@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" @@ -3653,6 +3843,11 @@ globals@^11.0.1: version "11.2.0" resolved "https://registry.yarnpkg.com/globals/-/globals-11.2.0.tgz#aa2ece052a787563ba70a3dcd9dc2eb8a9a0488c" +globals@^11.1.0: + version "11.11.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.11.0.tgz#dcf93757fa2de5486fbeed7118538adf789e9c2e" + integrity sha512-WHq43gS+6ufNOEqlrDBxVEbb8ntfXrfAUU2ZOpCxrBdGKW3gyv8mCxAfIBD0DroPKGrJ2eSsXsLtY9MPntsyTw== + globals@^9.0.0: version "9.17.0" resolved "https://registry.yarnpkg.com/globals/-/globals-9.17.0.tgz#0c0ca696d9b9bb694d2e5470bd37777caad50286" @@ -3898,6 +4093,13 @@ has-values@^1.0.0: is-number "^3.0.0" kind-of "^4.0.0" +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + hash-base@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-2.0.2.tgz#66ea1d856db4e8a5470cadf6fce23ae5244ef2e1" @@ -4132,6 +4334,11 @@ ignore@^3.3.3: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" +ignore@^5.0.2: + version "5.0.5" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.0.5.tgz#c663c548d6ce186fb33616a8ccb5d46e56bdbbf9" + integrity sha512-kOC8IUb8HSDMVcYrDVezCxpJkzSQWTAzf3olpKM6o9rM5zpojx23O0Fl8Wr4+qJ6ZbPEHqf1fdwev/DS7v7pmA== + image-size@~0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.1.tgz#28eea8548a4b1443480ddddc1e083ae54652439f" @@ -4569,6 +4776,11 @@ js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + js-yaml@^3.9.1: version "3.10.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" @@ -4584,6 +4796,11 @@ jsesc@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + jsesc@~0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" @@ -4973,7 +5190,7 @@ lodash@^4.0.0, lodash@^4.14.0, lodash@^4.15.0, lodash@^4.17.0, lodash@^4.17.1, l version "4.17.4" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.4.tgz#78203a4d1c328ae1d86dca6460e369b57f4055ae" -lodash@^4.16.2, lodash@^4.8.2: +lodash@^4.16.2, lodash@^4.17.11, lodash@^4.8.2: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" integrity sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg== @@ -5991,6 +6208,11 @@ path-parse@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + path-proxy@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/path-proxy/-/path-proxy-1.0.0.tgz#18e8a36859fc9d2f1a53b48dee138543c020de5e" @@ -6660,6 +6882,11 @@ regex-not@^1.0.0, regex-not@^1.0.2: extend-shallow "^3.0.2" safe-regex "^1.1.0" +regexpp@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-2.0.1.tgz#8d19d31cf632482b589049f8281f93dbcba4d07f" + integrity sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw== + regexpu-core@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" @@ -6887,6 +7114,13 @@ resolve@^1.1.6: dependencies: path-parse "^1.0.5" +resolve@^1.8.1, resolve@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.10.0.tgz#3bdaaeaf45cc07f375656dfd2e54ed0810b101ba" + integrity sha512-3sUr9aq5OfSg2S9pNtPA9hL1FVEAjvfOC4leW0SNf/mpnaakz2a9femSd6LqAww2RaFctwyf1lCqnTHuF1rxDg== + dependencies: + path-parse "^1.0.6" + resolve@~1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b" @@ -7485,14 +7719,14 @@ source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" +source-map@^0.5.0, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + source-map@^0.5.3, source-map@^0.5.5, source-map@~0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.6.tgz#75ce38f52bf0733c5a7f0c118d81334a2bb5f412" -source-map@^0.5.6: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - source-map@^0.6.0, source-map@~0.6.1: version "0.6.1" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" @@ -7821,6 +8055,11 @@ to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" -- cgit v1.2.3