diff --git a/.gitignore b/.gitignore index 15ae134..4222a12 100644 --- a/.gitignore +++ b/.gitignore @@ -2,13 +2,14 @@ *.avi *.mp4 *.wav -secrets.js -settings.js public/content ffdata node_modules builtAssets vsbenv +public/js/main-built* +public/js/editing-interface/editing-interface/main-built* +*.sqlite *~ .tern-port diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..e336d4c --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +public/js/lib/ +main-built.js diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..dc2fb82 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,3 @@ +{ + "singleQuote": true +} \ No newline at end of file diff --git a/Makefile b/Makefile index 41361ba..0c71adf 100644 --- a/Makefile +++ b/Makefile @@ -4,25 +4,12 @@ MAKEFILE_DIR := $(dir $(lastword $(MAKEFILE_LIST))) BASE_DIR := $(realpath $(MAKEFILE_DIR)) -# dirs and files ignored by gitignore -configd := $(BASE_DIR)/config -demo_secrets := $(configd)/demo-secrets.js -demo_settings := $(configd)/demo-settings.js -secrets := $(configd)/secrets.js -settings := $(configd)/settings.js - -node_modules: |$(secrets) $(settings) +node_modules: npm install -$(secrets): - cp $(demo_secrets) $(secrets) - -$(settings): - cp $(demo_settings) $(settings) - update: git pull cd submods/p2fa-vislab; git pull build_production: - cd public/js; r.js -o build.js + npm run build diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..063b78f --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: npm start diff --git a/app.js b/app.js index 199f054..c7a387e 100755 --- a/app.js +++ b/app.js @@ -11,11 +11,19 @@ var logger = require('morgan'); var errorHandler = require('errorhandler'); var csrf = require('lusca').csrf(); var methodOverride = require('method-override'); +var sslRedirect = require('heroku-ssl-redirect'); +const sequelize = require('./models/sequelize'); +// load models +require('./models'); -var MongoStore = require('connect-mongo')({ session: session }); +sequelize.sync(); + +var fs = require('fs'); +var https = require('https'); + +const SequelizeStore = require('connect-session-sequelize')(session.Store); var flash = require('express-flash'); var path = require('path'); -var mongoose = require('mongoose'); var passport = require('passport'); var expressValidator = require('express-validator'); var connectAssets = require('connect-assets'); @@ -26,7 +34,6 @@ var connectAssets = require('connect-assets'); var homeController = require('./controllers/home'); var userController = require('./controllers/user'); -var apiController = require('./controllers/api'); var contactController = require('./controllers/contact'); var editorController = require('./controllers/editor-controller'); var screenShotController = require('./controllers/screenshot'); @@ -45,138 +52,182 @@ var passportConf = require('./config/passport'); var app = express(); -/** - * Mongoose configuration. - */ - -mongoose.connect(secrets.db); -mongoose.connection.on('error', function() { - console.error('✗ MongoDB Connection Error. Please make sure MongoDB is running.'); -}); - -var hour = 3600000; -var day = hour * 24; -var week = day * 7; - -/** - * CSRF Whitelist - */ - -// TODO fix -var whitelist = ['/newvd']; - -/** - * Express configuration. - */ - -/** - * CORS - */ -app.all("/*", function(req, res, next) { - res.header("Access-Control-Allow-Origin", "*"); - res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); - next(); +function initServer() { + var hour = 3600000; + var day = hour * 24; + var week = day * 7; + + /** + * CSRF Whitelist + */ + + // TODO fix + var whitelist = ['/newvd']; + + /** + * Express configuration. + */ + + /** + * CORS + */ + app.all('/*', function (req, res, next) { + res.header('Access-Control-Allow-Origin', '*'); + res.header( + 'Access-Control-Allow-Headers', + 'Origin, X-Requested-With, Content-Type, Accept' + ); + next(); + }); + + app.set('port', process.env.PORT || 3000); + app.set('views', path.join(__dirname, 'views')); + app.set('view engine', 'jade'); + app.use(sslRedirect()); + app.use( + connectAssets({ + paths: ['public/css', 'public/js', 'public/img'], + helperContext: app.locals, + servePath: 'vdstatic', + compress: false, // connect-assets doesn't support es6+, I think? we'll compress with terser in the build process + }) + ); + app.use(compress()); + app.use(logger('dev')); + app.use(bodyParser.json({ limit: '100mb' })); + app.use(bodyParser.urlencoded({ limit: '100mb' })); + app.use(expressValidator()); + app.use(methodOverride()); + app.use(cookieParser()); + app.use(passport.initialize()); + app.use(passport.session()); + app.use(function (req, res, next) { + // AMy change + next(); + // if (whitelist.indexOf(req.path) !== -1) next(); + // else csrf(req, res, next); + }); + app.use(function (req, res, next) { + res.locals.user = req.user; + res.locals.prod = process.env.NODE_ENV === 'production'; + next(); + }); + app.use(flash()); + + app.use( + '/:extra(videodigests)?', + express.static(path.join(__dirname, 'public'), { maxAge: week }) + ); + app.use(function (req, res, next) { + // Keep track of previous URL to redirect back to + // original destination after a successful login. + if (req.method !== 'GET') return next(); + var path = req.path.split('/')[1]; + if (/(auth|login|logout|signup)$/i.test(path)) return next(); + req.session.returnTo = req.path; + next(); + }); + + // TODO: make this more informative + app.use(function (err, req, res, next) { + console.error(err.stack); + res.status(500).send('Sorry, something broke!'); + }); + + /** + * Application routes. + */ + var extraPath = ':extra?/?'; + // var extraPath = ""; + app.get('/:extra(videodigests)?', homeController.index); + // TODO separate editor from the viewer + app.get('/' + extraPath + 'view/:vdid', editorController.getEditor); + app.get('/' + extraPath + 'view/:vdid/:slug', editorController.getEditor); + app.get('/' + extraPath + 'editor', editorController.getEditor); + app.get('/' + extraPath + 'tutorial', homeController.tutorial); + + // TODO make more restful + app.get('/' + extraPath + 'digestdata/:vdid', editorController.getDigestData); + app.post( + '/' + extraPath + 'digestpublish/:vdid', + passportConf.isAuthenticated, + editorController.postPublishDigest + ); + app.get('/' + extraPath + 'autoseg/:vdid', editorController.getAutoSeg); + + // TODO add Authorization + app.post( + '/' + extraPath + 'digestdata/:vdid', + editorController.postDigestData + ); + app.get('/' + extraPath + 'checkstatus', editorController.getStatus); + app.get('/' + extraPath + 'screenshot', screenShotController.getScreenShot); + app.post('/' + extraPath + 'newvd', editorController.postNewVD); + // Disable "latest" page for now + // app.get('/' + extraPath + 'latest', vdlistController.getVDList); + app.get('/' + extraPath + 'login', userController.getLogin); + app.post('/' + extraPath + 'login', userController.postLogin); + app.get('/' + extraPath + 'logout', userController.logout); + app.get('/' + extraPath + 'forgot', userController.getForgot); + app.post('/' + extraPath + 'forgot', userController.postForgot); + app.get('/' + extraPath + 'reset/:token', userController.getReset); + app.post('/' + extraPath + 'reset/:token', userController.postReset); + app.get('/' + extraPath + 'signup', userController.getSignup); + app.post('/' + extraPath + 'signup', userController.postSignup); + app.get('/' + extraPath + 'contact', contactController.getContact); + app.post('/' + extraPath + 'contact', contactController.postContact); + app.get( + '/' + extraPath + 'account', + passportConf.isAuthenticated, + userController.getAccount + ); + app.post( + '/' + extraPath + 'account/profile', + passportConf.isAuthenticated, + userController.postUpdateProfile + ); + app.post( + '/' + extraPath + 'account/password', + passportConf.isAuthenticated, + userController.postUpdatePassword + ); + app.post( + '/' + extraPath + 'account/delete', + passportConf.isAuthenticated, + userController.postDeleteAccount + ); + + app.use(errorHandler()); +} + +const sessionStore = new SequelizeStore({ + db: sequelize, }); - -app.set('port', process.env.PORT || 3000); -app.set('views', path.join(__dirname, 'views')); -app.set('view engine', 'jade'); -app.use(connectAssets({ - paths: ['public/css', 'public/js'], - helperContext: app.locals, - servePath: 'vdstatic' -})); -app.use(compress()); -app.use(logger('dev')); -app.use(bodyParser.json({limit: "100mb"})); -app.use(bodyParser.urlencoded({limit: "100mb"})); -app.use(expressValidator()); -app.use(methodOverride()); -app.use(cookieParser()); -app.use(session({ - secret: secrets.sessionSecret, - store: new MongoStore({ - url: secrets.db, - auto_reconnect: true +app.use( + session({ + secret: secrets.sessionSecret, + store: sessionStore, + resave: false, + proxy: true, }) -})); -app.use(passport.initialize()); -app.use(passport.session()); -app.use(function(req, res, next) { - if (whitelist.indexOf(req.path) !== -1) next(); - else csrf(req, res, next); -}); -app.use(function(req, res, next) { - res.locals.user = req.user; - res.locals.prod = app.get('env') == 'production'; - next(); -}); -app.use(flash()); - -app.use('/:extra(videodigests)?', express.static(path.join(__dirname, 'public'), { maxAge: week })); -app.use(function(req, res, next) { - // Keep track of previous URL to redirect back to - // original destination after a successful login. - if (req.method !== 'GET') return next(); - var path = req.path.split('/')[1]; - if (/(auth|login|logout|signup)$/i.test(path)) return next(); - req.session.returnTo = req.path; - next(); -}); - -// TODO: make this more informative -app.use(function(err, req, res, next){ - console.error(err.stack); - res.send(500, 'Sorry, something broke!'); -}); +); -/** - * Application routes. - */ -var extraPath = ":extra?/?"; -app.get('/:extra(videodigests)?', homeController.index); -// TODO separate editor from the viewer -app.get('/' + extraPath + 'view/:ptitle', editorController.getEditor); -app.get('/' + extraPath + 'editor', editorController.getEditor); -app.get('/' + extraPath + 'tutorial', homeController.tutorial); - -// TODO make more restful -app.get('/' + extraPath + 'digestdata/:vdid', editorController.getDigestData); -app.post('/' + extraPath + 'digestpublish/:vdid', passportConf.isAuthenticated, editorController.postPublishDigest); -app.get('/' + extraPath + 'autoseg/:vdid', editorController.getAutoSeg); - -// TODO add Authorization -app.post('/' + extraPath + 'digestdata/:vdid', editorController.postDigestData); -app.get('/' + extraPath + 'checkstatus', editorController.getStatus); -app.get('/' + extraPath + 'screenshot', screenShotController.getScreenShot); -app.post('/' + extraPath + 'newvd', editorController.postNewVD); -app.get('/' + extraPath + 'vdigests', vdlistController.getVDList); -app.get('/' + extraPath + 'login', userController.getLogin); -app.post('/' + extraPath + 'login', userController.postLogin); -app.get('/' + extraPath + 'logout', userController.logout); -app.get('/' + extraPath + 'forgot', userController.getForgot); -app.post('/' + extraPath + 'forgot', userController.postForgot); -app.get('/' + extraPath + 'reset/:token', userController.getReset); -app.post('/' + extraPath + 'reset/:token', userController.postReset); -app.get('/' + extraPath + 'signup', userController.getSignup); -app.post('/' + extraPath + 'signup', userController.postSignup); -app.get('/' + extraPath + 'contact', contactController.getContact); -app.post('/' + extraPath + 'contact', contactController.postContact); -app.get('/' + extraPath + 'account', passportConf.isAuthenticated, userController.getAccount); -app.post('/' + extraPath + 'account/profile', passportConf.isAuthenticated, userController.postUpdateProfile); -app.post('/' + extraPath + 'account/password', passportConf.isAuthenticated, userController.postUpdatePassword); -app.post('/' + extraPath + 'account/delete', passportConf.isAuthenticated, userController.postDeleteAccount); -app.get('/' + extraPath + 'account/unlink/:provider', passportConf.isAuthenticated, userController.getOauthUnlink); - -app.use(errorHandler()); +sessionStore.sync(); +sequelize.sync(); /** * Start Express server. */ -app.listen(app.get('port'), function() { - console.log(" ✔ Express server listening on port %d in %s mode", app.get('port'), app.get('env')); +initServer(); + +app.listen(app.get('port'), function () { + console.log( + ' ✔ Express server listening on port %d in %s mode', + app.get('port'), + app.get('env') + ); }); module.exports = app; diff --git a/config/demo-secrets.js b/config/demo-secrets.js deleted file mode 100644 index e6d1264..0000000 --- a/config/demo-secrets.js +++ /dev/null @@ -1,129 +0,0 @@ -/** - * IMPORTANT NOTICE - * - * You should never commit this file to a public repository on GitHub! - * All public code on GitHub can be searched, that means anyone can see your - * uploaded secrets.js file. - * - * I did it for your convenience using "throw away" credentials so that - * all features could work out of the box. - * - * Untrack secrets.js from Git before pushing your code to GitHub: - * - * git rm --cached config/secrets.js - * - * If you have already commited this file to GitHub with your keys, then - * refer to https://help.github.com/articles/remove-sensitive-data - */ - -module.exports = { - - db: process.env.MONGODB|| 'mongodb://localhost:27017/vdigest', - - betaPW: "somepw", - - sessionSecret: "somesessionsecret", - - adminEmail: "admin@example.com", - mailgun: { - user: process.env.MAILGUN_USER || 'postmaster@sandbox697fcddc09814c6b83718b9fd5d4e5dc.mailgun.org', - password: process.env.MAILGUN_PASSWORD || '29eldds1uri6' - }, - - mandrill: { - user: process.env.MANDRILL_USER || 'hackathonstarterdemo', - password: process.env.MANDRILL_PASSWORD || 'E1K950_ydLR4mHw12a0ldA' - }, - - sendgrid: { - user: process.env.SENDGRID_USER || 'hslogin', - password: process.env.SENDGRID_PASSWORD || 'hspassword00' - }, - - nyt: { - key: process.env.NYT_KEY || '9548be6f3a64163d23e1539f067fcabd:5:68537648' - }, - - lastfm: { - api_key: process.env.LASTFM_KEY || 'c8c0ea1c4a6b199b3429722512fbd17f', - secret: process.env.LASTFM_SECRET || 'is cb7857b8fba83f819ea46ca13681fe71' - }, - - facebook: { - clientID: process.env.FACEBOOK_ID || '754220301289665', - clientSecret: process.env.FACEBOOK_SECRET || '41860e58c256a3d7ad8267d3c1939a4a', - callbackURL: '/auth/facebook/callback', - passReqToCallback: true - }, - - instagram: { - clientID: process.env.INSTAGRAM_ID || '9f5c39ab236a48e0aec354acb77eee9b', - clientSecret: process.env.INSTAGRAM_SECRET || '5920619aafe842128673e793a1c40028', - callbackURL: '/auth/instagram/callback', - passReqToCallback: true - }, - - github: { - clientID: process.env.GITHUB_ID || 'cb448b1d4f0c743a1e36', - clientSecret: process.env.GITHUB_SECRET || '815aa4606f476444691c5f1c16b9c70da6714dc6', - callbackURL: '/auth/github/callback', - passReqToCallback: true - }, - - twitter: { - consumerKey: process.env.TWITTER_KEY || '6NNBDyJ2TavL407A3lWxPFKBI', - consumerSecret: process.env.TWITTER_SECRET || 'ZHaYyK3DQCqv49Z9ofsYdqiUgeoICyh6uoBgFfu7OeYC7wTQKa', - callbackURL: '/auth/twitter/callback', - passReqToCallback: true - }, - - google: { - clientID: process.env.GOOGLE_ID || '828110519058.apps.googleusercontent.com', - clientSecret: process.env.GOOGLE_SECRET || 'JdZsIaWhUFIchmC1a_IZzOHb', - callbackURL: '/auth/google/callback', - passReqToCallback: true - }, - - linkedin: { - clientID: process.env.LINKEDIN_ID || '77chexmowru601', - clientSecret: process.env.LINKEDIN_SECRET || 'szdC8lN2s2SuMSy8', - callbackURL: '/auth/linkedin/callback', - scope: ['r_fullprofile', 'r_emailaddress', 'r_network'], - passReqToCallback: true - }, - - steam: { - apiKey: process.env.STEAM_KEY || 'D1240DEF4D41D416FD291D0075B6ED3F' - }, - - twilio: { - sid: process.env.TWILIO_SID || 'AC6f0edc4c47becc6d0a952536fc9a6025', - token: process.env.TWILIO_TOKEN || 'a67170ff7afa2df3f4c7d97cd240d0f3' - }, - - clockwork: { - apiKey: process.env.CLOCKWORK_KEY || '9ffb267f88df55762f74ba2f517a66dc8bedac5a' - }, - - stripe: { - apiKey: process.env.STRIPE_KEY || 'sk_test_BQokikJOvBiI2HlWgH4olfQ2' - }, - - tumblr: { - consumerKey: process.env.TUMBLR_KEY || 'FaXbGf5gkhswzDqSMYI42QCPYoHsu5MIDciAhTyYjehotQpJvM', - consumerSecret: process.env.TUMBLR_SECRET || 'QpCTs5IMMCsCImwdvFiqyGtIZwowF5o3UXonjPoNp4HVtJAL4o', - callbackURL: '/auth/tumblr/callback' - }, - - foursquare: { - clientId: process.env.FOURSQUARE_ID || '2STROLSFBMZLAHG3IBA141EM2HGRF0IRIBB4KXMOGA2EH3JG', - clientSecret: process.env.FOURSQUARE_SECRET || 'UAABFAWTIHIUFBL0PDC3TDMSXJF2GTGWLD3BES1QHXKAIYQB', - redirectUrl: process.env.FOURSQUARE_REDIRECT_URL || 'http://localhost:3000/auth/foursquare/callback' - }, - - venmo: { - clientId: process.env.VENMO_ID || '1688', - clientSecret: process.env.VENMO_SECRET || 'uQXtNBa6KVphDLAEx8suEush3scX8grs', - redirectUrl: process.env.VENMO_REDIRECT_URL || 'http://localhost:3000/auth/venmo/callback' - } -}; diff --git a/config/demo-settings.js b/config/demo-settings.js deleted file mode 100644 index 7842744..0000000 --- a/config/demo-settings.js +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Global settings - */ -/*global require module __dirname*/ - -var mkdirp = require('mkdirp'), - path = require('path'), - ffdataPath = path.normalize(path.join(__dirname, "..", "ffdata")), - paths = { - alignpy: path.join(ffdataPath, "../submods/p2fa-vislab/align.py"), - alignpy: "../submods/p2fa-vislab/align.py", - ffdata: ffdataPath, - videos: path.join(ffdataPath, "videos"), - audio: path.join(ffdataPath, "audio"), - screenshots: path.join(ffdataPath, "vdscreenshots"), - rawTrans: path.join(ffdataPath, "rawtrans"), - tmp: path.join(ffdataPath, "tmp") - }; - -/** create the paths if they don't exist **/ -for (var pth in paths) { - if (paths.hasOwnProperty(pth)) { - mkdirp(paths[pth]); - } -}; - -module.exports = { - paths: paths, - maxTransUploadSize: 21000000, // in bytes - max_yt_length: 20000 -}; diff --git a/config/passport.js b/config/passport.js index 4bacdda..c8e9c22 100755 --- a/config/passport.js +++ b/config/passport.js @@ -1,403 +1,70 @@ var _ = require('underscore'); -var passport = require('passport'); -var InstagramStrategy = require('passport-instagram').Strategy; -var LocalStrategy = require('passport-local').Strategy; -var FacebookStrategy = require('passport-facebook').Strategy; -var TwitterStrategy = require('passport-twitter').Strategy; -var GitHubStrategy = require('passport-github').Strategy; -var GoogleStrategy = require('passport-google-oauth').OAuth2Strategy; -var LinkedInStrategy = require('passport-linkedin-oauth2').Strategy; -var OAuthStrategy = require('passport-oauth').OAuthStrategy; // Tumblr -var OAuth2Strategy = require('passport-oauth').OAuth2Strategy; // Venmo, Foursquare +const bcrypt = require('bcrypt-nodejs'); +const passport = require('passport'); +const LocalStrategy = require('passport-local').Strategy; var User = require('../models/User'); var secrets = require('./secrets'); -passport.serializeUser(function(user, done) { +passport.serializeUser(function (user, done) { done(null, user.id); }); -passport.deserializeUser(function(id, done) { - User.findById(id, function(err, user) { - done(err, user); - }); -}); - -// Sign in with Instagram. - -passport.use(new InstagramStrategy(secrets.instagram,function(req, accessToken, refreshToken, profile, done) { - if (req.user) { - User.findOne({ instagram: profile.id }, function(err, existingUser) { - if (existingUser) { - req.flash('errors', { msg: 'There is already an Instagram account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); - } else { - User.findById(req.user.id, function(err, user) { - user.instagram = profile.id; - user.tokens.push({ kind: 'instagram', accessToken: accessToken }); - user.profile.name = user.profile.name || profile.displayName; - user.profile.picture = user.profile.picture || profile._json.data.profile_picture; - user.profile.website = user.profile.website || profile._json.data.website; - user.save(function(err) { - req.flash('info', { msg: 'Instagram account has been linked.' }); - done(err, user); - }); - }); - } - }); - } else { - User.findOne({ instagram: profile.id }, function(err, existingUser) { - if (existingUser) return done(null, existingUser); - - var user = new User(); - user.instagram = profile.id; - user.tokens.push({ kind: 'instagram', accessToken: accessToken }); - user.profile.name = profile.displayName; - // Similar to Twitter API, assigns a temporary e-mail address - // to get on with the registration process. It can be changed later - // to a valid e-mail address in Profile Management. - user.email = profile.username + "@instagram.com"; - user.profile.website = profile._json.data.website; - user.profile.picture = profile._json.data.profile_picture; - user.save(function(err) { - done(err, user); - }); - }); +passport.deserializeUser(async function (id, done) { + try { + const user = await User.findByPk(id); + done(null, user); + } catch (err) { + done(err, null); } -})); +}); // Sign in using Email and Password. -passport.use(new LocalStrategy({ usernameField: 'email' }, function(email, password, done) { - User.findOne({ email: email }, function(err, user) { - if (!user) return done(null, false, { message: 'Email ' + email + ' not found'}); - user.comparePassword(password, function(err, isMatch) { - if (isMatch) { - return done(null, user); +async function comparePassword(candidatePassword, userPassword) { + return new Promise((resolve, reject) => { + bcrypt.compare(candidatePassword, userPassword, function (err, isMatch) { + if (err) { + reject(err); } else { - return done(null, false, { message: 'Invalid email or password.' }); + resolve(isMatch); } }); }); -})); - -/** - * OAuth Strategy Overview - * - * - User is already logged in. - * - Check if there is an existing account with a id. - * - If there is, return an error message. (Account merging not supported) - * - Else link new OAuth account with currently logged-in user. - * - User is not logged in. - * - Check if it's a returning user. - * - If returning user, sign in and we are done. - * - Else check if there is an existing account with user's email. - * - If there is, return an error message. - * - Else create a new account. - */ - -// Sign in with Facebook. - -passport.use(new FacebookStrategy(secrets.facebook, function(req, accessToken, refreshToken, profile, done) { - if (req.user) { - User.findOne({ facebook: profile.id }, function(err, existingUser) { - if (existingUser) { - req.flash('errors', { msg: 'There is already a Facebook account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); - } else { - User.findById(req.user.id, function(err, user) { - user.facebook = profile.id; - user.tokens.push({ kind: 'facebook', accessToken: accessToken }); - user.profile.name = user.profile.name || profile.displayName; - user.profile.gender = user.profile.gender || profile._json.gender; - user.profile.picture = user.profile.picture || 'https://graph.facebook.com/' + profile.id + '/picture?type=large'; - user.save(function(err) { - req.flash('info', { msg: 'Facebook account has been linked.' }); - done(err, user); - }); - }); +} + +passport.use( + new LocalStrategy({ usernameField: 'email' }, async function ( + email, + password, + done + ) { + try { + const user = await User.findOne({ where: { email } }); + if (!user) { + return done(null, false, { message: 'Email ' + email + ' not found' }); } - }); - } else { - User.findOne({ facebook: profile.id }, function(err, existingUser) { - if (existingUser) return done(null, existingUser); - User.findOne({ email: profile._json.email }, function(err, existingEmailUser) { - if (existingEmailUser) { - req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Facebook manually from Account Settings.' }); - done(err); - } else { - var user = new User(); - user.email = profile._json.email; - user.facebook = profile.id; - user.tokens.push({ kind: 'facebook', accessToken: accessToken }); - user.profile.name = profile.displayName; - user.profile.gender = profile._json.gender; - user.profile.picture = 'https://graph.facebook.com/' + profile.id + '/picture?type=large'; - user.profile.location = (profile._json.location) ? profile._json.location.name : ''; - user.save(function(err) { - done(err, user); - }); - } - }); - }); - } -})); - -// Sign in with GitHub. - -passport.use(new GitHubStrategy(secrets.github, function(req, accessToken, refreshToken, profile, done) { - if (req.user) { - User.findOne({ github: profile.id }, function(err, existingUser) { - if (existingUser) { - req.flash('errors', { msg: 'There is already a GitHub account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); - } else { - User.findById(req.user.id, function(err, user) { - user.github = profile.id; - user.tokens.push({ kind: 'github', accessToken: accessToken }); - user.profile.name = user.profile.name || profile.displayName; - user.profile.picture = user.profile.picture || profile._json.avatar_url; - user.profile.location = user.profile.location || profile._json.location; - user.profile.website = user.profile.website || profile._json.blog; - user.save(function(err) { - req.flash('info', { msg: 'GitHub account has been linked.' }); - done(err, user); - }); - }); - } - }); - } else { - User.findOne({ github: profile.id }, function(err, existingUser) { - if (existingUser) return done(null, existingUser); - User.findOne({ email: profile._json.email }, function(err, existingEmailUser) { - if (existingEmailUser) { - req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with GitHub manually from Account Settings.' }); - done(err); - } else { - var user = new User(); - user.email = profile._json.email; - user.github = profile.id; - user.tokens.push({ kind: 'github', accessToken: accessToken }); - user.profile.name = profile.displayName; - user.profile.picture = profile._json.avatar_url; - user.profile.location = profile._json.location; - user.profile.website = profile._json.blog; - user.save(function(err) { - done(err, user); - }); - } - }); - }); - } -})); - -// Sign in with Twitter. - -passport.use(new TwitterStrategy(secrets.twitter, function(req, accessToken, tokenSecret, profile, done) { - if (req.user) { - User.findOne({ twitter: profile.id }, function(err, existingUser) { - if (existingUser) { - req.flash('errors', { msg: 'There is already a Twitter account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); - } else { - User.findById(req.user.id, function(err, user) { - user.twitter = profile.id; - user.tokens.push({ kind: 'twitter', accessToken: accessToken, tokenSecret: tokenSecret }); - user.profile.name = user.profile.name || profile.displayName; - user.profile.location = user.profile.location || profile._json.location; - user.profile.picture = user.profile.picture || profile._json.profile_image_url; - user.save(function(err) { - req.flash('info', { msg: 'Twitter account has been linked.' }); - done(err, user); - }); - }); - } - }); - - } else { - User.findOne({ twitter: profile.id }, function(err, existingUser) { - if (existingUser) return done(null, existingUser); - var user = new User(); - // Twitter will not provide an email address. Period. - // But a person’s twitter username is guaranteed to be unique - // so we can "fake" a twitter email address as follows: - user.email = profile.username + "@twitter.com"; - user.twitter = profile.id; - user.tokens.push({ kind: 'twitter', accessToken: accessToken, tokenSecret: tokenSecret }); - user.profile.name = profile.displayName; - user.profile.location = profile._json.location; - user.profile.picture = profile._json.profile_image_url; - user.save(function(err) { - done(err, user); - }); - }); - } -})); - -// Sign in with Google. - -passport.use(new GoogleStrategy(secrets.google, function(req, accessToken, refreshToken, profile, done) { - if (req.user) { - User.findOne({ google: profile.id }, function(err, existingUser) { - if (existingUser) { - req.flash('errors', { msg: 'There is already a Google account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); - } else { - User.findById(req.user.id, function(err, user) { - user.google = profile.id; - user.tokens.push({ kind: 'google', accessToken: accessToken }); - user.profile.name = user.profile.name || profile.displayName; - user.profile.gender = user.profile.gender || profile._json.gender; - user.profile.picture = user.profile.picture || profile._json.picture; - user.save(function(err) { - req.flash('info', { msg: 'Google account has been linked.' }); - done(err, user); - }); - }); - } - }); - } else { - User.findOne({ google: profile.id }, function(err, existingUser) { - if (existingUser) return done(null, existingUser); - User.findOne({ email: profile._json.email }, function(err, existingEmailUser) { - if (existingEmailUser) { - req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with Google manually from Account Settings.' }); - done(err); - } else { - var user = new User(); - user.email = profile._json.email; - user.google = profile.id; - user.tokens.push({ kind: 'google', accessToken: accessToken }); - user.profile.name = profile.displayName; - user.profile.gender = profile._json.gender; - user.profile.picture = profile._json.picture; - user.save(function(err) { - done(err, user); - }); - } - }); - }); - } -})); - -// Sign in with LinkedIn. - -passport.use(new LinkedInStrategy(secrets.linkedin, function(req, accessToken, refreshToken, profile, done) { - if (req.user) { - User.findOne({ linkedin: profile.id }, function(err, existingUser) { - if (existingUser) { - req.flash('errors', { msg: 'There is already a LinkedIn account that belongs to you. Sign in with that account or delete it, then link it with your current account.' }); - done(err); + const isMatch = await comparePassword(password, user.password); + if (isMatch) { + return done(null, user); } else { - User.findById(req.user.id, function(err, user) { - user.linkedin = profile.id; - user.tokens.push({ kind: 'linkedin', accessToken: accessToken }); - user.profile.name = user.profile.name || profile.displayName; - user.profile.location = user.profile.location || profile._json.location.name; - user.profile.picture = user.profile.picture || profile._json.pictureUrl; - user.profile.website = user.profile.website || profile._json.publicProfileUrl; - user.save(function(err) { - req.flash('info', { msg: 'LinkedIn account has been linked.' }); - done(err, user); - }); - }); + return done(null, false, { message: 'Invalid email or password.' }); } - }); - } else { - User.findOne({ linkedin: profile.id }, function(err, existingUser) { - if (existingUser) return done(null, existingUser); - User.findOne({ email: profile._json.emailAddress }, function(err, existingEmailUser) { - if (existingEmailUser) { - req.flash('errors', { msg: 'There is already an account using this email address. Sign in to that account and link it with LinkedIn manually from Account Settings.' }); - done(err); - } else { - var user = new User(); - user.linkedin = profile.id; - user.tokens.push({ kind: 'linkedin', accessToken: accessToken }); - user.email = profile._json.emailAddress; - user.profile.name = profile.displayName; - user.profile.location = profile._json.location.name; - user.profile.picture = profile._json.pictureUrl; - user.profile.website = profile._json.publicProfileUrl; - user.save(function(err) { - done(err, user); - }); - } - }); - }); - } -})); - -// Tumblr API setup. - -passport.use('tumblr', new OAuthStrategy({ - requestTokenURL: 'http://www.tumblr.com/oauth/request_token', - accessTokenURL: 'http://www.tumblr.com/oauth/access_token', - userAuthorizationURL: 'http://www.tumblr.com/oauth/authorize', - consumerKey: secrets.tumblr.consumerKey, - consumerSecret: secrets.tumblr.consumerSecret, - callbackURL: secrets.tumblr.callbackURL, - passReqToCallback: true - }, - function(req, token, tokenSecret, profile, done) { - User.findById(req.user._id, function(err, user) { - user.tokens.push({ kind: 'tumblr', accessToken: token, tokenSecret: tokenSecret }); - user.save(function(err) { - done(err, user); - }); - }); - } -)); - -// Foursquare API setup. - -passport.use('foursquare', new OAuth2Strategy({ - authorizationURL: 'https://foursquare.com/oauth2/authorize', - tokenURL: 'https://foursquare.com/oauth2/access_token', - clientID: secrets.foursquare.clientId, - clientSecret: secrets.foursquare.clientSecret, - callbackURL: secrets.foursquare.redirectUrl, - passReqToCallback: true - }, - function(req, accessToken, refreshToken, profile, done) { - User.findById(req.user._id, function(err, user) { - user.tokens.push({ kind: 'foursquare', accessToken: accessToken }); - user.save(function(err) { - done(err, user); - }); - }); - } -)); - -// Venmo API setup. - -passport.use('venmo', new OAuth2Strategy({ - authorizationURL: 'https://api.venmo.com/v1/oauth/authorize', - tokenURL: 'https://api.venmo.com/v1/oauth/access_token', - clientID: secrets.venmo.clientId, - clientSecret: secrets.venmo.clientSecret, - callbackURL: secrets.venmo.redirectUrl, - passReqToCallback: true - }, - function(req, accessToken, refreshToken, profile, done) { - User.findById(req.user._id, function(err, user) { - user.tokens.push({ kind: 'venmo', accessToken: accessToken }); - user.save(function(err) { - done(err, user); - }); - }); - } -)); + } catch (err) { + return done(err); + } + }) +); // Login Required middleware. -exports.isAuthenticated = function(req, res, next) { +exports.isAuthenticated = function (req, res, next) { if (req.isAuthenticated()) return next(); res.redirect('/login'); }; // Authorization Required middleware. -exports.isAuthorized = function(req, res, next) { +exports.isAuthorized = function (req, res, next) { var provider = req.path.split('/').slice(-1)[0]; if (_.findWhere(req.user.tokens, { kind: provider })) { @@ -405,4 +72,4 @@ exports.isAuthorized = function(req, res, next) { } else { res.redirect('/auth/' + provider); } -}; \ No newline at end of file +}; diff --git a/config/secrets.js b/config/secrets.js new file mode 100644 index 0000000..ca19f18 --- /dev/null +++ b/config/secrets.js @@ -0,0 +1,14 @@ +module.exports = { + db: process.env.MONGODB_URI || 'mongodb://localhost:27017/vdigest', + + betaPW: process.env.BETA_PASSWORD || 'somepw', + + sessionSecret: process.env.SESSION_SECRET || 'somesessionsecret', + + mailgun: { + user: process.env.MAILGUN_USER, + password: process.env.MAILGUN_PASSWORD, + }, + + adminEmail: 'amypavel@gmail.com', +}; diff --git a/config/settings.js b/config/settings.js new file mode 100644 index 0000000..776090b --- /dev/null +++ b/config/settings.js @@ -0,0 +1,32 @@ +/** + * Global settings + */ +/*global require module __dirname*/ + +var mkdirp = require('mkdirp'), + path = require('path'), + ffdataPath = path.normalize(path.join(__dirname, '..', 'ffdata')), + paths = { + alignpy: path.join(ffdataPath, '../submods/p2fa-vislab/align.py'), + alignpy: '../submods/p2fa-vislab/align.py', + ffdata: ffdataPath, + videos: path.join(ffdataPath, 'videos'), + audio: path.join(ffdataPath, 'audio'), + screenshots: path.join(ffdataPath, 'vdscreenshots'), + ssTrans: path.join(ffdataPath, 'sstrans'), + rawTrans: path.join(ffdataPath, 'rawtrans'), + tmp: path.join(ffdataPath, 'tmp'), + }; + +/** create the paths if they don't exist **/ +for (var pth in paths) { + if (paths.hasOwnProperty(pth)) { + mkdirp(paths[pth]); + } +} + +module.exports = { + paths, + maxTransUploadSize: 21000000, // in bytes + max_yt_length: 20000, +}; diff --git a/controllers/api.js b/controllers/api.js deleted file mode 100644 index 27f381f..0000000 --- a/controllers/api.js +++ /dev/null @@ -1,564 +0,0 @@ -var secrets = require('../config/secrets'); -var User = require('../models/User'); -var querystring = require('querystring'); -var validator = require('validator'); -var async = require('async'); -var cheerio = require('cheerio'); -var request = require('request'); -var graph = require('fbgraph'); -var LastFmNode = require('lastfm').LastFmNode; -var tumblr = require('tumblr.js'); -var foursquare = require('node-foursquare')({ secrets: secrets.foursquare }); -var Github = require('github-api'); -var Twit = require('twit'); -var stripe = require('stripe')(secrets.stripe.apiKey); -var twilio = require('twilio')(secrets.twilio.sid, secrets.twilio.token); -var Linkedin = require('node-linkedin')(secrets.linkedin.clientID, secrets.linkedin.clientSecret, secrets.linkedin.callbackURL); -var clockwork = require('clockwork')({key: secrets.clockwork.apiKey}); -var ig = require('instagram-node').instagram(); -var Y = require('yui/yql'); -var _ = require('underscore'); - -/** - * GET /api - * List of API examples. - */ - -exports.getApi = function(req, res) { - res.render('api/index', { - title: 'API Examples' - }); -}; - -/** - * GET /api/foursquare - * Foursquare API example. - */ - -exports.getFoursquare = function(req, res, next) { - var token = _.findWhere(req.user.tokens, { kind: 'foursquare' }); - async.parallel({ - trendingVenues: function(callback) { - foursquare.Venues.getTrending('40.7222756', '-74.0022724', { limit: 50 }, token.accessToken, function(err, results) { - callback(err, results); - }); - }, - venueDetail: function(callback) { - foursquare.Venues.getVenue('49da74aef964a5208b5e1fe3', token.accessToken, function(err, results) { - callback(err, results); - }); - }, - userCheckins: function(callback) { - foursquare.Users.getCheckins('self', null, token.accessToken, function(err, results) { - callback(err, results); - }); - } - }, - function(err, results) { - if (err) return next(err); - res.render('api/foursquare', { - title: 'Foursquare API', - trendingVenues: results.trendingVenues, - venueDetail: results.venueDetail, - userCheckins: results.userCheckins - }); - }); -}; - -/** - * GET /api/tumblr - * Tumblr API example. - */ - -exports.getTumblr = function(req, res) { - var token = _.findWhere(req.user.tokens, { kind: 'tumblr' }); - var client = tumblr.createClient({ - consumer_key: secrets.tumblr.consumerKey, - consumer_secret: secrets.tumblr.consumerSecret, - token: token.accessToken, - token_secret: token.tokenSecret - }); - client.posts('withinthisnightmare.tumblr.com', { type: 'photo' }, function(err, data) { - res.render('api/tumblr', { - title: 'Tumblr API', - blog: data.blog, - photoset: data.posts[0].photos - }); - }); -}; - -/** - * GET /api/facebook - * Facebook API example. - */ - -exports.getFacebook = function(req, res, next) { - var token = _.findWhere(req.user.tokens, { kind: 'facebook' }); - graph.setAccessToken(token.accessToken); - async.parallel({ - getMe: function(done) { - graph.get(req.user.facebook, function(err, me) { - done(err, me); - }); - }, - getMyFriends: function(done) { - graph.get(req.user.facebook + '/friends', function(err, friends) { - done(err, friends.data); - }); - } - }, - function(err, results) { - if (err) return next(err); - res.render('api/facebook', { - title: 'Facebook API', - me: results.getMe, - friends: results.getMyFriends - }); - }); -}; - -/** - * GET /api/scraping - * Web scraping example using Cheerio library. - */ - -exports.getScraping = function(req, res, next) { - request.get('https://news.ycombinator.com/', function(err, request, body) { - if (err) return next(err); - var $ = cheerio.load(body); - var links = []; - $(".title a[href^='http'], a[href^='https']").each(function() { - links.push($(this)); - }); - res.render('api/scraping', { - title: 'Web Scraping', - links: links - }); - }); -}; - -/** - * GET /api/github - * GitHub API Example. - */ -exports.getGithub = function(req, res) { - var token = _.findWhere(req.user.tokens, { kind: 'github' }); - var github = new Github({ token: token.accessToken }); - var repo = github.getRepo('sahat', 'requirejs-library'); - repo.show(function(err, repo) { - res.render('api/github', { - title: 'GitHub API', - repo: repo - }); - }); - -}; - -/** - * GET /api/aviary - * Aviary image processing example. - */ - -exports.getAviary = function(req, res) { - res.render('api/aviary', { - title: 'Aviary API' - }); -}; - -/** - * GET /api/nyt - * New York Times API example. - */ - -exports.getNewYorkTimes = function(req, res, next) { - var query = querystring.stringify({ 'api-key': secrets.nyt.key, 'list-name': 'young-adult' }); - var url = 'http://api.nytimes.com/svc/books/v2/lists?' + query; - request.get(url, function(error, request, body) { - if (request.statusCode === 403) return next(Error('Missing or Invalid New York Times API Key')); - var bestsellers = JSON.parse(body); - res.render('api/nyt', { - title: 'New York Times API', - books: bestsellers.results - }); - }); -}; - -/** - * GET /api/lastfm - * Last.fm API example. - */ - -exports.getLastfm = function(req, res, next) { - var lastfm = new LastFmNode(secrets.lastfm); - async.parallel({ - artistInfo: function(done) { - lastfm.request("artist.getInfo", { - artist: 'Epica', - handlers: { - success: function(data) { - done(null, data); - }, - error: function(err) { - done(err); - } - } - }); - }, - artistTopAlbums: function(done) { - lastfm.request("artist.getTopAlbums", { - artist: 'Epica', - handlers: { - success: function(data) { - var albums = []; - _.each(data.topalbums.album, function(album) { - albums.push(album.image.slice(-1)[0]['#text']); - }); - done(null, albums.slice(0, 4)); - }, - error: function(err) { - done(err); - } - } - }); - } - }, - function(err, results) { - if (err) return next(err.message); - var artist = { - name: results.artistInfo.artist.name, - image: results.artistInfo.artist.image.slice(-1)[0]['#text'], - tags: results.artistInfo.artist.tags.tag, - bio: results.artistInfo.artist.bio.summary, - stats: results.artistInfo.artist.stats, - similar: results.artistInfo.artist.similar.artist, - topAlbums: results.artistTopAlbums - }; - res.render('api/lastfm', { - title: 'Last.fm API', - artist: artist - }); - }); -}; - -/** - * GET /api/twitter - * Twiter API example. - */ - -exports.getTwitter = function(req, res, next) { - var token = _.findWhere(req.user.tokens, { kind: 'twitter' }); - var T = new Twit({ - consumer_key: secrets.twitter.consumerKey, - consumer_secret: secrets.twitter.consumerSecret, - access_token: token.accessToken, - access_token_secret: token.tokenSecret - }); - T.get('search/tweets', { q: 'hackathon since:2013-01-01', geocode: '40.71448,-74.00598,5mi', count: 50 }, function(err, reply) { - if (err) return next(err); - res.render('api/twitter', { - title: 'Twitter API', - tweets: reply.statuses - }); - }); -}; - -/** - * GET /api/steam - * Steam API example. - */ - -exports.getSteam = function(req, res, next) { - var steamId = '76561197982488301'; - var query = { l: 'english', steamid: steamId, key: secrets.steam.apiKey }; - - async.parallel({ - playerAchievements: function(done) { - query.appid = '49520'; - var qs = querystring.stringify(query); - request.get({ url: 'http://api.steampowered.com/ISteamUserStats/GetPlayerAchievements/v0001/?' + qs, json: true }, function(error, request, body) { - if (request.statusCode === 401) return done(new Error('Missing or Invalid Steam API Key')); - done(error, body); - }); - }, - playerSummaries: function(done) { - query.steamids = steamId; - var qs = querystring.stringify(query); - request.get({ url: 'http://api.steampowered.com/ISteamUser/GetPlayerSummaries/v0002/?' + qs, json: true }, function(error, request, body) { - if (request.statusCode === 401) return done(new Error('Missing or Invalid Steam API Key')); - done(error, body); - }); - }, - ownedGames: function(done) { - query.include_appinfo = 1; - query.include_played_free_games = 1; - var qs = querystring.stringify(query); - request.get({ url: 'http://api.steampowered.com/IPlayerService/GetOwnedGames/v0001/?' + qs, json: true }, function(error, request, body) { - if (request.statusCode === 401) return done(new Error('Missing or Invalid Steam API Key')); - done(error, body); - }); - } - }, - function(err, results) { - if (err) return next(err); - res.render('api/steam', { - title: 'Steam Web API', - ownedGames: results.ownedGames.response.games, - playerAchievemments: results.playerAchievements.playerstats, - playerSummary: results.playerSummaries.response.players[0] - }); - }); -}; - -/** - * GET /api/stripe - * Stripe API example. - */ - -exports.getStripe = function(req, res) { - res.render('api/stripe', { - title: 'Stripe API' - }); -}; - -/** - * POST /api/stripe - * @param stipeToken - * @param stripeEmail - */ - -exports.postStripe = function(req, res, next) { - var stripeToken = req.body.stripeToken; - var stripeEmail = req.body.stripeEmail; - - stripe.charges.create({ - amount: 395, - currency: 'usd', - card: stripeToken, - description: stripeEmail - }, function(err, charge) { - if (err && err.type === 'StripeCardError') { - req.flash('errors', { msg: 'Your card has been declined.'}); - res.redirect('/api/stripe'); - } - req.flash('success', { msg: 'Your card has been charged successfully.'}); - res.redirect('/api/stripe'); - }); -}; - -/** - * GET /api/twilio - * Twilio API example. - */ - -exports.getTwilio = function(req, res, next) { - res.render('api/twilio', { - title: 'Twilio API' - }); -}; - -/** - * POST /api/twilio - * Twilio API example. - * @param telephone - */ - -exports.postTwilio = function(req, res, next) { - var message = { - to: req.body.telephone, - from: '+13472235148', - body: 'Hello from the Hackathon Starter' - }; - twilio.sendMessage(message, function(err, responseData) { - if (err) return next(err.message); - req.flash('success', { msg: 'Text sent to ' + responseData.to + '.'}); - res.redirect('/api/twilio'); - }); -}; - -/** - * GET /api/clockwork - * Clockwork SMS API example. - */ - -exports.getClockwork = function(req, res) { - res.render('api/clockwork', { - title: 'Clockwork SMS API' - }); -}; - -/** - * POST /api/clockwork - * Clockwork SMS API example. - * @param telephone - */ - -exports.postClockwork = function(req, res, next) { - var message = { - To: req.body.telephone, - From: 'Hackathon', - Content: 'Hello from the Hackathon Starter' - }; - clockwork.sendSms(message, function(err, responseData) { - if (err) return next(err.errDesc); - req.flash('success', { msg: 'Text sent to ' + responseData.responses[0].to }); - res.redirect('/api/clockwork'); - }); -}; - -/** - * GET /api/venmo - * Venmo API example. - */ - -exports.getVenmo = function(req, res, next) { - var token = _.findWhere(req.user.tokens, { kind: 'venmo' }); - var query = querystring.stringify({ access_token: token.accessToken }); - - async.parallel({ - getProfile: function(done) { - request.get({ url: 'https://api.venmo.com/v1/me?' + query, json: true }, function(err, request, body) { - done(err, body); - }); - }, - getRecentPayments: function(done) { - request.get({ url: 'https://api.venmo.com/v1/payments?' + query, json: true }, function(err, request, body) { - done(err, body); - - }); - } - }, - function(err, results) { - if (err) return next(err); - res.render('api/venmo', { - title: 'Venmo API', - profile: results.getProfile.data, - recentPayments: results.getRecentPayments.data - }); - }); -}; - -/** - * POST /api/venmo - * @param user - * @param note - * @param amount - * Send money. - */ - -exports.postVenmo = function(req, res, next) { - req.assert('user', 'Phone, Email or Venmo User ID cannot be blank').notEmpty(); - req.assert('note', 'Please enter a message to accompany the payment').notEmpty(); - req.assert('amount', 'The amount you want to pay cannot be blank').notEmpty(); - - var errors = req.validationErrors(); - - if (errors) { - req.flash('errors', errors); - return res.redirect('/api/venmo'); - } - - var token = _.findWhere(req.user.tokens, { kind: 'venmo' }); - - var formData = { - access_token: token.accessToken, - note: req.body.note, - amount: req.body.amount - }; - - if (validator.isEmail(req.body.user)) { - formData.email = req.body.user; - } else if (validator.isNumeric(req.body.user) && - validator.isLength(req.body.user, 10, 11)) { - formData.phone = req.body.user; - } else { - formData.user_id = req.body.user; - } - - request.post('https://api.venmo.com/v1/payments', { form: formData }, function(err, request, body) { - if (err) return next(err); - if (request.statusCode !== 200) { - req.flash('errors', { msg: JSON.parse(body).error.message }); - return res.redirect('/api/venmo'); - } - req.flash('success', { msg: 'Venmo money transfer complete' }); - res.redirect('/api/venmo'); - }); -}; - -/** - * GET /api/linkedin - * LinkedIn API example. - */ - -exports.getLinkedin = function(req, res, next) { - var token = _.findWhere(req.user.tokens, { kind: 'linkedin' }); - var linkedin = Linkedin.init(token.accessToken); - - linkedin.people.me(function(err, $in) { - if (err) return next(err); - res.render('api/linkedin', { - title: 'LinkedIn API', - profile: $in - }); - }); -}; - -/** - * GET /api/instagram - * Instagram API example. - */ - -exports.getInstagram = function(req, res, next) { - var token = _.findWhere(req.user.tokens, { kind: 'instagram' }); - - ig.use({ client_id: secrets.instagram.clientID, client_secret: secrets.instagram.clientSecret }); - ig.use({ access_token: token.accessToken }); - - async.parallel({ - searchByUsername: function(done) { - ig.user_search('lisa_veronica', function(err, users, limit) { - done(err, users); - }); - }, - searchByUserId: function(done) { - ig.user('175948269', function(err, user) { - done(err, user); - }); - }, - popularImages: function(done) { - ig.media_popular(function(err, medias) { - done(err, medias); - }); - }, - myRecentMedia: function(done) { - ig.user_self_media_recent(function(err, medias, pagination, limit) { - done(err, medias); - }); - } - }, function(err, results) { - if (err) return next(err); - res.render('api/instagram', { - title: 'Instagram API', - usernames: results.searchByUsername, - userById: results.searchByUserId, - popularImages: results.popularImages, - myRecentMedia: results.myRecentMedia - }); - }); -}; - -/** - * GET /api/yahoo - * Yahoo API example. - */ -exports.getYahoo = function(req, res) { - Y.YQL('SELECT * FROM weather.forecast WHERE (location = 10007)', function(response) { - var location = response.query.results.channel.location; - var condition = response.query.results.channel.item.condition; - res.render('api/yahoo', { - title: 'Yahoo API', - location: location, - condition: condition - }); - }); -}; \ No newline at end of file diff --git a/controllers/contact.js b/controllers/contact.js index 1c8ba89..7e1ba47 100644 --- a/controllers/contact.js +++ b/controllers/contact.js @@ -1,11 +1,11 @@ var secrets = require('../config/secrets'); -var nodemailer = require("nodemailer"); +var nodemailer = require('nodemailer'); var smtpTransport = nodemailer.createTransport('SMTP', { service: 'Mailgun', auth: { - user: secrets.mailgun.user, - pass: secrets.mailgun.password - } + user: secrets.mailgun.user, + pass: secrets.mailgun.password, + }, }); /** @@ -13,9 +13,9 @@ var smtpTransport = nodemailer.createTransport('SMTP', { * Contact form page. */ -exports.getContact = function(req, res) { +exports.getContact = function (req, res) { res.render('contact', { - title: 'Contact' + title: 'Contact', }); }; @@ -27,7 +27,7 @@ exports.getContact = function(req, res) { * @param message */ -exports.postContact = function(req, res) { +exports.postContact = function (req, res) { req.assert('name', 'Name cannot be blank').notEmpty(); req.assert('email', 'Email is not valid').isEmail(); req.assert('message', 'Message cannot be blank').notEmpty(); @@ -49,10 +49,10 @@ exports.postContact = function(req, res) { to: to, from: from, subject: subject, - text: body + text: body, }; - smtpTransport.sendMail(mailOptions, function(err) { + smtpTransport.sendMail(mailOptions, function (err) { if (err) { req.flash('errors', { msg: err.message }); return res.redirect('/contact'); diff --git a/controllers/editor-controller.js b/controllers/editor-controller.js index 6b801c7..0922e7a 100644 --- a/controllers/editor-controller.js +++ b/controllers/editor-controller.js @@ -4,196 +4,697 @@ */ /*global require exports*/ -var fs = require('fs'), - mkdirp = require('mkdirp'), - ytdl = require('ytdl'), - multiparty = require('multiparty'), - url = require('url'), - sys = require('sys'), - exec = require('child_process').exec, - User = require('../models/User'), - util = require('util'), - slug = require('slug'), - querystring = require('querystring'), - path = require('path'), - VDigest = require('../models/VDigest'), - settings = require('../config/settings'), - spaths = settings.paths, - pathUtils = require('../utils/fpaths'), - returnError = require('../utils/errors').returnError, - cache = require('memory-cache'); - -var nodemailer = require("nodemailer"); -var secrets = require('../config/secrets'); -var smtpTransport = nodemailer.createTransport('SMTP', { - service: 'Mailgun', - auth: { - user: secrets.mailgun.user, - pass: secrets.mailgun.password - } -}); - +const { promises: fs } = require('fs'); +const ytdl = require('ytdl-core'); +const multiparty = require('multiparty'); +const url = require('url'); +const { exec } = require('child_process'); +const User = require('../models/User'); +const { VDigest, DEFAULT_DIGEST } = require('../models/VDigest'); +const Ownership = require('../models/Ownership'); +const slug = require('slug'); +const querystring = require('querystring'); +const path = require('path'); +const settings = require('../config/settings'); +const spaths = settings.paths; +const { returnError } = require('../utils/errors'); +const cache = require('memory-cache'); +const { getSmallVideo } = require('./video-download'); +const { youtubeUrlFromId } = require('./url-helpers'); // Helper functions var returnJson = function (res, data, code) { code = code || 200; - res.writeHead(code, {'content-type': 'application/json'}); + res.writeHead(code, { 'content-type': 'application/json' }); res.write(JSON.stringify(data)); res.end(); }; -// Helper functions var returnErrorJson = function (res, data, code) { code = code || 400; - res.writeHead(code, {'content-type': 'application/json'}); + res.writeHead(code, { 'content-type': 'application/json' }); res.write(JSON.stringify(data)); res.end(); }; -var srtToText = function (srtText) { +function makeVDigestDataCacheObject({ + digest, + alignTrans, + ytid, + videoLength, + pubdisplay, +}) { + return JSON.stringify({ + digest, + transcript: alignTrans, + ytid, + videoLength, + pubdisplay, + }); +} + +const VALID_TRANSCRIPT_TYPES = new Set(['asr', 'manual', 'upload']); + +const DEFAULT_CAPTION_OPTIONS = { asr: false, manual: false }; +function getYouTubeSubtitleOptions(ytdlInfo) { + const { playerResponse } = ytdlInfo; + if (!playerResponse) { + return DEFAULT_CAPTION_OPTIONS; + } + const { captions } = playerResponse; + if (!captions) { + return DEFAULT_CAPTION_OPTIONS; + } + const { playerCaptionsTracklistRenderer } = captions; + if (!playerCaptionsTracklistRenderer) { + return DEFAULT_CAPTION_OPTIONS; + } + const { captionTracks } = playerCaptionsTracklistRenderer; + if (!captionTracks) { + return DEFAULT_CAPTION_OPTIONS; + } + const asr = captionTracks.some((track) => track.kind === 'asr'); + const manual = captionTracks.some( + (track) => track.kind === undefined && track.languageCode.startsWith('en') + ); + + return { + asr, + manual, + }; +} + +function srtToText(srtText) { var srtData = srtText.split(/\n\n/g), - writeData = ""; + writeData = ''; srtData.forEach(function (srCluster) { if (srCluster) { - writeData += srCluster.split("\n").slice(2).join(". "); - writeData += "\n"; + writeData += srCluster.split('\n').slice(2).join('. '); + writeData += '\n'; } }); return writeData; -}; +} + +const cardTimingRegex = /^(\d\d):(\d\d):(\d\d[\.,]\d\d\d) --> (\d\d):(\d\d):(\d\d[\.,]\d\d\d)/; + +function getTextForCurrentCard(cardText) { + // Skip all VTT cards that contain a cue tag, for now as the transcript is duplicated + // in those cards + if (cardText.indexOf('') >= 0 || cardText.length === 0) { + return ''; + } + cardText = `${cardText.charAt(0).toUpperCase()}${cardText.slice(1)}`; + if (!cardText.endsWith('.')) { + cardText += '.'; + } + return cardText; +} + +function vttToText(vttText) { + const vttLines = vttText.split('\n'); + let result = ''; + + let foundFirstTiming = false; + let currentCard = ''; + + for (const line of vttLines) { + const timingMatch = line.match(cardTimingRegex); + if (timingMatch) { + foundFirstTiming = true; + result += getTextForCurrentCard(currentCard); + currentCard = ''; + } else if (foundFirstTiming) { + currentCard += line + '\n'; + } + } + result += getTextForCurrentCard(currentCard); + return result; +} + +function getAlignmentForVttWithoutCues(vttText) { + const vttLines = vttText.split('\n'); + const words = []; + let cardStart = 0; + let cardEnd = 0; + let sentenceNumber = 0; + let currentCardParts = []; + + function flushCurrentCard() { + if (currentCardParts.length > 0) { + if (cardEnd > cardStart) { + words.push({ + word: currentCardParts.join(' '), + alignedWord: currentCardParts.join(' ').toUpperCase(), + start: cardStart, + end: cardEnd, + speaker: sentenceNumber, + sentenceNumber, + }); + sentenceNumber++; + } + currentCardParts = []; + } + } + + for (const line of vttLines) { + const timingMatch = line.match(cardTimingRegex); + if (timingMatch) { + flushCurrentCard(); + const [ + , + fromHours, + fromMinutes, + fromSeconds, + toHours, + toMinutes, + toSeconds, + ] = timingMatch; + cardStart = + parseInt(fromHours, 10) * 60 * 60 + + parseInt(fromMinutes, 10) * 60 + + parseFloat(fromSeconds); + cardEnd = + parseInt(toHours, 10) * 60 * 60 + + parseInt(toMinutes, 10) * 60 + + parseFloat(toSeconds); + } else if (line.length > 0) { + currentCardParts.push(line.trim()); + } + } + flushCurrentCard(); + return { words }; +} + +function getAlignmentForVttWithCues(vttText) { + const vttLines = vttText.split('\n'); + const words = []; + let cardStart = 0; + let cardEnd = 0; + let sentenceNumber = 0; + for (const line of vttLines) { + const timingMatch = line.match(cardTimingRegex); + if (timingMatch) { + const [ + , + fromHours, + fromMinutes, + fromSeconds, + toHours, + toMinutes, + toSeconds, + ] = timingMatch; + cardStart = + parseInt(fromHours, 10) * 60 * 60 + + parseInt(fromMinutes, 10) * 60 + + parseFloat(fromSeconds); + cardEnd = + parseInt(toHours, 10) * 60 * 60 + + parseInt(toMinutes, 10) * 60 + + parseFloat(toSeconds); + } else if (cardStart !== cardEnd && line.indexOf('') >= 0) { + let wordStart = cardStart; + let wordEnd = cardStart; + for (const part of line.split('')) { + const match = part.match( + /([^<>]+)(<\/c>)?(<(\d\d):(\d\d):(\d\d\.\d\d\d)>)?/ + ); + let word = part.trim(); + if (match) { + const [, w, , , hours, minutes, seconds] = match; + word = w.trim(); + if (hours && minutes && seconds) { + wordEnd = + parseInt(hours, 10) * 60 * 60 + + parseInt(minutes, 10) * 60 + + parseFloat(seconds); + } + } else { + wordEnd = cardEnd; + } + words.push({ + word, + alignedWord: word.toUpperCase(), + start: wordStart, + end: wordEnd, + speaker: 0, + sentenceNumber, + }); + wordStart = wordEnd; + } + sentenceNumber++; // crude... + } + } + return { words }; +} + +function getAlignmentForVtt(vttText) { + return vttText.indexOf('') === -1 + ? getAlignmentForVttWithoutCues(vttText) + : getAlignmentForVttWithCues(vttText); +} + +function getAlignmentForSrt(srtText) { + let shouldAdd = false; + let cardStart = 0; + let cardEnd = 0; + let currentCardParts = []; + + function flushCurrentCard() { + if (currentCardParts.length > 0) { + if (cardEnd > cardStart) { + words.push({ + word: currentCardParts.join(' '), + alignedWord: currentCardParts.join(' ').toUpperCase(), + start: cardStart, + end: cardEnd, + speaker: sentenceNumber, + sentenceNumber, + }); + sentenceNumber++; + } + currentCardParts = []; + } + } - + for (const line of srtText.split('\n')) { + const timingMatch = line.match(cardTimingRegex); + if (timingMatch) { + const [ + , + fromHours, + fromMinutes, + fromSeconds, + toHours, + toMinutes, + toSeconds, + ] = timingMatch; + cardStart = + parseInt(fromHours, 10) * 60 * 60 + + parseInt(fromMinutes, 10) * 60 + + parseFloat(fromSeconds); + cardEnd = + parseInt(toHours, 10) * 60 * 60 + + parseInt(toMinutes, 10) * 60 + + parseFloat(toSeconds); + shouldAdd = true; + } else if (line === '') { + flushCurrentCard(); + shouldAdd = false; + } else if (shouldAdd) { + currentCardParts.push(line); + } + } + flushCurrentCard(); + return { words }; +} + +async function createVideoDigest( + res, + { userId, ytid, tfname, videoLength, title, alignTrans, next } +) { + try { + const vd = await VDigest.create({ + ytid, + rawTransName: tfname, + videoName: ytid, + videoLength, + title, + digest: { ...DEFAULT_DIGEST, title }, + alignTrans, + state: 1, + uploadUser: userId, + }); + // add ownership + await vd.addUser(userId); + + const payload = { intrmid: vd.id, title }; + + res.writeHead(200, { 'content-type': 'application/json' }); + res.write(JSON.stringify(payload)); + res.end(); + } catch (err) { + console.error(err); + returnError( + res, + 'problem saving video digest to the database -- please try again', + next + ); + } +} + +async function getTranscriptAndCreateDigest({ + res, + userId, + title, + videoLength, + ytid, + captionsPath, + next, +}) { + // read the text so we can store it into + var tfname, rawTransFile, alignTrans; + + tfname = ytid + '.srt'; + + let writeData = undefined; + let srtData = undefined; + let vttData = undefined; + + try { + if (captionsPath) { + const captionsPathData = await fs.readFile(captionsPath, 'utf-8'); + if (captionsPath.endsWith('.srt')) { + srtData = captionsPathData; + } else if (captionsPath.endsWith('.vtt')) { + vttData = captionsPathData; + } + } + + if (vttData) { + writeData = vttToText(vttData); + alignTrans = getAlignmentForVtt(vttData); + } else if (srtData) { + writeData = srtToText(srtData); + alignTrans = getAlignmentForSrt(srtData); + } else { + throw new Error('No vttData or srtData'); + } + } catch (err) { + console.log(err); + console.log('No transcript available', err); + return returnError(res, 'unable to retrieve or parse captions'); + } + + tfname = ytid + '.txt'; + rawTransFile = path.join(spaths.rawTrans, ytid + '.txt'); + try { + await fs.writeFile(rawTransFile, writeData); + } catch (err) { + console.log(err); + return returnError(res, 'unable to get YouTube transcript'); + } + + createVideoDigest(res, { + userId, + ytid, + tfname, + videoLength, + title, + alignTrans, + next, + }); +} + +async function getTranscript({ + res, + userId, + title, + videoLength, + next, + ytid, + transcriptType, +}) { + console.log('Trying to download subtitle file for: ' + ytid); + + if (videoLength > settings.max_yt_length) { + returnError( + res, + 'Video length exceeds ' + + Math.floor(settings.max_yt_length / 60) + + ' minutes', + next + ); + return; + } + + // download the video transcript + const subCommand = + transcriptType === 'asr' ? '--write-auto-sub' : '--write-sub'; + const filePrefix = `${ytid}-${transcriptType}`; + const ytdlCommand = `youtube-dl --skip-download ${subCommand} --sub-format vtt -o '${path.join( + spaths.videos, + `${filePrefix}.%(ext)s` + )}' ${youtubeUrlFromId(ytid)}`; + + console.log('cmd: ' + ytdlCommand); + return new Promise((resolve) => { + exec(ytdlCommand, async function (error, stdout, stderr) { + if (error) { + console.log('error: ' + error); + console.log('stderror: ' + stderr); + return resolve( + returnError(res, 'unable to get YouTube video captions') + ); + } + + // find the file we just wrote + const files = await fs.readdir(spaths.videos); + const transcriptFile = files.find((file) => file.startsWith(filePrefix)); + if (transcriptFile === undefined) { + return resolve( + returnError(res, 'unable to get YouTube video captions') + ); + } + + await getTranscriptAndCreateDigest({ + res, + userId, + title, + ytid, + videoLength, + next, + captionsPath: path.join(spaths.videos, transcriptFile), + }); + resolve(); + }); + }); +} /** * Returns the editor js template (TODO consider bootstraping data) */ -exports.getEditor = function(req, res) { +exports.getEditor = function (req, res) { + // console.log(req.params); res.render('editor', { - title: 'Video Digest Editor' + title: 'Video Digest Editor', }); }; /** * Returns the readyness/processing status of the video digest */ -exports.getStatus = function(req, res) { - var uparsed = url.parse(req.url), - did = uparsed.query && querystring.parse(uparsed.query).id; - - VDigest.findById(did, function (err, vd) { - var vstatus = 0; - var msg = ""; - console.log(vd.state); - if (err || !vd) { - msg = "unable to load the video digest"; - } - else if (vd.isProcessing()) { - vstatus = 3; - msg = "video digest is processing"; - } - else if (vd.isReady()) { - vstatus = 1; - msg = "video digest is ready for editing"; - } - res.writeHead(200, {"content-type": "application/json"}); - res.end(JSON.stringify({"status": vstatus, "message": msg})); - }); +exports.getStatus = async function (req, res) { + const uparsed = url.parse(req.url); + const did = uparsed.query && querystring.parse(uparsed.query).id; + + let msg = ''; + let vd; + try { + vd = await VDigest.findByPk(did); + } catch (err) { + msg = 'unable to load the video digest'; + } + if (!vd) { + msg = 'unable to load the video digest'; + } else if (vd.isProcessing) { + vstatus = 3; + msg = 'video digest is processing'; + } else if (vd.isReady) { + vstatus = 1; + msg = 'video digest is ready for editing'; + } + + res.writeHead(200, { 'content-type': 'application/json' }); + res.end(JSON.stringify({ status: vstatus, message: msg })); }; +async function getCanUserEdit(user, vdid) { + if (!user || !vdid) { + return false; + } + try { + const ownership = await Ownership.findOne({ + where: { UserId: user.id, VDigestId: vdid }, + }); + return Boolean(ownership); + } catch (err) { + console.error('Error while fetching ownership', err); + return false; + } +} + /** * Returns the digest data needed for the editor /digestdata/:vid */ -exports.getDigestData = function (req, res, next) { - var vdid = req.params.vdid; - if (cache.get(vdid)) { - console.log("using vdid cache for: " + vdid); - res.writeHead(200, {"content-type": "application/json"}); - return res.end(cache.get(vdid)); +exports.getDigestData = async function (req, res, next) { + console.log('Getting digest data...'); + const vdid = req.params.vdid; + const userCanEdit = await getCanUserEdit(req.user, vdid); + const task = req.query.task; + + if (task !== 'edit' && task !== 'view') { + returnError(res, `invalid data task: ${task}`); + return; + } + if (task === 'edit' && !userCanEdit) { + returnError(res, 'user does not have access to digest', next); + return; } - VDigest.findById(vdid, function (err, vd) { - if (err || !vd) { - returnError(res, "unable to load the specified video digest data", next); - } - else if (vd.isProcessing()) { - returnError(res, "the video digest is currently processing", next); - } - else if (!vd.isReady()) { - returnError(res, "the transcript did not upload correctly: please create the video digest from scratch", next); - } else { - res.writeHead(200, {"content-type": "application/json"}); - var jsonStrResp = JSON.stringify({"digest": vd.digest, "transcript": vd.alignTrans, "ytid": vd.ytid, "videoLength": vd.videoLength}); - res.end(jsonStrResp); - cache.put(vdid, jsonStrResp, 10000000); - } - }); -}; + const cachedData = cache.get(vdid); + if (cachedData) { + console.log('Cache hit'); + } else { + console.log('Cache miss'); + } + + if ( + cachedData && + ((task === 'view' && JSON.parse(cachedData).pubdisplay) || + (task === 'edit' && userCanEdit)) + ) { + console.log('using vdid cache for: ' + vdid); + console.log(JSON.parse(cachedData).digest.chapters[0].sections); + res.writeHead(200, { 'content-type': 'application/json' }); + return res.end(cachedData); + } + + console.log('Not using cached data...'); + let vd; + try { + vd = await VDigest.findByPk(vdid); + } catch (err) { + returnError(res, 'unable to load the specified video digest data', next); + return; + } + if (!vd) { + returnError(res, 'unable to load the specified video digest data', next); + return; + } else if (task === 'view' && !vd.pubdisplay) { + returnError(res, 'video digest is not published', next); + } else if (task === 'edit' && !userCanEdit) { + returnError(res, 'user does not have access to digest', next); + } else if (vd.isProcessing) { + returnError(res, 'the video digest is currently processing', next); + } else if (!vd.isReady) { + returnError( + res, + 'the transcript did not upload correctly: please create the video digest from scratch', + next + ); + } else { + res.writeHead(200, { 'content-type': 'application/json' }); + const jsonStrResp = makeVDigestDataCacheObject(vd); + cache.put(vdid, jsonStrResp, 10000000); + res.end(jsonStrResp); + } +}; /** * Post to the digest data /digestdata/:vid */ -exports.postPublishDigest = function(req, res, next) { +exports.postPublishDigest = async function (req, res, next) { var vdid = req.params.vdid; - if (req.user.vdigests.indexOf(vdid) === -1) { - returnError(res, "you do not have the access to publish this digest", next); + if (!(await getCanUserEdit(req.user, vdid))) { + returnError(res, 'you do not have the access to publish this digest', next); return; } - VDigest.findById(vdid, function (err, vd) { - if (err || !vd) { - returnError(res, "unable to save the video digest data", next); - return; - } - if (!vd.pubdisplay) { - vd.pubdisplay = true; - vd.puburl = "http://vis.berkeley.edu/videodigests/view/" + slug(vd.digest.title + " " + vd.id); - vd.save(); + const publish = Boolean(req.body.publish); + const unlisted = Boolean(req.body.unlisted); + + let vd; + try { + vd = await VDigest.findByPk(vdid); + } catch (err) { + returnError(res, 'unable to save the video digest data', next); + return; + } + if (!vd) { + returnError(res, 'unable to save the video digest data', next); + return; + } + try { + if (publish) { + vd.pubdisplay = !unlisted; + if (!vd.puburl) { + vd.puburl = slug(vd.digest.title); + } + await vd.save(); + } else { + vd.pubdisplay = false; + vd.puburl = null; + await vd.save(); } - res.writeHead(200, {"content-type": "application/json"}); - res.end(JSON.stringify({"status": "success", "message": "published the video digest", puburl: vd.puburl})); - }); + // clear the cache + cache.del(vdid); + res.writeHead(200, { 'content-type': 'application/json' }); + res.end( + JSON.stringify({ + status: 'success', + message: 'published the video digest', + puburl: vd.puburl, + }) + ); + } catch (err) { + returnError(res, 'unable to save the video digest data', next); + return; + } }; /** * Post to the digest data /digestdata/:vid */ -exports.postDigestData = function(req, res, next) { +exports.postDigestData = async function (req, res, next) { var vdid = req.params.vdid; + let vd; + try { + vd = await VDigest.findByPk(vdid); + } catch (err) { + returnError(res, 'unable to save the video digest data', next); + return; + } + if (!vd) { + returnError(res, 'unable to save the video digest data', next); + return; + } - VDigest.findById(vdid, function (err, vd) { - if (err || !vd) { - returnError(res, "unable to save the video digest data", next); - return; - } - - // TODO remove audioName check used for VD experiment - if ((!req.user || req.user.vdigests.indexOf(vdid) === -1) && vd.audioName != 'Fpz-stC1uh8') { - returnError(res, "you do not have the access to change this digest", next); - return; - } + if (!(await getCanUserEdit(req.user, vdid))) { + returnError(res, 'you do not have the access to change this digest', next); + return; + } - vd.digest = req.body.object; - vd.save(function (err) { - // TODO check that the the user can save the data - if (err) { - returnError(res, "unable to save the video digest data", next); - return; - } - res.writeHead(200, {"content-type": "application/json"}); - res.end(JSON.stringify({"status": "success", "message": "saved the video digest data"})); - }); - }); -}; + vd.title = req.body.object.title; + vd.digest = req.body.object; + try { + await vd.save(); + } catch (err) { + returnError(res, 'unable to save the video digest data', next); + return; + } + // update memory cache + const jsonStrResp = makeVDigestDataCacheObject(vd); + cache.put(vdid, jsonStrResp, 10000000); + + res.writeHead(200, { 'content-type': 'application/json' }); + res.end( + JSON.stringify({ + status: 'success', + message: 'saved the video digest data', + }) + ); +}; // multipart process for loading a new video -exports.postNewVD = function(req, res, next) { +exports.postNewVD = function (req, res, next) { req.assert('yturl', 'YouTube URL is not a valid URL').isURL(); if (!req.user) { - returnError(res, "You must be logged in to create a video digest", next); + returnError(res, 'You must be logged in to create a video digest', next); return; } @@ -202,395 +703,209 @@ exports.postNewVD = function(req, res, next) { var form = new multiparty.Form({ maxFilesSize: settings.maxTransUploadSize, - uploadDir: spaths.rawTrans + uploadDir: spaths.rawTrans, }); - form.parse(req, function (err, fields, files) { + form.parse(req, async function (err, fields, files) { if (err) { returnError(res, err.message, next); return; } - var ytparsed = url.parse(fields.yturl && fields.yturl[0]), - ytid = ytparsed.query && querystring.parse(ytparsed.query).v; - if (!(ytparsed.hostname === "youtube.com" || ytparsed.hostname === "www.youtube.com") || !ytid) { + const ytparsed = url.parse(fields.yturl && fields.yturl[0]); + const ytid = ytparsed.query && querystring.parse(ytparsed.query).v; + const userId = req.user.id; + + if ( + !( + ytparsed.hostname === 'youtube.com' || + ytparsed.hostname === 'www.youtube.com' + ) || + !ytid + ) { // TODO return informative messages to the user (how to do this?) - returnError(res, "you must proivde a YouTube url in the format: http://www.youtube.com/watch?v=someIdValue", next); + returnError( + res, + 'You must provide a YouTube url in the format: https://www.youtube.com/watch?v=someIdValue', + next + ); return; } - var ytaddr = "https://www.youtube.com/watch?v=" + ytid; - - if (files.tranupload || (fields.usegtrans && fields.usegtrans[0])) { - - var vidFile = pathUtils.getVideoFile(ytid); - var sendGoodResponse = function () { - // read the text so we can store it into - var vlencmd = "nice -n 20 ffprobe -loglevel error -show_streams " + vidFile + " | grep duration= | cut -f2 -d= | head -n 1"; - exec(vlencmd, function (err, vlen) { - if (err) { - returnError(res, "unable to determine video length", next); - return; - } - var tfname, - rawTransFile; - if (fields.usegtrans) { - tfname = ytid + ".srt"; - // TODO convert SRT to text and move to appropo location - fs.readFile(path.join(spaths.videos, ytid + ".en.srt"), "utf8", function (err, data) { - if (err) { - return returnError(res, "unable to get YouTube transcript"); - } - var writeData = srtToText(data); - tfname = ytid + ".txt"; - rawTransFile = path.join(spaths.rawTrans, ytid + ".txt"); - fs.writeFile(rawTransFile, writeData, function (err) { - if (err) { - return returnError(res, "unable to get YouTube transcript"); - } - saveVD(); - // now call the ready function - }); - }); - } else { - var fp = files.tranupload[0].path.split(path.sep); - tfname = fp[fp.length - 1]; - saveVD(); - } - function saveVD () { - var vd = new VDigest({ytid: ytid, rawTransName: tfname, videoName: ytid, videoLength: vlen, digest: {title: fields.yttitle[0]}}); - vd.save(function (err) { - if (err) { - console.log(err); - returnError(res, "problem saving video digest to the database -- please try again", next); - return; - } else { - res.writeHead(200, {'content-type': 'application/json'}); - res.write('{"intrmid":"' + vd._id +'"}'); - res.end(); - return; - } - }); - }; - }); - }; // end sendGoodResponse + const step = fields.step[0]; + + if (step === '1') { + let info = undefined; + try { + info = await ytdl.getInfo(youtubeUrlFromId(ytid)); + } catch (err) { + console.log(err); + console.log(err.message); + returnError( + res, + 'Unable to find a YouTube Video with the given URL', + next + ); + return; + } - // download the yt video - var downloading = false; - fs.exists(vidFile, function (exists) { - if (downloading) { + const { videoDetails } = info.playerResponse; + const imageUrl = videoDetails.thumbnail.thumbnails[0].url; + const { title, lengthSeconds } = videoDetails; + + const subopts = getYouTubeSubtitleOptions(info); + + const payload = { + iurl: imageUrl, + title, + subopts, + lengthSeconds: parseInt(lengthSeconds, 10), + }; + res.writeHead(200, { 'content-type': 'application/json' }); + res.write(JSON.stringify(payload)); + res.end(); + return; + } else if (step === '2') { + if (fields.trantype && VALID_TRANSCRIPT_TYPES.has(fields.trantype[0])) { + const transcriptType = fields.trantype[0]; + if (transcriptType === 'upload') { + res.writeHead(200, { 'content-type': 'application/json' }); + res.write(JSON.stringify({ tranupload: true })); + res.end(); return; } - else { - - // first download the video transcript if necessary - var ytdl_cmd = "youtube-dl -f mp4 --write-auto-sub -o '" + path.join(spaths.videos, ytid) + ".%(ext)s'" + " " + ytaddr; - - - //var vidWS = fs.createWriteStream(vidFile); - ytdl.getInfo(ytaddr, function(err, info) { - if (info.length_seconds > settings.max_yt_length || err) { - returnError(res, (err && err.message) || ("Video length exceeds " + Math.floor(settings.max_yt_length/60) + " minutes"), next); - return; - } - - downloading = true; - console.log("cmd: " + ytdl_cmd); - exec(ytdl_cmd, function (error, stdout, stderr) { - downloading = false; - if (error) { - console.log("error: " + error); - console.log("stderror: " + stderr); - return returnError(res, "unable to load YouTube video properly"); - } - sendGoodResponse(); - }); - }); + try { + await getSmallVideo({ ytid }); + } catch (err) { + returnError( + res, + 'Unable to get YouTube Video with the given URL', + next + ); } - }); - - } else if (fields.intrmid && fields.intrmid[0]) { - if (!Number(fields.createdigest[0])) { - returnError(res, "you must select 'yes' to continue", next); + await getTranscript({ + res, + userId, + title: fields.yttitle[0], + videoLength: parseInt(fields.lengthSeconds[0], 10), + next, + ytid, + transcriptType, + }); return; } - - var intrmid = fields.intrmid[0]; - // set the state to 2 - // first clean the text - VDigest.findById(intrmid, function (err1, vdigest) { - if (err1 || !vdigest || !vdigest.rawTransName || ! vdigest.videoName) { - returnError(res, "encountered a problem loading the video digest data: please try resubmitting", next); - return; + } else if (step === '3') { + // handle custom captions upload + if (files.tranupload && files.tranupload[0]) { + const captionsPath = files.tranupload[0].path; + console.log(files.tranupload, captionsPath); + try { + await getSmallVideo({ ytid }); + } catch (err) { + returnError( + res, + 'Unable to get YouTube Video with the given URL', + next + ); } - vdigest.state = 2; - vdigest.save(); - - var vname = vdigest.videoName, - aname = vname, - inVideoFile = vdigest.getVideoFile(), - outAudioFile = pathUtils.getAudioFile(aname), - outAlignTrans = path.join(spaths.tmp, aname + "_aligned.json"), - state = 0; - - // - // Clean up the text - // - var rtxtfile = path.join(spaths.rawTrans, vdigest.rawTransName); - fs.readFile(rtxtfile, 'utf8', function (err2, data) { - if (err2) { - returnError(res, "encountered a problem processing the transcript: is it a plain text file?", next); - return; - } - - // convert if it's an srt file - var newLineData = data.split("\n"); - if (newLineData.length > 2 && newLineData[0] == "1" && /-->/.test(newLineData[1])) { - data = srtToText(data); - fs.writeFile(rtxtfile, data); - } - - var paragraphs = data.split("."), - out = [], - line, - spkct = 0; - paragraphs.forEach(function (para, i) { - if ((i + 1) % 4 == 0) { - spkct += 1; - } - para = para.replace("\n", " "); - para = para.replace(/[^-\w\d,.?!\(\)' ]/g, ""); - para = para.replace(/\s+[^\w]+\s+/g, ""); - para = para.replace(/\s+/g, " "); - if (para.replace(/\s+/g, "") !== "") { - line = { - speaker: "" + spkct, - "line": para - }; - out.push(line); - } - }); - vdigest.preAlignTrans = out; - vdigest.save(function (err) { - if (err) { - returnError(res, "encountered a problem processing the transcript: is it a plain text file?", next); - return; - } - console.log("transcript is finished"); - if (state === 3) { - alignTranscript(); - } else { - state = 3; - vdigest.state = state; - vdigest.save(); - } - }); + return await getTranscriptAndCreateDigest({ + res, + userId, + title: fields.yttitle[0], + videoLength: parseInt(fields.lengthSeconds[0], 10), + ytid, + captionsPath, + next, }); - - // - // Extract the audio from the video in the appropriate format - // - var child, - cmd; - cmd = "nice -n 20 ffmpeg -i " + inVideoFile + " -acodec pcm_s16le -y " + outAudioFile; - console.log(cmd); - // executes `pwd` - child = exec(cmd, function (error, stdout, stderr) { - if (error !== null) { - returnError(res, "error processing the video", next); - console.log('exec error: ' + error); - return; - } - vdigest.audioName = aname; - vdigest.save(); - console.log("audio is finished"); - if (state === 3) { - alignTranscript(); - } else { - state = 3; - vdigest.state = state; - vdigest.save(); - } - }); - - - var alignTranscript = function () { - var outPreFile = path.join(spaths.tmp, vdigest.videoName + ".json"); - fs.writeFile(outPreFile, JSON.stringify(vdigest.preAlignTrans), function (err) { - if (err) { - returnError(res, "error parsing video transcript", next); - return; - } - - // make a temporary working dir for the alignment process - var tmpAlignDir = path.join(spaths.tmp, vname); - mkdirp(tmpAlignDir, function (err0) { - if (err0 !== null) { - console.log('exec error: ' + err0); - returnError(res, "system error creating the aligned transcript", next); - return; - } - - res.writeHead(200, {'content-type': 'application/json'}); - res.write('{"readyid":"' + vdigest._id +'"}'); - res.end(); - - var alignCmd = "nice -n 20 python " + spaths.alignpy + " " - + outAudioFile + " " + outPreFile + " " + outAlignTrans - + " > " + outAlignTrans + "-output"; - console.log("starting alignment command"); - console.log(alignCmd); - - // get the user account - User.findById(req.user.id, function(err, user) { - if (err) return next(err); - if (!~user.vdigests.indexOf(vdigest.id)) { - user.vdigests.push(vdigest.id); - user.save(); - } - }); - - // add this video digest to their account - child = exec(alignCmd, {cwd: tmpAlignDir}, function (error, stdout, stderr) { - if (error !== null) { - console.log('exec error: ' + error); - returnError(res, "error creating the aligned transcript", next); - return; - } - - console.log("finished processing vdigest"); - fs.readFile(outAlignTrans, 'utf8', function (err2, data) { - console.log("done reading the aligned transcript"); - var alignTrans = JSON.parse(data); - // TODO why do we have this first word error? - alignTrans.words[0].speaker = "0"; - vdigest.alignTrans = alignTrans; - vdigest.state = 1; - vdigest.save(function (err) { - if (err) { - console.log("unable to save the video digest"); - console.log(err); - return; - } - - // now generate the sentences - var sentCall = "python add_sentences " + vdigest.id; - exec(sentCall, {cwd: spaths.analysis}, function () { - // send email to user - var from = "video.digests@vis.berkeley.edu"; - var name = "video-digest admin"; - var body = "Hello " + req.user.profile.name +",\n\n" - + "The transcript-video alignment is finished and you may now edit your video digest at: http://vis.berkeley.edu/videodigests/editor#edit/" + vdigest._id + "\n\n" - + "Best wishes,\n -Friendly Neighborhood Video Digest Bot"; - - var to = req.user.email; - var subject = 'Video Digests: Video-transcript alignment complete'; - - var mailOptions = { - to: to, - from: from, - subject: subject, - text: body - }; - - smtpTransport.sendMail(mailOptions, function(err) { - if (err) { - console.log(err); - } - }); - }); - }); - }); - });// end align command - }); // end make temporary directory - }); - }; - }); - } else { - // No files: first upload - // TODO check/handle for existing transcript - // obtain video info and save to DB if video does not exist - // TODO handle incorrect urls ? what happens? - ytdl.getInfo(ytaddr, function(err, info) { - if (err && err.message) { - returnError(res, "unable to find a YouTube Video with the given URL", next); - return; - } - res.writeHead(200, {'content-type': 'application/json'}); - res.write(JSON.stringify(info)); - res.end(); - }); + } } + + returnError(res, 'Unknown error! Please try again', next); }); + return; }; - -exports.getAutoSeg = function (req, res, next) { +exports.getAutoSeg = async function (req, res, next) { // get the transcript - VDigest.findById(req.params.vdid, function (err, vdigest) { - if (err || !vdigest) { - return returnErrorJson(res, err); - } - - if (!vdigest.rawTransName) { - var transText = vdigest.alignTrans.words.map(function (wrd) { + let vd; + try { + vd = await VDigest.findByPk(req.params.vdid); + } catch (err) { + return returnErrorJson(res, err); + } + if (!vd) { + return returnErrorJson(res, err); + } + if (!vdigest.rawTransName) { + var transText = vdigest.alignTrans.words + .map(function (wrd) { return wrd.word; - }).join(" ").replace(" {p}", ""); - vdigest.rawTransName = Math.random().toString(36).substr(6) + ".txt"; - var outfile = path.join(spaths.rawTrans, vdigest.rawTransName); - fs.writeFile(outfile, transText, function (err) { - if (err) { - return returnErrorJson(res, err, 500); + }) + .join(' ') + .replace(' {p}', ''); + vdigest.rawTransName = Math.random().toString(36).substr(6) + '.txt'; + var outfile = path.join(spaths.rawTrans, vdigest.rawTransName); + try { + await fs.writeFile(outfile, transText); + } catch (err) { + return returnErrorJson(res, err, 500); + } + } + doSysCall(); + + function doSysCall() { + var rtxtfile = vdigest.getSSFile(); + var segSysCall = + 'python adv_seg.py eval ' + spaths.segConfigFile + ' ' + rtxtfile; + // execute system call + if (!vdigest.sentSepTransName) { + console.log('trying to generate separated transcript'); + var scmd = 'python add_sentences.py ' + vdigest.id; + console.log(scmd); + + exec(scmd, { cwd: spaths.utils }, function (err, stdout, stderr) { + console.log('error: ' + err); + console.log('error: ' + stderr); + if (err || !vdigest.sentSepTransName) { + return returnErrorJson( + res, + { msg: 'error processing transcript - please try again later' }, + 500 + ); + } else { + doSysCall(); } - doSysCall(); }); } else { - doSysCall(); - } - - function doSysCall() { - var rtxtfile = vdigest.getSSFile(); - var segSysCall = "python adv_seg.py eval " + spaths.segConfigFile + " " + rtxtfile; - // execute system call - if (!vdigest.sentSepTransName) { - console.log("trying to generate separated transcript"); - var scmd = "python add_sentences.py " + vdigest.id; - console.log( scmd ); - - exec(scmd, {cwd: spaths.utils}, function (err, stdout, stderr) { - console.log("error: " + err); - console.log("error: " + stderr); - if (err || !vdigest.sentSepTransName) { - return returnErrorJson(res, {msg: "error processing transcript - please try again later"}, 500); - } else { - doSysCall(); - } - }); - } else { - console.log(segSysCall); - var segProc = exec(segSysCall, {cwd: spaths.analysis}, function (error, stdout, stderr) { - console.log("finished segmentation"); - console.log("error: " + error) - console.log("stderror: " + stderr) - console.log("stdout: " + stdout) - // get sentence breaks from stdout - if (error || stderr) { - return returnErrorJson(res, {"msg": "Segmentation error -- please try again: " + stderr}); - } - try{ - var sps = stdout.split("\n"); - var sentBreaks = sps[sps.length-4]; - return returnJson(res, {breaks: sentBreaks}); - } catch (e) { - return returnErrorJson(res, {"msg": "Segmentation error -- please try again"}); - } - // read results from system call or return error - // return the word/sentence numbers - }); - } + console.log(segSysCall); + var segProc = exec(segSysCall, { cwd: spaths.analysis }, function ( + error, + stdout, + stderr + ) { + console.log('finished segmentation'); + console.log('error: ' + error); + console.log('stderror: ' + stderr); + console.log('stdout: ' + stdout); + // get sentence breaks from stdout + if (error || stderr) { + return returnErrorJson(res, { + msg: 'Segmentation error -- please try again: ' + stderr, + }); + } + try { + var sps = stdout.split('\n'); + var sentBreaks = sps[sps.length - 4]; + return returnJson(res, { breaks: sentBreaks }); + } catch (e) { + return returnErrorJson(res, { + msg: 'Segmentation error -- please try again', + }); + } + // read results from system call or return error + // return the word/sentence numbers + }); } - }); - - + } }; diff --git a/controllers/home.js b/controllers/home.js index 72246a2..668b982 100644 --- a/controllers/home.js +++ b/controllers/home.js @@ -3,14 +3,14 @@ * Home page. */ -exports.index = function(req, res) { +exports.index = function (req, res) { res.render('home', { - title: 'Home' + title: 'Home', }); }; -exports.tutorial = function(req, res) { +exports.tutorial = function (req, res) { res.render('tutorial', { - title: 'Video Digest Tutorial' + title: 'Video Digest Tutorial', }); }; diff --git a/controllers/screenshot.js b/controllers/screenshot.js index 990b6d6..0425359 100644 --- a/controllers/screenshot.js +++ b/controllers/screenshot.js @@ -3,55 +3,95 @@ * Return a screenshot of the given video at the given time */ /*global require exports Buffer*/ -var fs = require('fs'), - VDigest = require('../models/VDigest'), - path = require('path'), - pathUtils = require('../utils/fpaths'), - spaths = require('../config/settings').paths, - exec = require('child_process').exec, - returnError = require('../utils/errors').returnError; +const fs = require('fs'); +const { VDigest } = require('../models/VDigest'); +const path = require('path'); +const pathUtils = require('../utils/fpaths'); +const { paths: spaths } = require('../config/settings'); +const { exec } = require('child_process'); +const { returnError } = require('../utils/errors'); +const { getSmallVideo } = require('./video-download'); -exports.getScreenShot = function (req, res, next) { - var vdid = req.query.id, - time = req.query.time.substr(0, 6) || 0, - usetime; +exports.getScreenShot = async function (req, res, next) { + const vdid = req.query.id; + const time = req.query.time.substr(0, 6) || 0; + let usetime; try { usetime = Number(time); if (usetime < 0) { - throw new Error("screenshot time is out of bounds"); + throw new Error('screenshot time is out of bounds'); } } catch (e) { - returnError(res, "time must be a nonegative number and indicate the the second value of the screenshot", next); + returnError( + res, + 'time must be a nonegative number and indicate the the second value of the screenshot', + next + ); } - VDigest.findById(vdid, function (err, vd) { - if (err || !vd || !vd.videoName) { - returnError(res, "cannot create a screenshot: unable to find the given video digest", next); - return; - } - usetime = Math.min(usetime, vd.videoLength - 0.3); // TODO fix the screenshot edge case - var videoFile = vd.getVideoFile(), - outssFile = pathUtils.getScreenShotFile(vd.videoName, usetime), - cmd = "nice -n 10 ffmpeg -ss " + usetime + " -i " + videoFile + " -f image2 -vframes 1 -y " + outssFile; - console.log( cmd ); + let vd; + try { + vd = await VDigest.findByPk(vdid); + } catch (err) { + returnError( + res, + 'cannot create a screenshot: unable to find the given video digest', + next + ); + return; + } + if (!vd || !vd.videoName) { + returnError( + res, + 'cannot create a screenshot: unable to find the given video digest', + next + ); + return; + } - exec(cmd, function (err2) { - console.log( "finished execution" ); + usetime = Math.min(usetime, vd.videoLength - 0.3); // TODO fix the screenshot edge case + const ytid = vd.videoName; + try { + await getSmallVideo({ ytid }); + } catch (err) { + // file doesn't exist + returnError( + res, + 'cannot create a screenshot: unable to get the given video', + next + ); + return; + } + + const videoFile = vd.getVideoFile; + const outssFile = pathUtils.getScreenShotFile(ytid, usetime); + const cmd = + 'nice -n 10 ffmpeg -ss ' + + usetime + + ' -i ' + + videoFile + + ' -f image2 -vframes 1 -y ' + + outssFile; + console.log(cmd); + + exec(cmd, function (err2) { + console.log('finished execution'); + if (err2) { + returnError(res, 'system error while taking screenshot', next); + return; + } + fs.readFile(outssFile, function (err3, img) { if (err2) { - returnError(res, "system error while taking screenshot", next); + returnError(res, 'system error while taking screenshot', next); return; } - fs.readFile(outssFile, function (err3, img) { - if (err2) { - returnError(res, "system error while taking screenshot", next); - return; - } - var base64Image = "data:image/jpeg;base64," + (new Buffer(img, 'binary').toString('base64')); - res.writeHead(200, {'content-type': 'text/plain'}); - res.end(base64Image); - }); + const base64Image = + 'data:image/jpeg;base64,' + + new Buffer(img, 'binary').toString('base64'); + res.writeHead(200, { 'content-type': 'text/plain' }); + res.end(base64Image); }); }); }; diff --git a/controllers/url-helpers.js b/controllers/url-helpers.js new file mode 100644 index 0000000..25913d1 --- /dev/null +++ b/controllers/url-helpers.js @@ -0,0 +1,6 @@ +function youtubeUrlFromId(ytid) { + return `https://www.youtube.com/watch?v=${ytid}`; +} +module.exports = { + youtubeUrlFromId, +}; diff --git a/controllers/user.js b/controllers/user.js index fc86c7a..8fa9938 100644 --- a/controllers/user.js +++ b/controllers/user.js @@ -3,7 +3,8 @@ var async = require('async'); var crypto = require('crypto'); var nodemailer = require('nodemailer'); var passport = require('passport'); -var User = require('../models/User'); +const User = require('../models/User'); +const { VDigest } = require('../models/VDigest'); var secrets = require('../config/secrets'); /** @@ -11,10 +12,10 @@ var secrets = require('../config/secrets'); * Login page. */ -exports.getLogin = function(req, res) { - if (req.user) return res.redirect('/videodigests'); +exports.getLogin = function (req, res) { + if (req.user) return res.redirect('/'); res.render('account/login', { - title: 'Login' + title: 'Login', }); }; @@ -25,28 +26,27 @@ exports.getLogin = function(req, res) { * @param password */ -exports.postLogin = function(req, res, next) { +exports.postLogin = function (req, res, next) { req.assert('email', 'Email is not valid').isEmail(); req.assert('password', 'Password cannot be blank').notEmpty(); - var errors = req.validationErrors(); if (errors) { req.flash('errors', errors); - return res.redirect('/videodigests/login'); + return res.redirect('/login'); } - passport.authenticate('local', function(err, user, info) { + passport.authenticate('local', function (err, user, info) { if (err) return next(err); if (!user) { req.flash('errors', { msg: info.message }); return res.redirect('/login'); } - req.logIn(user, function(err) { + req.logIn(user, function (err) { if (err) return next(err); req.flash('success', { msg: 'Success! You are logged in.' }); - res.redirect('/videodigests'); // TODO + res.redirect('/'); // TODO }); })(req, res, next); }; @@ -56,7 +56,7 @@ exports.postLogin = function(req, res, next) { * Log out. */ -exports.logout = function(req, res) { +exports.logout = function (req, res) { req.logout(); res.redirect('/'); }; @@ -66,10 +66,10 @@ exports.logout = function(req, res) { * Signup page. */ -exports.getSignup = function(req, res) { +exports.getSignup = function (req, res) { if (req.user) return res.redirect('/'); - res.render('videodigests/account/signup', { - title: 'Create Account' + res.render('account/signup', { + title: 'Create Account', }); }; @@ -80,39 +80,45 @@ exports.getSignup = function(req, res) { * @param password */ -exports.postSignup = function(req, res, next) { +exports.postSignup = async function (req, res, next) { req.assert('email', 'Email is not valid').isEmail(); req.assert('password', 'Password must be at least 4 characters long').len(4); - req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password); - req.assert('beta', "Incorrect beta code").equals(secrets.betaPW); - req.assert('name', 'Please fill in your name so we know what to call you =)').notEmpty(); + req + .assert('confirmPassword', 'Passwords do not match') + .equals(req.body.password); + req.assert('beta', 'Incorrect beta code').equals(secrets.betaPW); + req + .assert('name', 'Please fill in your name so we know what to call you =)') + .notEmpty(); var errors = req.validationErrors(); if (errors) { req.flash('errors', errors); - return res.redirect('/videodigests/signup'); + return res.redirect('/signup'); } - var user = new User({ - email: req.body.email, - password: req.body.password, - profile: {name: req.body.name} - }); + const existingUser = await User.findOne({ where: { email: req.body.email } }); + if (existingUser) { + req.flash('errors', { + msg: 'Account with that email address already exists.', + }); + return res.redirect('/signup'); + } - User.findOne({ email: req.body.email }, function(err, existingUser) { - if (existingUser) { - req.flash('errors', { msg: 'Account with that email address already exists.' }); - return res.redirect('/videodigests/signup'); - } - user.save(function(err) { + try { + const user = await User.create({ + email: req.body.email, + password: req.body.password, + name: req.body.name, + }); + req.logIn(user, function (err) { if (err) return next(err); - req.logIn(user, function(err) { - if (err) return next(err); - res.redirect('/videodigests'); - }); + res.redirect('/'); }); - }); + } catch (err) { + return next(err); + } }; /** @@ -120,21 +126,25 @@ exports.postSignup = function(req, res, next) { * Profile page. */ -exports.getAccount = function(req, res) { - User.findById(req.user.id) - .populate("vdigests", "digest.title puburl id") - .exec(function (err, user) { - if (err) { - console.log(err); // TODO handle error - req.flash('error', { msg: 'There was a problem loading your profile.' }); - res.redirect('/videodigests'); - } else { - res.render('account/profile', { - title: 'Account Management', - vds: user.vdigests - }); - } - }); +exports.getAccount = async function (req, res) { + try { + const user = await User.findByPk(req.user.id, { + include: VDigest, + through: { + attributes: ['title', 'puburl', 'id'], + }, + }); + res.render('account/profile', { + title: 'Account Management', + vds: user.VDigests, + }); + } catch (err) { + console.log(err); // TODO handle error + req.flash('error', { + msg: 'There was a problem loading your profile.', + }); + res.redirect('/'); + } }; /** @@ -142,21 +152,19 @@ exports.getAccount = function(req, res) { * Update profile information. */ -exports.postUpdateProfile = function(req, res, next) { - User.findById(req.user.id, function(err, user) { - if (err) return next(err); +exports.postUpdateProfile = async function (req, res, next) { + try { + const user = await User.findByPk(req.user.id); user.email = req.body.email || ''; - user.profile.name = req.body.name || ''; - user.profile.gender = req.body.gender || ''; - user.profile.location = req.body.location || ''; - user.profile.website = req.body.website || ''; - - user.save(function(err) { - if (err) return next(err); - req.flash('success', { msg: 'Profile information updated.' }); - res.redirect('/videodigests/account'); - }); - }); + user.name = req.body.name || ''; + user.location = req.body.location || ''; + user.website = req.body.website || ''; + await user.save(); + req.flash('success', { msg: 'Profile information updated.' }); + res.redirect('/account'); + } catch (err) { + return next(err); + } }; /** @@ -165,28 +173,28 @@ exports.postUpdateProfile = function(req, res, next) { * @param password */ -exports.postUpdatePassword = function(req, res, next) { +exports.postUpdatePassword = async function (req, res, next) { req.assert('password', 'Password must be at least 4 characters long').len(4); - req.assert('confirmPassword', 'Passwords do not match').equals(req.body.password); + req + .assert('confirmPassword', 'Passwords do not match') + .equals(req.body.password); var errors = req.validationErrors(); if (errors) { req.flash('errors', errors); - return res.redirect('/videodigests/account'); + return res.redirect('/account'); } - User.findById(req.user.id, function(err, user) { - if (err) return next(err); - + try { + const user = await User.findByPk(req.user.id); user.password = req.body.password; - - user.save(function(err) { - if (err) return next(err); - req.flash('success', { msg: 'Password has been changed.' }); - res.redirect('/videodigests/account'); - }); - }); + await user.save(); + req.flash('success', { msg: 'Password has been changed.' }); + res.redirect('/account'); + } catch (err) { + return next(err); + } }; /** @@ -195,35 +203,17 @@ exports.postUpdatePassword = function(req, res, next) { * @param id - User ObjectId */ -exports.postDeleteAccount = function(req, res, next) { - User.remove({ _id: req.user.id }, function(err) { - if (err) return next(err); +exports.postDeleteAccount = async function (req, res, next) { + try { + const user = await User.findByPk(req.user.id); + if (user) { + await user.destroy(); + } req.logout(); - res.redirect('/videodigests'); - }); -}; - -/** - * GET /account/unlink/:provider - * Unlink OAuth2 provider from the current user. - * @param provider - * @param id - User ObjectId - */ - -exports.getOauthUnlink = function(req, res, next) { - var provider = req.params.provider; - User.findById(req.user.id, function(err, user) { - if (err) return next(err); - - user[provider] = undefined; - user.tokens = _.reject(user.tokens, function(token) { return token.kind === provider; }); - - user.save(function(err) { - if (err) return next(err); - req.flash('info', { msg: provider + ' account has been unlinked.' }); - res.redirect('/videodigests/account'); - }); - }); + res.redirect('/'); + } catch (err) { + return next(err); + } }; /** @@ -231,23 +221,38 @@ exports.getOauthUnlink = function(req, res, next) { * Reset Password page. */ -exports.getReset = function(req, res) { +exports.getReset = async function (req, res) { if (req.isAuthenticated()) { - return res.redirect('/videodigests'); + return res.redirect('/'); } - User - .findOne({ resetPasswordToken: req.params.token }) - .where('resetPasswordExpires').gt(Date.now()) - .exec(function(err, user) { - if (!user) { - req.flash('errors', { msg: 'Password reset token is invalid or has expired.' }); - return res.redirect('/videodigests/forgot'); - } - res.render('account/reset', { - title: 'Password Reset' + try { + const user = await User.findOne({ + where: { resetPasswordToken: req.params.token }, + }); + console.log( + 'Reset expiration date:', + user ? user.resetPasswordExpires : 'not found' + ); + if ( + !user || + !user.resetPasswordExpires || + user.resetPasswordExpires < new Date() + ) { + req.flash('errors', { + msg: 'Password reset token is invalid or has expired.', }); + return res.redirect('/forgot'); + } + res.render('account/reset', { + title: 'Password Reset', + }); + } catch (err) { + req.flash('errors', { + msg: 'Password reset token is invalid or has expired.', }); + return res.redirect('/forgot'); + } }; /** @@ -255,7 +260,7 @@ exports.getReset = function(req, res) { * Process the reset password request. */ -exports.postReset = function(req, res, next) { +exports.postReset = async function (req, res, next) { req.assert('password', 'Password must be at least 4 characters long.').len(4); req.assert('confirm', 'Passwords must match.').equals(req.body.password); @@ -266,53 +271,70 @@ exports.postReset = function(req, res, next) { return res.redirect('back'); } - async.waterfall([ - function(done) { - User - .findOne({ resetPasswordToken: req.params.token }) - .where('resetPasswordExpires').gt(Date.now()) - .exec(function(err, user) { - if (!user) { - req.flash('errors', { msg: 'Password reset token is invalid or has expired.' }); - return res.redirect('back'); - } - - user.password = req.body.password; - user.resetPasswordToken = undefined; - user.resetPasswordExpires = undefined; - - user.save(function(err) { - if (err) return next(err); - req.logIn(user, function(err) { - done(err, user); - }); - }); - }); - }, - function(user, done) { - var smtpTransport = nodemailer.createTransport('SMTP', { - service: 'Mailgun', - auth: { - user: secrets.mailgun.user, - pass: secrets.mailgun.password + try { + const user = await User.findOne({ + where: { resetPasswordToken: req.params.token }, + }); + if ( + !user || + !user.resetPasswordExpires || + user.resetPasswordExpires < new Date() + ) { + req.flash('errors', { + msg: 'Password reset token is invalid or has expired.', + }); + return res.redirect('back'); + } + + user.password = req.body.password; + user.resetPasswordToken = undefined; + user.resetPasswordExpires = undefined; + await user.save(); + + await new Promise((resolve, reject) => { + req.logIn(user, function (err) { + if (err) { + reject(err); + } else { + resolve(); } }); - var mailOptions = { - to: user.email, - from: 'hackathon@starter.com', - subject: 'Your Hackathon Starter password has been changed', - text: 'Hello,\n\n' + - 'This is a confirmation that the password for your account ' + user.email + ' has just been changed.\n' - }; - smtpTransport.sendMail(mailOptions, function(err) { - req.flash('success', { msg: 'Success! Your password has been changed.' }); - done(err); + }); + + const smtpTransport = nodemailer.createTransport('SMTP', { + service: 'Mailgun', + auth: { + user: secrets.mailgun.user, + pass: secrets.mailgun.password, + }, + }); + const mailOptions = { + to: user.email, + from: 'hackathon@starter.com', + subject: 'Your Hackathon Starter password has been changed', + text: + 'Hello,\n\n' + + 'This is a confirmation that the password for your account ' + + user.email + + ' has just been changed.\n', + }; + await new Promise((resolve, reject) => { + smtpTransport.sendMail(mailOptions, function (err) { + req.flash('success', { + msg: 'Success! Your password has been changed.', + }); + if (err) { + reject(err); + } else { + resolve(); + } }); - } - ], function(err) { - if (err) return next(err); - res.redirect('/videodigests'); - }); + }); + + res.redirect('/'); + } catch (err) { + return next(err); + } }; /** @@ -320,12 +342,12 @@ exports.postReset = function(req, res, next) { * Forgot Password page. */ -exports.getForgot = function(req, res) { +exports.getForgot = function (req, res) { if (req.isAuthenticated()) { - return res.redirect('/videodigests'); + return res.redirect('/'); } res.render('account/forgot', { - title: 'Forgot Password' + title: 'Forgot Password', }); }; @@ -335,62 +357,82 @@ exports.getForgot = function(req, res) { * @param email */ -exports.postForgot = function(req, res, next) { +exports.postForgot = async function (req, res, next) { req.assert('email', 'Please enter a valid email address.').isEmail(); var errors = req.validationErrors(); if (errors) { req.flash('errors', errors); - return res.redirect('/videodigests/forgot'); + return res.redirect('/forgot'); } - async.waterfall([ - function(done) { - crypto.randomBytes(16, function(err, buf) { - var token = buf.toString('hex'); - done(err, token); - }); - }, - function(token, done) { - User.findOne({ email: req.body.email.toLowerCase() }, function(err, user) { - if (!user) { - req.flash('errors', { msg: 'No account with that email address exists.' }); - return res.redirect('/videodigests/forgot'); + try { + const token = await new Promise((resolve, reject) => { + crypto.randomBytes(16, function (err, buf) { + if (err) { + reject(err); + } else { + var token = buf.toString('hex'); + resolve(token); } + }); + }); + + const user = await User.findOne({ + where: { email: req.body.email.toLowerCase() }, + }); + if (!user) { + req.flash('errors', { + msg: 'No account with that email address exists.', + }); + return res.redirect('/forgot'); + } + + user.resetPasswordToken = token; + user.resetPasswordExpires = Date.now() + 3600000; // 1 hour - user.resetPasswordToken = token; - user.resetPasswordExpires = Date.now() + 3600000; // 1 hour + await user.save(); - user.save(function(err) { - done(err, token, user); + const smtpTransport = nodemailer.createTransport('SMTP', { + service: 'Mailgun', + auth: { + user: secrets.mailgun.user, + pass: secrets.mailgun.password, + }, + }); + const mailOptions = { + to: user.email, + from: 'hackathon@starter.com', + subject: 'Reset your password on Hackathon Starter', + text: + 'You are receiving this email because you (or someone else) have requested the reset of the password for your account.\n\n' + + 'Please click on the following link, or paste this into your browser to complete the process:\n\n' + + 'http://' + + req.headers.host + + '/reset/' + + token + + '\n\n' + + 'If you did not request this, please ignore this email and your password will remain unchanged.\n', + }; + await new Promise((resolve, reject) => { + smtpTransport.sendMail(mailOptions, function (err) { + req.flash('info', { + msg: + 'An e-mail has been sent to ' + + user.email + + ' with further instructions.', }); - }); - }, - function(token, user, done) { - var smtpTransport = nodemailer.createTransport('SMTP', { - service: 'Mailgun', - auth: { - user: secrets.mailgun.user, - pass: secrets.mailgun.password + if (err) { + reject(err); + } else { + resolve(); } }); - var mailOptions = { - to: user.email, - from: 'hackathon@starter.com', - subject: 'Reset your password on Hackathon Starter', - text: 'You are receiving this email because you (or someone else) have requested the reset of the password for your account.\n\n' + - 'Please click on the following link, or paste this into your browser to complete the process:\n\n' + - 'http://' + req.headers.host + '/reset/' + token + '\n\n' + - 'If you did not request this, please ignore this email and your password will remain unchanged.\n' - }; - smtpTransport.sendMail(mailOptions, function(err) { - req.flash('info', { msg: 'An e-mail has been sent to ' + user.email + ' with further instructions.' }); - done(err, 'done'); - }); - } - ], function(err) { - if (err) return next(err); - res.redirect('/videodigests/forgot'); - }); + }); + + res.redirect('/forgot'); + } catch (err) { + return next(err); + } }; diff --git a/controllers/vdlist.js b/controllers/vdlist.js index cdbeaf9..595b831 100644 --- a/controllers/vdlist.js +++ b/controllers/vdlist.js @@ -1,16 +1,19 @@ - -var VDigest = require('../models/VDigest'); +const { VDigest } = require('../models/VDigest'); /** * GET /contact * Contact form page. */ -exports.getVDList = function(req, res) { +exports.getVDList = async function (req, res) { + const vds = await VDigest.findAll({ + where: { pubdisplay: true }, + attributes: ['id', 'puburl', 'title'], + order: [['createdAt', 'DESC']], + limit: 20, + }); -VDigest.find({}, "pubdisplay puburl digest.title", function (err, vds) { res.render('vdlist', { title: 'Video Digests', - vds: vds + vds, }); -}); }; diff --git a/controllers/video-download.js b/controllers/video-download.js new file mode 100644 index 0000000..27ae73d --- /dev/null +++ b/controllers/video-download.js @@ -0,0 +1,54 @@ +const { + promises: fs, + constants: { R_OK }, +} = require('fs'); +const path = require('path'); +const { exec } = require('child_process'); +const { paths: spaths } = require('../config/settings'); +const { youtubeUrlFromId } = require('./url-helpers'); + +async function getSmallVideo({ ytid }) { + console.log('Checking video file for: ', ytid); + const filename = `${ytid}.mp4`; + const videoPath = path.join(spaths.videos, filename); + try { + await fs.access(videoPath, R_OK); + // The file already exists + console.log('Video file already downloaded for:', ytid); + return; + } catch (err) { + // we need to download it + } + + console.log('Downloading video file for:', ytid); + + // get the worst quality video because we only need it for screenshots + const ytdlCommand = `youtube-dl -f worst --recode-video mp4 -o '${path.join( + spaths.videos, + `${ytid}.%(ext)s` + )}' ${youtubeUrlFromId(ytid)}`; + console.log('cmd: ' + ytdlCommand); + return new Promise((resolve, reject) => { + exec(ytdlCommand, async function (error, stdout, stderr) { + if (error) { + console.error('error:', error); + console.error('stderror:', stderr); + reject('unable to get YouTube video video'); + } else { + try { + // make sure it exists now + await fs.access(videoPath, R_OK); + console.log('Downloaded video file for: ', ytid); + resolve(); + } catch (err) { + console.error('error:', err); + reject(err); + } + } + }); + }); +} + +module.exports = { + getSmallVideo, +}; diff --git a/edit-interface.html b/edit-interface.html index ae12ceb..0738533 100755 --- a/edit-interface.html +++ b/edit-interface.html @@ -1,13 +1,14 @@ - Summary Interface + Video Digests Creator + - +
diff --git a/micromodal.min.js b/micromodal.min.js new file mode 100644 index 0000000..960c6e8 --- /dev/null +++ b/micromodal.min.js @@ -0,0 +1 @@ +Found. Redirecting to /micromodal@0.4.6/dist/micromodal.min.js \ No newline at end of file diff --git a/models/Ownership.js b/models/Ownership.js new file mode 100644 index 0000000..0171e03 --- /dev/null +++ b/models/Ownership.js @@ -0,0 +1,26 @@ +const sequelize = require('./sequelize'); +const { DataTypes } = require('sequelize'); +const User = require('./User'); +const { VDigest } = require('./VDigest'); + +const Ownership = sequelize.define('Ownership', { + UserId: { + type: DataTypes.STRING, + references: { + model: User, + key: 'id', + }, + }, + VDigestId: { + type: DataTypes.STRING, + references: { + model: VDigest, + key: 'id', + }, + }, +}); + +User.belongsToMany(VDigest, { through: Ownership }); +VDigest.belongsToMany(User, { through: Ownership }); + +module.exports = Ownership; diff --git a/models/User.js b/models/User.js index d0c342a..13c875f 100644 --- a/models/User.js +++ b/models/User.js @@ -1,81 +1,54 @@ -var mongoose = require('mongoose'); var bcrypt = require('bcrypt-nodejs'); var crypto = require('crypto'); -var ShortId = require('mongoose-minid'); - -var userSchema = new mongoose.Schema({ - email: { type: String, unique: true, lowercase: true }, - password: String, - - facebook: String, - twitter: String, - google: String, - github: String, - instagram: String, - linkedin: String, - tokens: Array, - - profile: { - name: { type: String, default: 'VDigest User' }, - gender: { type: String, default: '' }, - location: { type: String, default: '' }, - website: { type: String, default: '' }, - picture: { type: String, default: '' } +const shortid = require('shortid'); +const { DataTypes } = require('sequelize'); +const sequelize = require('./sequelize'); + +const User = sequelize.define('User', { + id: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + defaultValue: shortid.generate, + primaryKey: true, + }, + email: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + }, + name: { + type: DataTypes.STRING, + allowNull: false, + }, + location: { + type: DataTypes.STRING, + allowNull: true, + }, + website: { + type: DataTypes.STRING, + allowNull: true, + }, + password: { + type: DataTypes.STRING, + allowNull: false, + set(value) { + /** + * Hash the password for security. + */ + const salt = bcrypt.genSaltSync(5); + const hash = bcrypt.hashSync(value, salt); + this.setDataValue('password', hash); + }, + }, + resetPasswordToken: { + type: DataTypes.STRING, + allowNull: true, + }, + resetPasswordExpires: { + type: DataTypes.DATE, + allowNull: true, }, - - vdigests: [{ type: ShortId, ref: 'VDigest' }], - - resetPasswordToken: String, - resetPasswordExpires: Date -}); - -/** - * Hash the password for security. - * "Pre" is a Mongoose middleware that executes before each user.save() call. - */ - -userSchema.pre('save', function(next) { - var user = this; - - if (!user.isModified('password')) return next(); - - bcrypt.genSalt(5, function(err, salt) { - if (err) return next(err); - - bcrypt.hash(user.password, salt, null, function(err, hash) { - if (err) return next(err); - user.password = hash; - next(); - }); - }); }); -/** - * Validate user's password. - * Used by Passport-Local Strategy for password validation. - */ - -userSchema.methods.comparePassword = function(candidatePassword, cb) { - bcrypt.compare(candidatePassword, this.password, function(err, isMatch) { - if (err) return cb(err); - cb(null, isMatch); - }); -}; - -/** - * Get URL to a user's gravatar. - * Used in Navbar and Account Management page. - */ - -userSchema.methods.gravatar = function(size) { - if (!size) size = 200; - - if (!this.email) { - return 'https://gravatar.com/avatar/?s=' + size + '&d=retro'; - } - - var md5 = crypto.createHash('md5').update(this.email).digest('hex'); - return 'https://gravatar.com/avatar/' + md5 + '?s=' + size + '&d=retro'; -}; - -module.exports = mongoose.model('User', userSchema); +module.exports = User; diff --git a/models/VDigest.js b/models/VDigest.js index 443e919..9d6ddd4 100644 --- a/models/VDigest.js +++ b/models/VDigest.js @@ -1,82 +1,131 @@ - /*global require exports*/ -var mongoose = require('mongoose'), - User = require('./User'), - ShortId = require('mongoose-minid'), - spaths = require('../config/settings').paths, - path = require('path'), - pathUtils = require('../utils/fpaths'); +const User = require('./User'); +const shortid = require('shortid'); +const pathUtils = require('../utils/fpaths'); + +const { DataTypes } = require('sequelize'); +const sequelize = require('./sequelize'); + +const DEFAULT_DIGEST = Object.freeze({ + author: '', + title: 'Video Digest', + chapters: [], +}); -var vdSchema = new mongoose.Schema({ - _id: { type: ShortId, length: 7}, - ytid: String, - pubdisplay: {type: Boolean, default: false}, - rawTransName: String, - sentSepTransName: String, - nSentences: Number, - preAlignTrans: [{speaker: String, line: String}], - videoName: String, - videoLength: Number, +const VDigest = sequelize.define('VDigest', { + id: { + type: DataTypes.STRING, + allowNull: false, + defaultValue: shortid.generate, + primaryKey: true, + }, + ytid: { + type: DataTypes.STRING, + allowNull: false, + }, + pubdisplay: { + type: DataTypes.BOOLEAN, + defaultValue: false, + }, + rawTransName: { + type: DataTypes.STRING, + }, + sentSepTransName: { + type: DataTypes.STRING, + }, + nSentences: { + type: DataTypes.INTEGER, + }, + videoName: { + type: DataTypes.STRING, + }, + videoLength: { + type: DataTypes.FLOAT, + }, puburl: { - type: String, - unique: true, - sparse: true - }, - audioName: String, - alignTrans:{words: [{"start": Number, - "speaker": Number, - "end": Number, - "word": String, - "sentenceNumber": Number, - "alignedWord": String}] - }, - uploadDate: {type: Date, default: Date.now}, - uploadUser: {type: mongoose.Schema.ObjectId, ref: "User"}, - state: {type: Number, default: 0}, - anyedit: {type: Boolean, default: false}, + type: DataTypes.STRING, + }, + audioName: { + type: DataTypes.STRING, + }, + alignTrans: { + // just json and not jsonb for now because + // I don't think we need to query it at all + type: DataTypes.JSON, + }, + uploadUser: { + type: DataTypes.STRING, + references: { + model: User, + key: 'id', + }, + }, + state: { + type: DataTypes.INTEGER, + defaultValue: 0, + allowNull: false, + }, + anyedit: { + type: DataTypes.BOOLEAN, + defaultValue: false, + allowNull: false, + }, + title: { + type: DataTypes.STRING, + defaultValue: 'New Video Digest', + }, digest: { - author: String, - title: { - type: String, - default: "Video Digest" + type: DataTypes.JSON, + defaultValue: DEFAULT_DIGEST, + }, + + // virtual fields + isProcessing: { + type: DataTypes.VIRTUAL, + get() { + return this.state > 1; + }, + set(value) { + throw new Error('do not set virutal'); + }, + }, + isReady: { + type: DataTypes.VIRTUAL, + get() { + return this.state === 1; + }, + set(value) { + throw new Error('do not set virutal'); + }, + }, + getVideoFile: { + type: DataTypes.VIRTUAL, + get() { + return pathUtils.getVideoFile(this.videoName); + }, + set(value) { + throw new Error('do not set virutal'); + }, + }, + getAudioFile: { + type: DataTypes.VIRTUAL, + get() { + return pathUtils.getVideoFile(this.audioName); }, - chapters: [{ - title: String, - start: Number, - end: Number, - ytid: String, - sections: [{ - end: Number, - start: Number, - summary: [String], - thumbnail: { - time: Number, - data: String - } - }]}] - } + set(value) { + throw new Error('do not set virutal'); + }, + }, + getSSFile: { + type: DataTypes.VIRTUAL, + get() { + return pathUtils.getSSTransFile(this.id); + }, + set(value) { + throw new Error('do not set virutal'); + }, + }, }); -vdSchema.methods.isProcessing = function () { - return this.state > 1; -}; - -vdSchema.methods.isReady = function () { - return this.state === 1; -}; - -vdSchema.methods.getVideoFile = function () { - return pathUtils.getVideoFile(this.videoName); -}; - -vdSchema.methods.getAudioFile = function () { - return pathUtils.getVideoFile(this.audioName); -}; - -vdSchema.methods.getSSFile = function () { - return pathUtils.getSSTransFile(this._id); -}; - - -module.exports = mongoose.model('VDigest', vdSchema); +module.exports = { VDigest, DEFAULT_DIGEST }; diff --git a/models/index.js b/models/index.js new file mode 100644 index 0000000..a9ceb1a --- /dev/null +++ b/models/index.js @@ -0,0 +1,4 @@ +const sequelize = require('./sequelize'); +const { VDigest } = require('./VDigest'); +const User = require('./User'); +const Ownership = require('./Ownership'); diff --git a/models/sequelize.js b/models/sequelize.js new file mode 100644 index 0000000..bbd2b19 --- /dev/null +++ b/models/sequelize.js @@ -0,0 +1,19 @@ +const { Sequelize } = require('sequelize'); + +let sequelize; +if (process.env.DATABASE_URL) { + sequelize = new Sequelize(process.env.DATABASE_URL, { + dialect: 'postgres', + protocol: 'postgres', + logging: true, + }); +} else { + // local dev with sqlite + sequelize = new Sequelize({ + dialect: 'sqlite', + storage: 'local-database.sqlite', + logging: false, + }); +} + +module.exports = sequelize; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..b561168 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6313 @@ +{ + "name": "vdigest", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.10.3", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.3.tgz", + "integrity": "sha512-fDx9eNW0qz0WkUeqL6tXEXzVlPh6Y5aCDEZesl0xBGA8ndRukX91Uk44ZqnkECp01NAZUdCAl+aiQNGi0k88Eg==", + "dev": true, + "requires": { + "@babel/highlight": "^7.10.3" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.10.3", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.3.tgz", + "integrity": "sha512-bU8JvtlYpJSBPuj1VUmKpFGaDZuLxASky3LhaKj3bmpSTY6VWooSM8msk+Z0CZoErFye2tlABF6yDkT3FOPAXw==", + "dev": true + }, + "@babel/highlight": { + "version": "7.10.3", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.3.tgz", + "integrity": "sha512-Ih9B/u7AtgEnySE2L2F0Xm0GaM729XqqLfHkalTsbjXGyqmf/6M0Cu0WpvqueUlW+xk88BHw9Nkpj49naU+vWw==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.10.3", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@sindresorhus/is": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-0.14.0.tgz", + "integrity": "sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==" + }, + "@szmarczak/http-timer": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-1.1.2.tgz", + "integrity": "sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==", + "requires": { + "defer-to-connect": "^1.0.1" + } + }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" + }, + "@types/minimatch": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz", + "integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==", + "dev": true + }, + "@types/node": { + "version": "14.0.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.0.23.tgz", + "integrity": "sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw==" + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "CSSselect": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/CSSselect/-/CSSselect-0.4.1.tgz", + "integrity": "sha1-+Kt+H4QYzmPNput713ioXX7EkrI=", + "requires": { + "CSSwhat": "0.4", + "domutils": "1.4" + } + }, + "CSSwhat": { + "version": "0.4.7", + "resolved": "https://registry.npmjs.org/CSSwhat/-/CSSwhat-0.4.7.tgz", + "integrity": "sha1-hn2g/zn3eGEyQsRM/qg/CqTr35s=" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "acorn": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-2.7.0.tgz", + "integrity": "sha1-q259nYhqrKiwhbwzEreaGYQz8Oc=" + }, + "acorn-globals": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-1.0.9.tgz", + "integrity": "sha1-VbtemGkVB7dFedBRNBMhfDgMVM8=", + "requires": { + "acorn": "^2.1.0" + } + }, + "addressparser": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/addressparser/-/addressparser-0.3.2.tgz", + "integrity": "sha1-WYc/Nej89sc2HBAjkmHXbhU0i7I=" + }, + "ajv": { + "version": "6.12.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz", + "integrity": "sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==", + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", + "requires": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + } + }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=" + }, + "ansi-align": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.0.tgz", + "integrity": "sha512-ZpClVKqXN3RGBmKibdfWzqCY4lnjEuoNzU5T0oEFpfd/z5qJHVarukridD4juLO2FXMiwUQxr9WqQtaYa8XRYw==", + "requires": { + "string-width": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==" + }, + "emoji-regex": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", + "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", + "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", + "requires": { + "emoji-regex": "^7.0.1", + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^5.1.0" + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "requires": { + "ansi-regex": "^4.1.0" + } + } + } + }, + "ansi-escape-sequences": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/ansi-escape-sequences/-/ansi-escape-sequences-5.1.2.tgz", + "integrity": "sha512-JcpoVp1W1bl1Qn4cVuiXEhD6+dyXKSOgCn2zlzE8inYgCJCBy1aPnUhlz6I4DFum8D4ovb9Qi/iAjUcGvG2lqw==", + "requires": { + "array-back": "^4.0.0" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "anymatch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", + "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", + "requires": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + } + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "argparse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.7.tgz", + "integrity": "sha1-wolQZIBVeBDxSovGLXoG9j7X+VE=", + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "array-back": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.1.tgz", + "integrity": "sha512-Z/JnaVEXv+A9xabHzN43FiiiWEE7gPCRXMrVmRm00tWbjZRul1iHm7ECzlyNq1p4a4ATXz+G9FJ3GqGOkOV3fg==" + }, + "array-differ": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-3.0.0.tgz", + "integrity": "sha512-THtfYS6KtME/yIAhKjZ2ul7XI96lQGHRputJQHO80LAWQnuGP4iCIN8vdMRboGbIEYBwU33q8Tch1os2+X0kMg==", + "dev": true + }, + "array-filter": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-1.0.0.tgz", + "integrity": "sha1-uveeYubvTCpMC4MSMtr/7CUfnYM=" + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, + "arrify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-2.0.1.tgz", + "integrity": "sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug==", + "dev": true + }, + "asap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", + "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0=" + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "assertion-error": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.0.0.tgz", + "integrity": "sha1-x/hUOP3UZrx8oWq5DIFRN5el0js=", + "dev": true + }, + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=" + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "available-typed-arrays": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.2.tgz", + "integrity": "sha512-XWX3OX8Onv97LMk/ftVyBibpGwY5a8SmuxZPzeOxqmuEqUCOM9ZE+uIaD1VNJ5QnvU2UQusvmKbuM1FR8QWGfQ==", + "requires": { + "array-filter": "^1.0.0" + } + }, + "aws-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/aws-sign/-/aws-sign-0.3.0.tgz", + "integrity": "sha1-PYHKabR0seFlGHKLUcJP8Lvtxuk=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", + "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==" + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "base64-js": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.3.1.tgz", + "integrity": "sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g==" + }, + "base64url": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz", + "integrity": "sha512-ir1UPr3dkwexU7FdV8qBBbNDRUhMmIekYMFZfi+C/sLNnRESKPl23nB9b2pltqfOQNnGzsDdId90AEtG5tCx4A==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "bcrypt-nodejs": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/bcrypt-nodejs/-/bcrypt-nodejs-0.0.3.tgz", + "integrity": "sha1-xgkX8m3CNWYVZsaBBhwwPCsohCs=" + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "binary-extensions": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.0.0.tgz", + "integrity": "sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow==" + }, + "bl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", + "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + } + } + }, + "blessed": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.0.29.tgz", + "integrity": "sha1-vRt+vi6pLYQvRw9r+gvSAReAQJQ=", + "dev": true + }, + "block-stream": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", + "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", + "optional": true, + "requires": { + "inherits": "~2.0.0" + } + }, + "bluebird": { + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", + "integrity": "sha1-9y12C+Cbf3bQjtj66Ysomo0F+rM=" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "boom": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/boom/-/boom-0.4.2.tgz", + "integrity": "sha1-emNune1O/O+xnO9JR6PGffrukRs=", + "requires": { + "hoek": "0.9.x" + } + }, + "boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "requires": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==" + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "bson": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.0.4.tgz", + "integrity": "sha512-Ioi3TD0/1V3aI8+hPfC56TetYmzfq2H07jJa9A1lKTxWsFtHtYdLMGMXjtGEg9v0f72NSM07diRQEUNYhLupIA==", + "requires": { + "buffer": "^5.1.0", + "long": "^4.0.0" + } + }, + "buffer": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz", + "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==", + "requires": { + "base64-js": "^1.0.2", + "ieee754": "^1.1.4" + } + }, + "buffer-from": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", + "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", + "dev": true + }, + "buffer-writer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", + "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==" + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "cacheable-request": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-6.1.0.tgz", + "integrity": "sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==", + "requires": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^3.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^4.1.0", + "responselike": "^1.0.2" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "requires": { + "pump": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==" + } + } + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", + "requires": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + } + }, + "chai": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/chai/-/chai-1.10.0.tgz", + "integrity": "sha1-5AMcyHZURhp1lD5aNatG6vOcHrk=", + "dev": true, + "requires": { + "assertion-error": "1.0.0", + "deep-eql": "0.1.3" + } + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "character-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-1.2.1.tgz", + "integrity": "sha1-wN3kqxgnE7kZuXCVmhI+zBow/NY=" + }, + "cheerio": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.16.0.tgz", + "integrity": "sha1-eArkcmkuqF4eD+My6Aa9upjBbQo=", + "requires": { + "CSSselect": "~0.4.0", + "entities": "~1.1.1", + "htmlparser2": "~3.7.0", + "lodash": "~2.4.1" + } + }, + "chokidar": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.4.0.tgz", + "integrity": "sha512-aXAaho2VJtisB/1fg1+3nlLJqGOuewTzQpd/Tz0yTg2R0e4IGtshYvtjowyEumcBv2z+y4+kc75Mz7j5xJskcQ==", + "requires": { + "anymatch": "~3.1.1", + "braces": "~3.0.2", + "fsevents": "~2.1.2", + "glob-parent": "~5.1.0", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.4.0" + } + }, + "chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" + }, + "ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==" + }, + "clap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", + "requires": { + "chalk": "^1.1.3" + } + }, + "clean-css": { + "version": "3.4.28", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-3.4.28.tgz", + "integrity": "sha1-vxlF6C/ICPVWlebd6uwBQA79A/8=", + "requires": { + "commander": "2.8.x", + "source-map": "0.4.x" + }, + "dependencies": { + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "requires": { + "graceful-readlink": ">= 1.0.0" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "requires": { + "amdefine": ">=0.0.4" + } + } + } + }, + "cli-boxes": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-2.2.0.tgz", + "integrity": "sha512-gpaBrMAizVEANOpfZp/EEUixTXDyGt7DFzdK5hU+UbWt/J0lB0w20ncZj59Z9a93xHb9u12zF5BS6i9RKbtg4w==" + }, + "cli-progress": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.8.2.tgz", + "integrity": "sha512-qRwBxLldMSfxB+YGFgNRaj5vyyHe1yMpVeDL79c+7puGujdKJHQHydgqXDcrkvQgJ5U/d3lpf6vffSoVVUftVQ==", + "requires": { + "colors": "^1.1.2", + "string-width": "^4.2.0" + }, + "dependencies": { + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + } + } + }, + "cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", + "requires": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + }, + "dependencies": { + "wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=" + } + } + }, + "clockwork": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/clockwork/-/clockwork-0.1.4.tgz", + "integrity": "sha1-SkS7Zq68MLtjwbxHUevvYHfPrAM=", + "requires": { + "request": ">=2.33.0", + "xml2js": ">=0.4.1", + "xmlbuilder": ">=2.1.0" + } + }, + "clone-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.2.tgz", + "integrity": "sha1-0dyXOSAxTfZ/vrlCI7TuNQI56Ws=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "colors": { + "version": "0.6.0-1", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.0-1.tgz", + "integrity": "sha1-bbtozri8YPKzE9zFzhWZ8G0Z5no=" + }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.6.0.tgz", + "integrity": "sha1-nfflL7Kgyw+4kFjugMMQQiXzfh0=" + }, + "compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", + "dev": true + }, + "component-emitter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz", + "integrity": "sha1-KWWU8nU9qmOZbSrwjRWpURbJrsM=", + "dev": true + }, + "compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "requires": { + "mime-db": ">= 1.43.0 < 2" + } + }, + "compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "requires": { + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" + }, + "dependencies": { + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "configstore": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/configstore/-/configstore-5.0.1.tgz", + "integrity": "sha512-aMKprgk5YhBNyH25hj8wGt2+D52Sw1DRRIzqBwLp2Ya9mFmY8KPvvtvmna8SxVR9JMZ4kzMD68N22vlaRpkeFA==", + "requires": { + "dot-prop": "^5.2.0", + "graceful-fs": "^4.1.2", + "make-dir": "^3.0.0", + "unique-string": "^2.0.0", + "write-file-atomic": "^3.0.0", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" + } + } + }, + "connect-assets": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/connect-assets/-/connect-assets-5.4.0.tgz", + "integrity": "sha1-djtY2A6UXIVyErHOZt9gnkJNkJ0=", + "requires": { + "argparse": "1.0.7", + "csswring": "5.0.0", + "mime": "1.3.4", + "mincer": "1.5.0", + "postcss": "5.0.21", + "uglify-js": "2.6.2" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + }, + "mime": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.3.4.tgz", + "integrity": "sha1-EV+eO2s9rylZmDyzjxSaLUDrXVM=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "uglify-js": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.2.tgz", + "integrity": "sha1-9QvoikLNOWpiUdxSqzcvccwS/vA=", + "requires": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + } + } + } + }, + "connect-flash": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/connect-flash/-/connect-flash-0.1.1.tgz", + "integrity": "sha1-2GMPJtlaf4UfmVax6MxnMvO2qjA=" + }, + "connect-mongo": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/connect-mongo/-/connect-mongo-3.2.0.tgz", + "integrity": "sha512-0Mx88079Z20CG909wCFlR3UxhMYGg6Ibn1hkIje1hwsqOLWtL9HJV+XD0DAjUvQScK6WqY/FA8tSVQM9rR64Rw==", + "requires": { + "mongodb": "^3.1.0" + } + }, + "connect-session-sequelize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/connect-session-sequelize/-/connect-session-sequelize-7.0.0.tgz", + "integrity": "sha512-RWThzaFeq2RDelFA1WE82f6Eb0rm6OiflYoilQ6SilNqd+DbLBUOcO/ulbggleRK/3xGBRlAV3/ab0BAanKWGw==", + "requires": { + "debug": "^4.1.1", + "deep-equal": "^2.0.3" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "constantinople": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.0.2.tgz", + "integrity": "sha1-S5RdmTeQe82Y7ldRIsOBdRZUQUE=", + "requires": { + "acorn": "^2.1.0" + } + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-jar": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/cookie-jar/-/cookie-jar-0.3.0.tgz", + "integrity": "sha1-vJon1OK5fhhs1XyeIGPLmfpozMw=" + }, + "cookie-parser": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.5.tgz", + "integrity": "sha512-f13bPUj/gG/5mDr+xLmSxxDsB9DQiTIfhJS/sqjrmfAWiAN+x2O4i/XguTL9yDZ+/IFDanJ+5x7hC4CXT9Tdzw==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "cookiejar": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-1.3.2.tgz", + "integrity": "sha1-YdMini2iDIWQMiM1ApWKm331gkk=", + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cosmiconfig": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz", + "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.1.0", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.7.2" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "cryptiles": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-0.2.2.tgz", + "integrity": "sha1-7ZH/HxetE9N0gohZT4pIoNJvMlw=", + "requires": { + "boom": "0.4.x" + } + }, + "crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==" + }, + "css": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/css/-/css-1.0.8.tgz", + "integrity": "sha1-k4aBHKgrzMnuf7WnMrHioxfIo+c=", + "requires": { + "css-parse": "1.0.4", + "css-stringify": "1.0.5" + } + }, + "css-parse": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/css-parse/-/css-parse-1.0.4.tgz", + "integrity": "sha1-OLBQP7+dqfVOnB29pg4UXHcRe90=" + }, + "css-stringify": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/css-stringify/-/css-stringify-1.0.5.tgz", + "integrity": "sha1-sNBClG2ylTu50pKQCmy19tASIDE=" + }, + "csso": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/csso/-/csso-1.8.2.tgz", + "integrity": "sha1-06BgraXSoWt1Bh+tnZFtCdwvTlA=", + "requires": { + "clap": "^1.0.9", + "source-map": "^0.5.3" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "csswring": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/csswring/-/csswring-5.0.0.tgz", + "integrity": "sha1-sG/Bjq0zQm9ZOVMwCqgLTOzQjW8=", + "requires": { + "minimist": "^1.1.0", + "onecolor": "^2.4.0", + "postcss": "^5.0.0" + } + }, + "ctype": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/ctype/-/ctype-0.5.3.tgz", + "integrity": "sha1-gsGMJGH3QRTvFsE1IkrQuRRMoS8=" + }, + "cycle": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/cycle/-/cycle-1.0.3.tgz", + "integrity": "sha1-IegLK+hYD5i0aPN5QwZisEbDStI=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "decompress-response": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-3.3.0.tgz", + "integrity": "sha1-gKTdMjdIOEv6JICDYirt7Jgq3/M=", + "requires": { + "mimic-response": "^1.0.0" + } + }, + "deep-eql": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-0.1.3.tgz", + "integrity": "sha1-71WKyrjeJSBs1xOQbXTlaTDrafI=", + "dev": true, + "requires": { + "type-detect": "0.1.1" + } + }, + "deep-equal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.0.3.tgz", + "integrity": "sha512-Spqdl4H+ky45I9ByyJtXteOm9CaIrPmnIPmOhrkKGNYWeDgCvJ8jNYVCTjChxW4FqGuZnLHADc8EKRMX6+CgvA==", + "requires": { + "es-abstract": "^1.17.5", + "es-get-iterator": "^1.1.0", + "is-arguments": "^1.0.4", + "is-date-object": "^1.0.2", + "is-regex": "^1.0.5", + "isarray": "^2.0.5", + "object-is": "^1.1.2", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "regexp.prototype.flags": "^1.3.0", + "side-channel": "^1.0.2", + "which-boxed-primitive": "^1.0.1", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.2" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + } + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "defer-to-connect": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-1.1.3.tgz", + "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==" + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "diff": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/diff/-/diff-1.0.8.tgz", + "integrity": "sha1-NDJ2MI7Jkbe8giZ+1VvBQR+XFmY=", + "dev": true + }, + "directmail": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/directmail/-/directmail-0.1.8.tgz", + "integrity": "sha1-5IUsigxVGb70kE/Nltdggi9CpEY=", + "requires": { + "simplesmtp": "~0.3.30" + } + }, + "dkim-signer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/dkim-signer/-/dkim-signer-0.1.2.tgz", + "integrity": "sha1-L/XWHIfY+/9aixMc/8XsO6HCVVM=", + "requires": { + "mimelib": "~0.2.15", + "punycode": "~1.2.4" + }, + "dependencies": { + "punycode": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.2.4.tgz", + "integrity": "sha1-VACKyXKux0F13vnLpt9/qdORh0A=" + } + } + }, + "dom-serializer": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz", + "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==", + "requires": { + "domelementtype": "^2.0.1", + "entities": "^2.0.0" + }, + "dependencies": { + "domelementtype": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", + "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==" + }, + "entities": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz", + "integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==" + } + } + }, + "domelementtype": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" + }, + "domhandler": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.2.1.tgz", + "integrity": "sha1-Wd+dzSJ+gIs2Wuc+H2aErD2Ub8I=", + "requires": { + "domelementtype": "1" + } + }, + "domutils": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.4.3.tgz", + "integrity": "sha1-CGVRN5bGswYDGFDhdVFrr4C3Km8=", + "requires": { + "domelementtype": "1" + } + }, + "dot-prop": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.2.0.tgz", + "integrity": "sha512-uEUyaDKoSQ1M4Oq8l45hSE26SnTxL6snNnqvK/VWx5wJhmff5z0FUVJDKDanor/6w3kzE3i7XZOk+7wC0EXr1A==", + "requires": { + "is-obj": "^2.0.0" + } + }, + "dottie": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.2.tgz", + "integrity": "sha512-fmrwR04lsniq/uSr8yikThDTrM7epXHBAAjH9TbeH3rEA8tdCO7mRzB9hdmdGyJCxF8KERo9CITcm3kGuoyMhg==" + }, + "duplexer3": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer3/-/duplexer3-0.1.4.tgz", + "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=" + }, + "eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "encoding": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "requires": { + "iconv-lite": "~0.4.13" + } + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "entities": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "requires": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + } + }, + "es-abstract": { + "version": "1.17.6", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.6.tgz", + "integrity": "sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw==", + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-regex": "^1.1.0", + "object-inspect": "^1.7.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + }, + "es-get-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.0.tgz", + "integrity": "sha512-UfrmHuWQlNMTs35e1ypnvikg6jCz3SK8v8ImvmDsh36fCVUR1MqoFDiyn0/k52C8NqO3YsO8Oe0azeesNuqSsQ==", + "requires": { + "es-abstract": "^1.17.4", + "has-symbols": "^1.0.1", + "is-arguments": "^1.0.4", + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-string": "^1.0.5", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + } + } + }, + "es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "requires": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + } + }, + "escape-goat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-2.1.1.tgz", + "integrity": "sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q==" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "execa": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-2.1.0.tgz", + "integrity": "sha512-Y/URAVapfbYy2Xp/gb6A0E7iR8xeqOCXsuuaoMn7A5PzrXUK84E1gyiEfq0wQd/GHA6GsoHWwhNq8anb0mleIw==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.0", + "get-stream": "^5.0.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^3.0.0", + "onetime": "^5.1.0", + "p-finally": "^2.0.0", + "signal-exit": "^3.0.2", + "strip-final-newline": "^2.0.0" + }, + "dependencies": { + "get-stream": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.1.0.tgz", + "integrity": "sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw==", + "dev": true, + "requires": { + "pump": "^3.0.0" + } + } + } + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "express-flash": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/express-flash/-/express-flash-0.0.2.tgz", + "integrity": "sha1-I9GovPP5DXB5KOSJ+Whp7K0KzaI=", + "requires": { + "connect-flash": "0.1.x" + } + }, + "express-session": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.1.tgz", + "integrity": "sha512-UbHwgqjxQZJiWRTMyhvWGvjBQduGCSBDhhZXYenziMFjxst5rMV+aJZ6hKPHZnPyHGsrqRICxtX8jtEbm/z36Q==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.0", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "express-validator": { + "version": "2.21.0", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-2.21.0.tgz", + "integrity": "sha1-9fwvn6npqFeGNPEOhrpaQ0a5b08=", + "requires": { + "bluebird": "3.4.x", + "lodash": "4.16.x", + "validator": "5.7.x" + }, + "dependencies": { + "lodash": { + "version": "4.16.6", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.16.6.tgz", + "integrity": "sha1-0iyaxmAojzhD4Wun0rXQbMon13c=" + }, + "validator": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-5.7.0.tgz", + "integrity": "sha1-eoelgUa2laxIYHEUHAxJ1n2gXlw=" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "eyes": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/eyes/-/eyes-0.1.8.tgz", + "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=" + }, + "fast-deep-equal": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", + "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==" + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" + }, + "fbgraph": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/fbgraph/-/fbgraph-0.2.13.tgz", + "integrity": "sha1-oQfa/BJVowFiQTyJ9buuWLbwow4=", + "requires": { + "qs": "1.2.x", + "request": "2.40.x" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "optional": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "optional": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=" + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "optional": true, + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime": "~1.2.11" + } + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "^0.1.5", + "ctype": "0.5.3" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "optional": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=" + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "oauth-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", + "optional": true + }, + "qs": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.2.2.tgz", + "integrity": "sha1-GbV/8k3CqZzh+L32r82ln472H4g=" + }, + "request": { + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", + "integrity": "sha1-TdZw9pbx5uhC5mtLXoOTAaub62c=", + "requires": { + "aws-sign2": "~0.5.0", + "forever-agent": "~0.5.0", + "form-data": "~0.1.0", + "hawk": "1.1.1", + "http-signature": "~0.10.0", + "json-stringify-safe": "~5.0.0", + "mime-types": "~1.0.1", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.3.0", + "qs": "~1.0.0", + "stringstream": "~0.0.4", + "tough-cookie": ">=0.12.0", + "tunnel-agent": "~0.4.0" + }, + "dependencies": { + "qs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz", + "integrity": "sha1-UKk+K1r2aRwxvOpdrnjubqGQN2g=" + } + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "optional": true + } + } + }, + "fd-slicer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", + "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", + "requires": { + "pend": "~1.2.0" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "find-versions": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-3.2.0.tgz", + "integrity": "sha512-P8WRou2S+oe222TOCHitLy8zj+SIsVJh52VP4lvXkaFVnOFFdoWv1H1Jjvel1aI6NCFOAaeAVm8qrI0odiLcww==", + "dev": true, + "requires": { + "semver-regex": "^2.0.0" + } + }, + "follow-redirects": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-0.0.3.tgz", + "integrity": "sha1-bOZ6JNsf4T8ibBFxpyp+8rF7j2U=", + "requires": { + "underscore": "^1.10.2" + }, + "dependencies": { + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" + } + } + }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz", + "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q==" + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-minipass": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", + "integrity": "sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA==", + "requires": { + "minipass": "^2.6.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "fsevents": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", + "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", + "optional": true + }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "optional": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "optional": true + } + } + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "fwk": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fwk/-/fwk-1.0.11.tgz", + "integrity": "sha1-CYyPcXLsJRNOyGoUc6/6Nk1AQ0c=", + "requires": { + "async": "0.2.x", + "should": "0.6.x" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=" + } + } + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + } + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "github-api": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/github-api/-/github-api-0.7.0.tgz", + "integrity": "sha1-ONIdN16Iw1Hyq/yQ8TLiee0qYyo=", + "requires": { + "underscore": "*", + "xmlhttprequest": "*" + } + }, + "glob": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.3.tgz", + "integrity": "sha1-4xPusknHr/qlxHUoaw4RW1mDlGc=", + "dev": true, + "requires": { + "graceful-fs": "~2.0.0", + "inherits": "2", + "minimatch": "~0.2.11" + }, + "dependencies": { + "graceful-fs": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz", + "integrity": "sha1-fNLNsiiko/Nule+mzBQt59GhNtA=", + "dev": true + } + } + }, + "glob-parent": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", + "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", + "requires": { + "is-glob": "^4.0.1" + } + }, + "global-dirs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-2.0.1.tgz", + "integrity": "sha512-5HqUqdhkEovj2Of/ms3IeS/EekcO54ytHRLV4PEY2rhRwrHXLQjeVEES0Lhka0xwNDtGYn58wyC4s5+MHsOO6A==", + "requires": { + "ini": "^1.3.5" + } + }, + "got": { + "version": "9.6.0", + "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", + "integrity": "sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==", + "requires": { + "@sindresorhus/is": "^0.14.0", + "@szmarczak/http-timer": "^1.1.2", + "cacheable-request": "^6.0.0", + "decompress-response": "^3.3.0", + "duplexer3": "^0.1.4", + "get-stream": "^4.1.0", + "lowercase-keys": "^1.0.1", + "mimic-response": "^1.0.1", + "p-cancelable": "^1.0.0", + "to-readable-stream": "^1.0.0", + "url-parse-lax": "^3.0.0" + } + }, + "graceful-fs": { + "version": "3.0.12", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.12.tgz", + "integrity": "sha512-J55gaCS4iTTJfTXIxSVw3EMQckcqkpdRv3IR7gu6sq0+tbC363Zx6KH/SEwXASK9JRbhyZmVjJEVJIOxYsB3Qg==", + "optional": true, + "requires": { + "natives": "^1.1.3" + } + }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=" + }, + "growl": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/growl/-/growl-1.8.1.tgz", + "integrity": "sha1-Sy3sjZB+k9szZiTc7AGDUC+MlCg=", + "dev": true + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", + "integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", + "requires": { + "ajv": "^6.5.5", + "har-schema": "^2.0.0" + } + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==" + }, + "has-symbols": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "has-yarn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/has-yarn/-/has-yarn-2.1.0.tgz", + "integrity": "sha512-UqBRqi4ju7T+TqGNdqAO0PaSVGsDGJUBQvk9eUWNGRY1CFGDzYhLWoM7JQEemnlvVcv/YEmc2wNW8BC24EnUsw==" + }, + "hash-arg": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/hash-arg/-/hash-arg-1.0.3.tgz", + "integrity": "sha512-BUvgqsnHlEupirIUo/pyaeodQ4gEP4b5aC/HgOvQcy7MMOhXrQjImcM+jupDNwBZDLxXpD04CufZQN32g1LdfQ==" + }, + "hawk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.1.1.tgz", + "integrity": "sha1-h81JH5tG5OKurKM1QWdmiF0tHtk=", + "optional": true, + "requires": { + "boom": "0.4.x", + "cryptiles": "0.2.x", + "hoek": "0.9.x", + "sntp": "0.2.x" + } + }, + "he": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/he/-/he-0.3.6.tgz", + "integrity": "sha1-nXvERud5Y5MzAd1gLVcxy4YRNeA=" + }, + "heroku-ssl-redirect": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/heroku-ssl-redirect/-/heroku-ssl-redirect-0.0.4.tgz", + "integrity": "sha1-IboHB6pQO1CkEqCUar+qiO99CCw=" + }, + "hike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/hike/-/hike-1.0.2.tgz", + "integrity": "sha1-WaoFPok5FjsrH6+JGkJkKQpkhno=" + }, + "hoek": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-0.9.1.tgz", + "integrity": "sha1-PTIkYrrfB3Fup+uFuviAec3c5QU=" + }, + "homedir": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/homedir/-/homedir-0.6.0.tgz", + "integrity": "sha1-KyHbZr8Ipts4JJo+/1LX0YcGrx4=" + }, + "html-entities": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.3.1.tgz", + "integrity": "sha512-rhE/4Z3hIhzHAUKbW8jVcCyuT5oJCXXqhN/6mXXVCpzTmvJnoH2HL/bt3EZ6p55jbFJBeAe1ZNpL5BugLujxNA==" + }, + "htmlparser2": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-3.7.3.tgz", + "integrity": "sha1-amTHdjfAjG8w7CqBV6UzM758sF4=", + "requires": { + "domelementtype": "1", + "domhandler": "2.2", + "domutils": "1.5", + "entities": "1.0", + "readable-stream": "1.1" + }, + "dependencies": { + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "entities": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.0.0.tgz", + "integrity": "sha1-sph6o4ITR/zeZCsk/fyeT7cSvyY=" + } + } + }, + "http-cache-semantics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.0.tgz", + "integrity": "sha512-carPklcUh7ROWRK7Cv27RPtdhYhUsela/ue5/jKzjegVvXDqM2ILE9Q2BGn9JZJh1g87cp56su/FgQSzcWS8cQ==" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "husky": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/husky/-/husky-4.2.5.tgz", + "integrity": "sha512-SYZ95AjKcX7goYVZtVZF2i6XiZcHknw50iXvY7b0MiGoj5RwdgRQNEHdb+gPDPCXKlzwrybjFjkL6FOj8uRhZQ==", + "dev": true, + "requires": { + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "compare-versions": "^3.6.0", + "cosmiconfig": "^6.0.0", + "find-versions": "^3.2.0", + "opencollective-postinstall": "^2.0.2", + "pkg-dir": "^4.2.0", + "please-upgrade-node": "^3.2.0", + "slash": "^3.0.0", + "which-pm-runs": "^1.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz", + "integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg==" + }, + "ignore": { + "version": "5.1.8", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.1.8.tgz", + "integrity": "sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw==", + "dev": true + }, + "ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=" + }, + "ignore-walk": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", + "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", + "requires": { + "minimatch": "^3.0.4" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "import-fresh": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.2.1.tgz", + "integrity": "sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "import-lazy": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-2.1.0.tgz", + "integrity": "sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM=" + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=" + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "instagram-node": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/instagram-node/-/instagram-node-0.4.3.tgz", + "integrity": "sha1-kHZB+gJmScHyMrkPGPwMBNjhNvg=", + "requires": { + "colors": "0.6.0-1", + "fwk": "1.0.x" + } + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "is-arguments": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-bigint": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.0.tgz", + "integrity": "sha512-t5mGUXC/xRheCK431ylNiSkGGpBp8bHENBcENTkDT6ppwPzEVxNGZRvgvmOEfbWkFhA7D2GEuE2mmQTr78sl2g==" + }, + "is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "requires": { + "binary-extensions": "^2.0.0" + } + }, + "is-boolean-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.0.1.tgz", + "integrity": "sha512-TqZuVwa/sppcrhUCAYkGBk7w0yxfQQnxq28fjkO53tnK9FQXmdwz2JS5+GjsWQ6RByES1K40nI+yDic5c9/aAQ==" + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "is-callable": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", + "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==" + }, + "is-ci": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-2.0.0.tgz", + "integrity": "sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==", + "requires": { + "ci-info": "^2.0.0" + } + }, + "is-date-object": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-installed-globally": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.3.2.tgz", + "integrity": "sha512-wZ8x1js7Ia0kecP/CHM/3ABkAmujX7WPvQk6uu3Fly/Mk44pySulQpnHG46OMjHGXApINnV4QhY3SWnECO2z5g==", + "requires": { + "global-dirs": "^2.0.1", + "is-path-inside": "^3.0.1" + } + }, + "is-map": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.1.tgz", + "integrity": "sha512-T/S49scO8plUiAOA2DBTBG3JHpn1yiw0kRp6dgiZ0v2/6twi5eiB0rHtHFH9ZIrvlWc6+4O+m4zg5+Z833aXgw==" + }, + "is-npm": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-npm/-/is-npm-4.0.0.tgz", + "integrity": "sha512-96ECIfh9xtDDlPylNPXhzjsykHsMJZ18ASpaWzQyBr4YRTcVjUvzaHayDAES2oU/3KpljhHUjtSRNiDwi0F0ig==" + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + }, + "is-number-object": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.4.tgz", + "integrity": "sha512-zohwelOAur+5uXtk8O3GPQ1eAcu4ZX3UwxQhUlfFFMNpUd83gXgjbhJh6HmB6LUNV/ieOLQuDwJO3dWJosUeMw==" + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==" + }, + "is-path-inside": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.2.tgz", + "integrity": "sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg==" + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "is-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.0.tgz", + "integrity": "sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-set": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.1.tgz", + "integrity": "sha512-eJEzOtVyenDs1TMzSQ3kU3K+E0GUS9sno+F0OBT97xsgcJsF9nXMBtkT9/kut5JEpM7oL7X/0qxR17K3mcwIAA==" + }, + "is-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", + "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", + "dev": true + }, + "is-string": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz", + "integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==" + }, + "is-symbol": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", + "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", + "requires": { + "has-symbols": "^1.0.1" + } + }, + "is-typed-array": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.3.tgz", + "integrity": "sha512-BSYUBOK/HJibQ30wWkWold5txYwMUXQct9YHAQJr8fSwvZoiglcqB0pd7vEN23+Tsi9IUEjztdOSzl4qLVYGTQ==", + "requires": { + "available-typed-arrays": "^1.0.0", + "es-abstract": "^1.17.4", + "foreach": "^2.0.5", + "has-symbols": "^1.0.1" + } + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "is-weakmap": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", + "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==" + }, + "is-weakset": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz", + "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==" + }, + "is-yarn-global": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-yarn-global/-/is-yarn-global-0.3.0.tgz", + "integrity": "sha512-VjSeb/lHmkoyd8ryPVIKvOCn4D1koMqY+vqyjjUfc3xyKtP4dYOxM44sZrnqQSzSds3xyOrUTLTC9LVCVgLngw==" + }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "jade": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/jade/-/jade-1.11.0.tgz", + "integrity": "sha1-nIDlOMEtP7lcjZu5VZ+gzAQEBf0=", + "requires": { + "character-parser": "1.2.1", + "clean-css": "^3.1.9", + "commander": "~2.6.0", + "constantinople": "~3.0.1", + "jstransformer": "0.0.2", + "mkdirp": "~0.5.0", + "transformers": "2.1.0", + "uglify-js": "^2.4.19", + "void-elements": "~2.0.1", + "with": "~4.0.0" + } + }, + "js-base64": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.2.tgz", + "integrity": "sha512-1hgLrLIrmCgZG+ID3VoLNLOSwjGnoZa8tyrUdEteMeIzsT6PH7PMLyUvbDwzNE56P3PNxyvuIOx4Uh2E5rzQIw==" + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.0.tgz", + "integrity": "sha1-Wx85evx11ne96Lz8Dkfh+aPZqJg=" + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "jstransformer": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-0.0.2.tgz", + "integrity": "sha1-eq4pqQPRls+glz2IXT5HlH7Ndqs=", + "requires": { + "is-promise": "^2.0.0", + "promise": "^6.0.1" + } + }, + "jwt-simple": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/jwt-simple/-/jwt-simple-0.1.0.tgz", + "integrity": "sha1-VGs0qrAuPNScQ6QnlJizTZQAQeM=" + }, + "keyv": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", + "integrity": "sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==", + "requires": { + "json-buffer": "3.0.0" + } + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "requires": { + "is-buffer": "^1.1.5" + } + }, + "lastfm": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/lastfm/-/lastfm-0.9.3.tgz", + "integrity": "sha512-H/NoLWyRFG2wL+M5HQgQKa9TkAMoedWpY+1aTr0RIOfMnvy5YlBF/VcMYhHycBX2ZH+Vo+Aw6c1yJm6Q9ZMssA==", + "requires": { + "underscore": "~1.6.0" + }, + "dependencies": { + "underscore": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.6.0.tgz", + "integrity": "sha1-izixDKze9jM3uLJOT/htRa6lKag=" + } + } + }, + "latest-version": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", + "integrity": "sha512-weT+r0kTkRQdCdYCNtkMwWXQTMEswKrFBkm4ckQOMVhhqhIMI1UT2hMj+1iigIhgSZm5gTmrRXBNoGUgaTY1xA==", + "requires": { + "package-json": "^6.3.0" + } + }, + "lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=" + }, + "less": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/less/-/less-1.7.5.tgz", + "integrity": "sha1-TyIM9yiKJ+rKc5325ICKLUwNV1Y=", + "requires": { + "clean-css": "2.2.x", + "graceful-fs": "~3.0.2", + "mime": "~1.2.11", + "mkdirp": "~0.5.0", + "request": "~2.40.0", + "source-map": "0.1.x" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "optional": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "optional": true + }, + "clean-css": { + "version": "2.2.23", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-2.2.23.tgz", + "integrity": "sha1-BZC1R4tRbEkD7cLYm9P9vdKGMow=", + "optional": true, + "requires": { + "commander": "2.2.x" + } + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "commander": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.2.0.tgz", + "integrity": "sha1-F1rUuTF/P/YV8gHB5XIk9Vo+kd8=", + "optional": true + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=", + "optional": true + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "optional": true, + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime": "~1.2.11" + } + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "^0.1.5", + "ctype": "0.5.3" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "optional": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=", + "optional": true + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=", + "optional": true + }, + "oauth-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", + "optional": true + }, + "qs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz", + "integrity": "sha1-UKk+K1r2aRwxvOpdrnjubqGQN2g=", + "optional": true + }, + "request": { + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", + "integrity": "sha1-TdZw9pbx5uhC5mtLXoOTAaub62c=", + "optional": true, + "requires": { + "aws-sign2": "~0.5.0", + "forever-agent": "~0.5.0", + "form-data": "~0.1.0", + "hawk": "1.1.1", + "http-signature": "~0.10.0", + "json-stringify-safe": "~5.0.0", + "mime-types": "~1.0.1", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.3.0", + "qs": "~1.0.0", + "stringstream": "~0.0.4", + "tough-cookie": ">=0.12.0", + "tunnel-agent": "~0.4.0" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "optional": true + } + } + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "list-it": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/list-it/-/list-it-1.3.5.tgz", + "integrity": "sha512-IgTW/WsIxQUPDC9Hzig3KPPeJV+u+Hh2KqLSc82UBCJlmPrcLP9kfv+yTZHwM+dCT3fICCX6fXu+OXZ1qROflw==", + "requires": { + "ansi-escape-sequences": "^5.1.2", + "debug": "^4.1.1", + "eastasianwidth": "^0.2.0", + "hash-arg": "^1.0.1", + "node-getopt": "^0.3.2" + }, + "dependencies": { + "debug": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", + "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "lodash": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-2.4.2.tgz", + "integrity": "sha1-+t2DS5aDBz2hebPq5tnA0VBT9z4=" + }, + "lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=" + }, + "long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=" + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==" + }, + "lru-cache": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.7.3.tgz", + "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=", + "dev": true + }, + "lusca": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/lusca/-/lusca-1.6.1.tgz", + "integrity": "sha512-+JzvUMH/rsE/4XfHdDOl70bip0beRcHSviYATQM0vtls59uVtdn1JMu4iD7ZShBpAmFG8EnaA+PrYG9sECMIOQ==", + "requires": { + "tsscmp": "^1.0.5" + } + }, + "m3u8stream": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.8.0.tgz", + "integrity": "sha512-vvSjdkBPdDHzVr2M+aIXbnYys4zX6m3UzxMaxBJr1PpE0e/3sawkLD4EEmz/q9hv87bleotR70cOWR3UBMtskw==", + "requires": { + "miniget": "^2.0.1", + "sax": "^1.2.4" + } + }, + "mailcomposer": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/mailcomposer/-/mailcomposer-0.2.12.tgz", + "integrity": "sha1-TQKmBGFq3LRfs203UT9MG9C3VoE=", + "requires": { + "dkim-signer": "~0.1.1", + "follow-redirects": "0.0.3", + "he": "~0.3.6", + "mime": "~1.2.11", + "mimelib": "~0.2.15" + }, + "dependencies": { + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=" + } + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "memory-cache": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/memory-cache/-/memory-cache-0.0.5.tgz", + "integrity": "sha1-2/maVtc2LEPsyvOfC6b5fzGgZ4Y=" + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "method-override": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/method-override/-/method-override-1.0.2.tgz", + "integrity": "sha1-1vgCddsjojOAAoySFbl0cL4B1ok=", + "requires": { + "methods": "1.0.0" + }, + "dependencies": { + "methods": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.0.0.tgz", + "integrity": "sha1-mnPYY3XfzvJu9hyj5Lii4lOKgOM=" + } + } + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, + "mimelib": { + "version": "0.2.19", + "resolved": "https://registry.npmjs.org/mimelib/-/mimelib-0.2.19.tgz", + "integrity": "sha1-N+yQpqx9AJVIUdCywxYY8KSdoO4=", + "requires": { + "addressparser": "~0.3.2", + "encoding": "~0.1.7" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==" + }, + "mimoza": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mimoza/-/mimoza-1.0.0.tgz", + "integrity": "sha1-10qk/giTLwBeQwvce/z6lfyrTmI=", + "requires": { + "mime-db": "^1.6.0" + } + }, + "mincer": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/mincer/-/mincer-1.5.0.tgz", + "integrity": "sha1-/ybpGDUBNkmSC2Xb5Q8sFs4f7rQ=", + "requires": { + "argparse": "^1.0.2", + "compressible": "^2.0.2", + "hike": "^1.0.0", + "lodash": "^3.10.1", + "mimoza": "^1.0.0", + "mkdirp": "^0.5.1", + "pako": "^1.0.3", + "shellwords": "^0.1.0", + "source-map": "^0.5.3" + }, + "dependencies": { + "lodash": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", + "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "miniget": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/miniget/-/miniget-2.1.0.tgz", + "integrity": "sha512-fy9x3d/0oOIhkwAms6kgxTYkHwdELhMfgj+9a/aYZpJdTWIIWGta9aXHUtnzUn+LjBmRoTdPRQSi2hkmEvXk3A==" + }, + "minimatch": { + "version": "0.2.14", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-0.2.14.tgz", + "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", + "dev": true, + "requires": { + "lru-cache": "2", + "sigmund": "~1.0.0" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" + }, + "minipass": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.9.0.tgz", + "integrity": "sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz", + "integrity": "sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==", + "requires": { + "minipass": "^2.9.0" + } + }, + "mkdirp": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", + "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", + "requires": { + "minimist": "^1.2.5" + } + }, + "mocha": { + "version": "1.21.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-1.21.5.tgz", + "integrity": "sha1-fFiwkXTfl25DSiOx6NY5hz/FKek=", + "dev": true, + "requires": { + "commander": "2.3.0", + "debug": "2.0.0", + "diff": "1.0.8", + "escape-string-regexp": "1.0.2", + "glob": "3.2.3", + "growl": "1.8.1", + "jade": "0.26.3", + "mkdirp": "0.5.0" + }, + "dependencies": { + "commander": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.3.0.tgz", + "integrity": "sha1-/UMOiJgy7DU7ms0d4hfBHLPu+HM=", + "dev": true + }, + "debug": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.0.0.tgz", + "integrity": "sha1-ib2d9nMrUSVrxnBTQrugLtEhMe8=", + "dev": true, + "requires": { + "ms": "0.6.2" + } + }, + "escape-string-regexp": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.2.tgz", + "integrity": "sha1-Tbwv5nTnGUnK8/smlc5/LcHZqNE=", + "dev": true + }, + "jade": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/jade/-/jade-0.26.3.tgz", + "integrity": "sha1-jxDXl32NefL2/4YqgbBRPMslaGw=", + "dev": true, + "requires": { + "commander": "0.6.1", + "mkdirp": "0.3.0" + }, + "dependencies": { + "commander": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-0.6.1.tgz", + "integrity": "sha1-+mihT2qUXVTbvlDYzbMyDp47GgY=", + "dev": true + }, + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=", + "dev": true + } + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=", + "dev": true + }, + "mkdirp": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", + "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.6.2.tgz", + "integrity": "sha1-2JwhJMb9wTU9Zai3e/GqxLGTcIw=", + "dev": true + } + } + }, + "moment": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.27.0.tgz", + "integrity": "sha512-al0MUK7cpIcglMv3YF13qSgdAIqxHTO7brRtaz3DlSULbqfazqkc5kEjNrLDOM7fsjshoFIihnU8snrP7zUvhQ==" + }, + "moment-timezone": { + "version": "0.5.31", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.31.tgz", + "integrity": "sha512-+GgHNg8xRhMXfEbv81iDtrVeTcWt0kWmTEY1XQK14dICTXnWJnT0dxdlPspwqF3keKMVPXwayEsk1DI0AA/jdA==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "mongodb": { + "version": "3.5.7", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.7.tgz", + "integrity": "sha512-lMtleRT+vIgY/JhhTn1nyGwnSMmJkJELp+4ZbrjctrnBxuLbj6rmLuJFz8W2xUzUqWmqoyVxJLYuC58ZKpcTYQ==", + "requires": { + "bl": "^2.2.0", + "bson": "^1.1.4", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + }, + "dependencies": { + "bson": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.4.tgz", + "integrity": "sha512-S/yKGU1syOMzO86+dGpg2qGoDL0zvzcb262G+gqEy6TgP6rt6z6qxSFX/8X6vLC91P7G7C3nLs0+bvDzmvBA3Q==" + } + } + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "mri": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.1.5.tgz", + "integrity": "sha512-d2RKzMD4JNyHMbnbWnznPaa8vbdlq/4pNZ3IgdaGrVbBhebBsGUUE/6qorTMYNS6TwuH3ilfOlD2bf4Igh8CKg==", + "dev": true + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "multiline": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/multiline/-/multiline-0.3.4.tgz", + "integrity": "sha1-HTjLBTCXtblLIfzTGxCxFlWd79w=", + "dev": true, + "requires": { + "strip-indent": "^0.1.0" + } + }, + "multimatch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-4.0.0.tgz", + "integrity": "sha512-lDmx79y1z6i7RNx0ZGCPq1bzJ6ZoDDKbvh7jxr9SJcWLkShMzXrHbYVpTdnhNM5MXpDUxCQ4DgqVttVXlBgiBQ==", + "dev": true, + "requires": { + "@types/minimatch": "^3.0.3", + "array-differ": "^3.0.0", + "array-union": "^2.1.0", + "arrify": "^2.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "multiparty": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/multiparty/-/multiparty-4.1.4.tgz", + "integrity": "sha1-TJbcvcEeP3kX4WFeZAtLUCK+ZP0=", + "requires": { + "fd-slicer": "~1.0.1", + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "nanoid": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz", + "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==" + }, + "natives": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/natives/-/natives-1.1.6.tgz", + "integrity": "sha512-6+TDFewD4yxY14ptjKaS63GVdtKiES1pTPyxn9Jb0rBqPMZ7VcCiooEhPNsr+mqHtMGxa/5c/HhcC4uPEUw/nA==", + "optional": true + }, + "needle": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.5.0.tgz", + "integrity": "sha512-o/qITSDR0JCyCKEQ1/1bnUXMmznxabbwi/Y4WwJElf+evwJNFNwIDMCCt5IigFVxgeGBJESLohGtIS9gEzo1fA==", + "requires": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "node-addon-api": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz", + "integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA==" + }, + "node-foursquare": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/node-foursquare/-/node-foursquare-0.2.1.tgz", + "integrity": "sha1-FOLhZxxmLrLRbRL7yJNrKLMBXjI=", + "requires": { + "winston": "0.6.x" + } + }, + "node-getopt": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/node-getopt/-/node-getopt-0.3.2.tgz", + "integrity": "sha512-yqkmYrMbK1wPrfz7mgeYvA4tBperLg9FQ4S3Sau3nSAkpOA0x0zC8nQ1siBwozy1f4SE8vq2n1WKv99r+PCa1Q==" + }, + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "optional": true, + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", + "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "optional": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "optional": true, + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "optional": true + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "optional": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "node-linkedin": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/node-linkedin/-/node-linkedin-0.2.0.tgz", + "integrity": "sha1-LSwDnLhx0N9dwUIrw+HPnhlpCj8=", + "requires": { + "lodash": "~2.4.1", + "request": "~2.31.0" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "optional": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "optional": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=" + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "optional": true, + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime": "~1.2.11" + } + }, + "hawk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", + "integrity": "sha1-uQuxaYByhUEdp//LjdJZhQLTtS0=", + "optional": true, + "requires": { + "boom": "0.4.x", + "cryptiles": "0.2.x", + "hoek": "0.9.x", + "sntp": "0.2.x" + } + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "^0.1.5", + "ctype": "0.5.3" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=" + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "oauth-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", + "optional": true + }, + "qs": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=" + }, + "request": { + "version": "2.31.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.31.0.tgz", + "integrity": "sha1-TIrJZ8mkuUEMtLoaYf22RCZ+7v8=", + "requires": { + "aws-sign2": "~0.5.0", + "forever-agent": "~0.5.0", + "form-data": "~0.1.0", + "hawk": "~1.0.0", + "http-signature": "~0.10.0", + "json-stringify-safe": "~5.0.0", + "mime": "~1.2.9", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.3.0", + "qs": "~0.6.0", + "tough-cookie": "~0.9.15", + "tunnel-agent": "~0.3.0" + } + }, + "tough-cookie": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-0.9.15.tgz", + "integrity": "sha1-dWF6w0fjZZBSsDUBMYhYKWdzmfY=", + "optional": true, + "requires": { + "punycode": ">=0.2.0" + } + }, + "tunnel-agent": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz", + "integrity": "sha1-rWgbaPUyGtKCfEz7G31d8s/pQu4=", + "optional": true + } + } + }, + "node-pre-gyp": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", + "integrity": "sha512-TwWAOZb0j7e9eGaf9esRx3ZcLaE5tQ2lvYy1pb5IAaG1a2e2Kv5Lms1Y4hpj+ciXJRofIxxlt5haeQ/2ANeE0Q==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + }, + "dependencies": { + "nopt": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.3.tgz", + "integrity": "sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg==", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "tar": { + "version": "4.4.13", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", + "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "requires": { + "chownr": "^1.1.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.8.6", + "minizlib": "^1.2.1", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.3" + } + } + } + }, + "nodemailer": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-0.6.5.tgz", + "integrity": "sha1-18yuckWalEy5fda3XuA3YnDV9Xw=", + "requires": { + "directmail": "~0.1.7", + "he": "~0.3.6", + "mailcomposer": "~0.2.10", + "public-address": "~0.1.1", + "readable-stream": "~1.1.9", + "simplesmtp": "~0.2 || ~0.3.30" + } + }, + "nodemon": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.4.tgz", + "integrity": "sha512-Ltced+hIfTmaS28Zjv1BM552oQ3dbwPqI4+zI0SLgq+wpJhSyqgYude/aZa/3i31VCQWMfXJVxvu86abcam3uQ==", + "requires": { + "chokidar": "^3.2.2", + "debug": "^3.2.6", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.0.4", + "pstree.remy": "^1.1.7", + "semver": "^5.7.1", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.2", + "update-notifier": "^4.0.0" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "normalize-url": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-4.5.0.tgz", + "integrity": "sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==" + }, + "npm-bundled": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.1.1.tgz", + "integrity": "sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA==", + "requires": { + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-normalize-package-bin": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz", + "integrity": "sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA==" + }, + "npm-packlist": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.4.8.tgz", + "integrity": "sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1", + "npm-normalize-package-bin": "^1.0.1" + } + }, + "npm-run-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-3.1.0.tgz", + "integrity": "sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth": { + "version": "0.9.15", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.15.tgz", + "integrity": "sha1-vR/vr2hslrdUda7VGWQS/2DPucE=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "object-inspect": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", + "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==" + }, + "object-is": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", + "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onecolor": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/onecolor/-/onecolor-2.5.0.tgz", + "integrity": "sha1-Ila2UdyAfBAfAK7b1JklxXpEMcE=" + }, + "onetime": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", + "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "opencollective-postinstall": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz", + "integrity": "sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==", + "dev": true + }, + "optimist": { + "version": "0.3.7", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.3.7.tgz", + "integrity": "sha1-yQlBrVnkJzMokjB00s8ufLxuwNk=", + "requires": { + "wordwrap": "~0.0.2" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-cancelable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-1.1.0.tgz", + "integrity": "sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==" + }, + "p-finally": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz", + "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==", + "dev": true + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "package-json": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-6.5.0.tgz", + "integrity": "sha512-k3bdm2n25tkyxcjSKzB5x8kfVxlMdgsbPr0GkZcwHsLpba6cBjqCt1KlcChKEvxHIcTB1FVMuwoijZ26xex5MQ==", + "requires": { + "got": "^9.6.0", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^6.2.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "packet-reader": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", + "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" + }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.0.0.tgz", + "integrity": "sha512-OOY5b7PAEFV0E2Fir1KOkxchnZNCdowAJgQ5NuxjpBKTRP3pQhwkrkxqQjeoKJ+fO7bCpmIZaogI4eZGDMEGOw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1", + "lines-and-columns": "^1.1.6" + } + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "passport": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.2.2.tgz", + "integrity": "sha1-nDjxe+uSnz2Br3uIOOhDDbhwPys=", + "requires": { + "passport-strategy": "1.x.x", + "pause": "0.0.1" + } + }, + "passport-facebook": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/passport-facebook/-/passport-facebook-1.0.3.tgz", + "integrity": "sha1-gqlaqwAXqxkLgVqx5kq3VILqzcc=", + "requires": { + "passport-oauth2": "1.x.x" + } + }, + "passport-github": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/passport-github/-/passport-github-0.1.5.tgz", + "integrity": "sha1-JY67da9AzcTjrxG+OhOLdcH4ZcE=", + "requires": { + "passport-oauth": "0.1.x", + "pkginfo": "0.2.x" + }, + "dependencies": { + "passport": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.1.18.tgz", + "integrity": "sha1-yCZEedy2QUytu2Z1LRKzfgtlJaE=", + "requires": { + "pause": "0.0.1", + "pkginfo": "0.2.x" + } + }, + "passport-oauth": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/passport-oauth/-/passport-oauth-0.1.15.tgz", + "integrity": "sha1-+3Tgr+hGFL+iVsX8cWzFa7/IzsA=", + "requires": { + "oauth": "0.9.x", + "passport": "~0.1.1", + "pkginfo": "0.2.x" + } + } + } + }, + "passport-google-oauth": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/passport-google-oauth/-/passport-google-oauth-0.1.5.tgz", + "integrity": "sha1-/WtIz5sgKDchx2NukdCUwWqGcdc=", + "requires": { + "passport-oauth": "~0.1.4", + "pkginfo": "0.2.x" + }, + "dependencies": { + "passport": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.1.18.tgz", + "integrity": "sha1-yCZEedy2QUytu2Z1LRKzfgtlJaE=", + "requires": { + "pause": "0.0.1", + "pkginfo": "0.2.x" + } + }, + "passport-oauth": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/passport-oauth/-/passport-oauth-0.1.15.tgz", + "integrity": "sha1-+3Tgr+hGFL+iVsX8cWzFa7/IzsA=", + "requires": { + "oauth": "0.9.x", + "passport": "~0.1.1", + "pkginfo": "0.2.x" + } + } + } + }, + "passport-instagram": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/passport-instagram/-/passport-instagram-0.1.2.tgz", + "integrity": "sha1-ochFJTMO7YoF0+z+w79WyqiVz9Y=", + "requires": { + "passport-oauth": "0.1.x", + "pkginfo": "0.2.x" + }, + "dependencies": { + "passport": { + "version": "0.1.18", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.1.18.tgz", + "integrity": "sha1-yCZEedy2QUytu2Z1LRKzfgtlJaE=", + "requires": { + "pause": "0.0.1", + "pkginfo": "0.2.x" + } + }, + "passport-oauth": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/passport-oauth/-/passport-oauth-0.1.15.tgz", + "integrity": "sha1-+3Tgr+hGFL+iVsX8cWzFa7/IzsA=", + "requires": { + "oauth": "0.9.x", + "passport": "~0.1.1", + "pkginfo": "0.2.x" + } + } + } + }, + "passport-linkedin-oauth2": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/passport-linkedin-oauth2/-/passport-linkedin-oauth2-1.6.1.tgz", + "integrity": "sha512-0qHAyxmiJxzk91C4VjlUWw7KtS6/33TFeFhvY1n2GaVpVfLfXEYJfQxls+jFbpetu/Wu5X2QgzWPJSf9F9k/IA==", + "requires": { + "passport-oauth2": "1.x.x", + "underscore": "^1.7.0" + } + }, + "passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha1-H+YyaMkudWBmJkN+O5BmYsFbpu4=", + "requires": { + "passport-strategy": "1.x.x" + } + }, + "passport-oauth": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-oauth/-/passport-oauth-1.0.0.tgz", + "integrity": "sha1-kK/2M4dUDwIImvKM2tOep/gNd98=", + "requires": { + "passport-oauth1": "1.x.x", + "passport-oauth2": "1.x.x" + } + }, + "passport-oauth1": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/passport-oauth1/-/passport-oauth1-1.1.0.tgz", + "integrity": "sha1-p96YiiEfnPRoc3cTDqdN8ycwyRg=", + "requires": { + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "utils-merge": "1.x.x" + } + }, + "passport-oauth2": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/passport-oauth2/-/passport-oauth2-1.5.0.tgz", + "integrity": "sha512-kqBt6vR/5VlCK8iCx1/KpY42kQ+NEHZwsSyt4Y6STiNjU+wWICG1i8ucc1FapXDGO15C5O5VZz7+7vRzrDPXXQ==", + "requires": { + "base64url": "3.x.x", + "oauth": "0.9.x", + "passport-strategy": "1.x.x", + "uid2": "0.0.x", + "utils-merge": "1.x.x" + } + }, + "passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha1-tVOaqPwiWj0a0XlHbd8ja0QPUuQ=" + }, + "passport-twitter": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/passport-twitter/-/passport-twitter-1.0.4.tgz", + "integrity": "sha1-AaeZ4fdgvy3knyul+6MigvGJMtc=", + "requires": { + "passport-oauth1": "1.x.x", + "xtraverse": "0.1.x" + } + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha1-HUCLP9t2kjuVQ9lvtMnf1TXZy10=" + }, + "pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pg": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.3.0.tgz", + "integrity": "sha512-jQPKWHWxbI09s/Z9aUvoTbvGgoj98AU7FDCcQ7kdejupn/TcNpx56v2gaOTzXkzOajmOEJEdi9eTh9cA2RVAjQ==", + "requires": { + "buffer-writer": "2.0.0", + "packet-reader": "1.0.0", + "pg-connection-string": "^2.3.0", + "pg-pool": "^3.2.1", + "pg-protocol": "^1.2.5", + "pg-types": "^2.1.0", + "pgpass": "1.x", + "semver": "4.3.2" + }, + "dependencies": { + "semver": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz", + "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c=" + } + } + }, + "pg-connection-string": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.3.0.tgz", + "integrity": "sha512-ukMTJXLI7/hZIwTW7hGMZJ0Lj0S2XQBCJ4Shv4y1zgQ/vqVea+FLhzywvPj0ujSuofu+yA4MYHGZPTsgjBgJ+w==" + }, + "pg-hstore": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.3.tgz", + "integrity": "sha512-qpeTpdkguFgfdoidtfeTho1Q1zPVPbtMHgs8eQ+Aan05iLmIs3Z3oo5DOZRclPGoQ4i68I1kCtQSJSa7i0ZVYg==", + "requires": { + "underscore": "^1.7.0" + } + }, + "pg-int8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", + "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==" + }, + "pg-pool": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.2.1.tgz", + "integrity": "sha512-BQDPWUeKenVrMMDN9opfns/kZo4lxmSWhIqo+cSAF7+lfi9ZclQbr9vfnlNaPr8wYF3UYjm5X0yPAhbcgqNOdA==" + }, + "pg-protocol": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.2.5.tgz", + "integrity": "sha512-1uYCckkuTfzz/FCefvavRywkowa6M5FohNMF5OjKrqo9PSR8gYc8poVmwwYQaBxhmQdBjhtP514eXy9/Us2xKg==" + }, + "pg-types": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", + "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "requires": { + "pg-int8": "1.0.1", + "postgres-array": "~2.0.0", + "postgres-bytea": "~1.0.0", + "postgres-date": "~1.0.4", + "postgres-interval": "^1.1.0" + } + }, + "pgpass": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.2.tgz", + "integrity": "sha1-Knu0G2BltnkH6R2hsHwYR8h3swY=", + "requires": { + "split": "^1.0.0" + } + }, + "picomatch": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", + "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==" + }, + "pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "requires": { + "find-up": "^4.0.0" + } + }, + "pkginfo": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/pkginfo/-/pkginfo-0.2.3.tgz", + "integrity": "sha1-cjnEKl72wwuPMoQ52bn/cQQkkPg=" + }, + "please-upgrade-node": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz", + "integrity": "sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==", + "dev": true, + "requires": { + "semver-compare": "^1.0.0" + } + }, + "postcss": { + "version": "5.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.0.21.tgz", + "integrity": "sha1-1M9vGXdGSMSSrFfCmPavs8BMrv4=", + "requires": { + "js-base64": "^2.1.9", + "source-map": "^0.5.5", + "supports-color": "^3.1.2" + }, + "dependencies": { + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=" + }, + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + }, + "supports-color": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.2.3.tgz", + "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", + "requires": { + "has-flag": "^1.0.0" + } + } + } + }, + "postgres-array": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", + "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==" + }, + "postgres-bytea": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", + "integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=" + }, + "postgres-date": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.5.tgz", + "integrity": "sha512-pdau6GRPERdAYUQwkBnGKxEfPyhVZXG/JiS44iZWiNdSOWE09N2lUgN6yshuq6fVSon4Pm0VMXd1srUUkLe9iA==" + }, + "postgres-interval": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", + "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "requires": { + "xtend": "^4.0.0" + } + }, + "prepend-http": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-2.0.0.tgz", + "integrity": "sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc=" + }, + "prettier": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.0.5.tgz", + "integrity": "sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg==" + }, + "pretty-quick": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-2.0.1.tgz", + "integrity": "sha512-y7bJt77XadjUr+P1uKqZxFWLddvj3SKY6EU4BuQtMxmmEFSMpbN132pUWdSG1g1mtUfO0noBvn7wBf0BVeomHg==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "execa": "^2.1.0", + "find-up": "^4.1.0", + "ignore": "^5.1.4", + "mri": "^1.1.4", + "multimatch": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "promise": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-6.1.0.tgz", + "integrity": "sha1-LOcp9rlLRcJoka0GAsXJDgTG7vY=", + "requires": { + "asap": "~1.0.0" + } + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "psl": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz", + "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==" + }, + "pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" + }, + "public-address": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/public-address/-/public-address-0.1.2.tgz", + "integrity": "sha1-+V8+DPKLifllsPGI/RJnrAhWVS8=" + }, + "pump": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", + "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "pupa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pupa/-/pupa-2.0.1.tgz", + "integrity": "sha512-hEJH0s8PXLY/cdXh66tNEQGndDrIKNqNC5xmrysZy3i5C3oEoLna7YAOad+7u125+zH1HNXUmGEkrhb3c2VriA==", + "requires": { + "escape-goat": "^2.0.0" + } + }, + "q": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/q/-/q-0.9.7.tgz", + "integrity": "sha1-TeLmyzspCIyeTLwDv51C+5bOL3U=" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "rai": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/rai/-/rai-0.1.12.tgz", + "integrity": "sha1-jM/QFND5YIYw3XPBm45LBXdUpqY=" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + } + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "readdirp": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.4.0.tgz", + "integrity": "sha512-0xe001vZBnJEK+uKcj8qOhyAKPzIT+gStxWr3LCB0DwcXR5NZJ3IaC+yGnHCYzB/S7ov3m3EEbZI2zeNvX+hGQ==", + "requires": { + "picomatch": "^2.2.1" + } + }, + "reduce-component": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-component/-/reduce-component-1.0.1.tgz", + "integrity": "sha1-4Mk1QsV0UhvqE98PlIjtgqt3xdo=", + "dev": true + }, + "regexp.prototype.flags": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", + "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.0-next.1" + } + }, + "registry-auth-token": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/registry-auth-token/-/registry-auth-token-4.1.1.tgz", + "integrity": "sha512-9bKS7nTl9+/A1s7tnPeGrUpRcVY+LUh7bfFgzpndALdPfXQBfQV77rQVtqgUV3ti4vc/Ik81Ex8UJDWDQ12zQA==", + "requires": { + "rc": "^1.2.8" + } + }, + "registry-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/registry-url/-/registry-url-5.1.0.tgz", + "integrity": "sha512-8acYXXTI0AkQv6RAOjE3vOaIXZkT9wo4LOFbBKYQEEnnMNBpKqdUrI6S4NT0KPIo/WVvJ5tE/X5LF/TQUf0ekw==", + "requires": { + "rc": "^1.2.8" + } + }, + "repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + }, + "request": { + "version": "2.88.2", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz", + "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.3", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.5.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + } + } + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "requirejs": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.6.tgz", + "integrity": "sha512-ipEzlWQe6RK3jkzikgCupiTbTvm4S0/CAU5GlgptkN5SO6F3u0UD0K18wy6ErDqiCyP4J4YYe1HuAShvsxePLg==" + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "responselike": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-1.0.2.tgz", + "integrity": "sha1-kYcg7ztjHFZCvgaPFa3lpG9Loec=", + "requires": { + "lowercase-keys": "^1.0.0" + } + }, + "retry-as-promised": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.2.0.tgz", + "integrity": "sha512-CybGs60B7oYU/qSQ6kuaFmRd9sTZ6oXSc0toqePvV74Ac6/IFZSI1ReFQmtCN+uvW1Mtqdwpvt/LGOiCBAY2Mg==", + "requires": { + "any-promise": "^1.3.0" + } + }, + "right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", + "requires": { + "align-text": "^0.1.1" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sanitize-filename": { + "version": "1.6.3", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.3.tgz", + "integrity": "sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==", + "requires": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "scmp": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/scmp/-/scmp-0.0.3.tgz", + "integrity": "sha1-NkjfLXKUZB5/eGc//CloHZutkHM=" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha1-De4hahyUGrN+nvsXiPavxf9VN/w=", + "dev": true + }, + "semver-diff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz", + "integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==", + "requires": { + "semver": "^6.3.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==" + } + } + }, + "semver-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-2.0.0.tgz", + "integrity": "sha512-mUdIBBvdn0PLOeP3TEkMH7HHeUP3GjsXCwKarjv/kGmUFOYg1VqEemKhoQpWMu6X2I8kHeuVdGibLGkVK+/5Qw==", + "dev": true + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "sequelize": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.3.3.tgz", + "integrity": "sha512-WO/b1ehjSFKlBCHzwZoaPhoW3WyXXy9x74yPrOP8NpE67wzbv0dIucDO4a+THLVyl3lnv3nFMZdJRdkUgb/ZAw==", + "requires": { + "debug": "^4.1.1", + "dottie": "^2.0.0", + "inflection": "1.12.0", + "lodash": "^4.17.15", + "moment": "^2.26.0", + "moment-timezone": "^0.5.31", + "retry-as-promised": "^3.2.0", + "semver": "^7.3.2", + "sequelize-pool": "^6.0.0", + "toposort-class": "^1.0.1", + "uuid": "^8.1.0", + "validator": "^10.11.0", + "wkx": "^0.5.0" + }, + "dependencies": { + "debug": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", + "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "requires": { + "ms": "^2.1.1" + } + }, + "lodash": { + "version": "4.17.19", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", + "integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "semver": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.2.tgz", + "integrity": "sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ==" + }, + "uuid": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.2.0.tgz", + "integrity": "sha512-CYpGiFTUrmI6OBMkAdjSDM0k5h8SkkiTP4WAjQgDgNB1S3Ou9VBEvr6q0Kv2H1mMk7IWfxYGpMH5sd5AvcIV2Q==" + }, + "validator": { + "version": "10.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.11.0.tgz", + "integrity": "sha512-X/p3UZerAIsbBfN/IwahhYaBbY68EN/UQBWHtsbXGT5bfrH/p4NQzUCG1kF/rtKaNpnJ7jAu6NGTdSNtyNIXMw==" + } + } + }, + "sequelize-pool": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-6.1.0.tgz", + "integrity": "sha512-4YwEw3ZgK/tY/so+GfnSgXkdwIJJ1I32uZJztIEgZeAO6HMgj64OzySbWLgxj+tXhZCJnzRfkY9gINw8Ft8ZMg==" + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "shellwords": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz", + "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==" + }, + "shortid": { + "version": "2.2.15", + "resolved": "https://registry.npmjs.org/shortid/-/shortid-2.2.15.tgz", + "integrity": "sha512-5EaCy2mx2Jgc/Fdn9uuDuNIIfWBpzY4XIlhoqtXF6qsf+/+SGZ+FxDdX/ZsMZiWupIWNqAEmiNY4RC+LSmCeOw==", + "requires": { + "nanoid": "^2.1.0" + } + }, + "should": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/should/-/should-0.6.3.tgz", + "integrity": "sha1-1LVTNciQjzpsR5cLaH91A3Ks3HM=" + }, + "side-channel": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz", + "integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==", + "requires": { + "es-abstract": "^1.17.0-next.1", + "object-inspect": "^1.7.0" + } + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==" + }, + "simplesmtp": { + "version": "0.3.35", + "resolved": "https://registry.npmjs.org/simplesmtp/-/simplesmtp-0.3.35.tgz", + "integrity": "sha1-AXseuLJjF6w20qKoqTJjGIBzagM=", + "requires": { + "rai": "~0.1.11", + "xoauth2": "~0.1.8" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + }, + "slug": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/slug/-/slug-0.9.4.tgz", + "integrity": "sha512-3YHq0TeJ4+AIFbJm+4UWSQs5A1mmeWOTQqydW3OoPmQfNKxlO96NDRTIrp+TBkmvEsEFrd+Z/LXw8OD/6OlZ5g==", + "requires": { + "unicode": ">= 0.3.1" + } + }, + "sntp": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-0.2.4.tgz", + "integrity": "sha1-+4hfGLDzqtGJ+CSGJTa87ux1CQA=", + "requires": { + "hoek": "0.9.x" + } + }, + "source-map": { + "version": "0.1.43", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.1.43.tgz", + "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", + "requires": { + "amdefine": ">=0.0.4" + } + }, + "source-map-support": { + "version": "0.5.19", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", + "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + }, + "dependencies": { + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "requires": { + "through": "2" + } + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=" + }, + "sqlite3": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.0.0.tgz", + "integrity": "sha512-rjvqHFUaSGnzxDy2AHCwhHy6Zp6MNJzCPGYju4kD8yi6bze4d1/zMTg6C7JI49b7/EM7jKMTvyfN/4ylBKdwfw==", + "requires": { + "node-addon-api": "2.0.0", + "node-gyp": "3.x", + "node-pre-gyp": "^0.11.0" + } + }, + "sshpk": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", + "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "streamspeed": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/streamspeed/-/streamspeed-2.0.0.tgz", + "integrity": "sha512-RFsqRckd50tB2TOBLE3FGohvoxdOxKk7AuePNCKkoN/I3nXh44EQ4KTFHh0EEoXErcmzlgjw3Z0v9uY7MCEu1A==" + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + } + } + }, + "string.prototype.trimend": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", + "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string.prototype.trimstart": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", + "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", + "requires": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + }, + "stringstream": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.6.tgz", + "integrity": "sha512-87GEBAkegbBcweToUrdzf3eLhWNg06FJTebl4BVJz/JgWy8CvEr9dRtX5qWphiynMSQlxxi+QqN0z5T32SLlhA==", + "optional": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-0.1.3.tgz", + "integrity": "sha1-xDzLZsJOScTieyI200/ixLvPFNw=", + "dev": true + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "stripe": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/stripe/-/stripe-2.9.0.tgz", + "integrity": "sha1-7nGbvxLmtVr9dH83Hg1Dr48xEc8=", + "requires": { + "when": "~3.1.0" + } + }, + "superagent": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-0.18.0.tgz", + "integrity": "sha1-nUN1o64sT71V/SDVsSokcNL8j2I=", + "dev": true, + "requires": { + "component-emitter": "1.1.2", + "cookiejar": "1.3.2", + "debug": "~0.7.2", + "extend": "~1.2.1", + "form-data": "0.1.2", + "formidable": "1.0.14", + "methods": "0.0.1", + "mime": "1.2.5", + "qs": "0.6.6", + "readable-stream": "1.0.27-1", + "reduce-component": "1.0.1" + }, + "dependencies": { + "async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha1-trvgsGdLnXGXCMo43owjfLUmw9E=", + "dev": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "dev": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "debug": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", + "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=", + "dev": true + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "dev": true + }, + "extend": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/extend/-/extend-1.2.1.tgz", + "integrity": "sha1-oPX9bPyDpf5J72mNYOyKYk3UV2w=", + "dev": true + }, + "form-data": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.2.tgz", + "integrity": "sha1-EUPCE1eRGnjdeROxibS6tdXVdEU=", + "dev": true, + "requires": { + "async": "~0.2.9", + "combined-stream": "~0.0.4", + "mime": "~1.2.11" + }, + "dependencies": { + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "dev": true + } + } + }, + "formidable": { + "version": "1.0.14", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.0.14.tgz", + "integrity": "sha1-Kz9MQRy7X91pXESEPiojUUpDIxo=", + "dev": true + }, + "methods": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/methods/-/methods-0.0.1.tgz", + "integrity": "sha1-J3yQ+L7zlwlkWoNxxRw7bGSOBow=", + "dev": true + }, + "mime": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.5.tgz", + "integrity": "sha1-nu0HMCKov14WyFZsaGe4gyv7+hM=", + "dev": true + }, + "qs": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=", + "dev": true + }, + "readable-stream": { + "version": "1.0.27-1", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.27-1.tgz", + "integrity": "sha1-a2eYPCA1fO/QfwFlABoW1xDZEHg=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + } + } + }, + "supertest": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-0.13.0.tgz", + "integrity": "sha1-SJK6/ZvqqbvMlf1anwSUmu8c4G8=", + "dev": true, + "requires": { + "methods": "1.0.0", + "superagent": "0.18.0" + }, + "dependencies": { + "methods": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.0.0.tgz", + "integrity": "sha1-mnPYY3XfzvJu9hyj5Lii4lOKgOM=", + "dev": true + } + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "optional": true, + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + }, + "term-size": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/term-size/-/term-size-2.2.0.tgz", + "integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw==" + }, + "terser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz", + "integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==", + "dev": true, + "requires": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "dependencies": { + "commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + } + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "to-readable-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-readable-stream/-/to-readable-stream-1.0.0.tgz", + "integrity": "sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==" + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "requires": { + "nopt": "~1.0.10" + } + }, + "tough-cookie": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz", + "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==", + "requires": { + "psl": "^1.1.28", + "punycode": "^2.1.1" + } + }, + "transformers": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/transformers/-/transformers-2.1.0.tgz", + "integrity": "sha1-XSPLNVYd2F3Gf7hIIwm0fVPM6ac=", + "requires": { + "css": "~1.0.8", + "promise": "~2.0", + "uglify-js": "~2.2.5" + }, + "dependencies": { + "is-promise": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-1.0.1.tgz", + "integrity": "sha1-MVc3YcBX4zwukaq56W2gjO++duU=" + }, + "promise": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/promise/-/promise-2.0.0.tgz", + "integrity": "sha1-RmSKqdYFr10ucMMCS/WUNtoCuA4=", + "requires": { + "is-promise": "~1" + } + }, + "uglify-js": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.2.5.tgz", + "integrity": "sha1-puAqcNg5eSuXgEiLe4sYTAlcmcc=", + "requires": { + "optimist": "~0.3.5", + "source-map": "~0.1.7" + } + } + } + }, + "truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha1-QFkjkJWS1W94pYGENLC3hInKXys=", + "requires": { + "utf8-byte-length": "^1.0.1" + } + }, + "tsscmp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz", + "integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==" + }, + "tumblr.js": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/tumblr.js/-/tumblr.js-0.0.4.tgz", + "integrity": "sha1-V/i8PSMVtFMCuhDCFwtcMArvR4w=", + "requires": { + "request": "2.12.0" + }, + "dependencies": { + "request": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.12.0.tgz", + "integrity": "sha1-EfRvILPQ9ISMY4OZHIB5CvFsjkg=", + "requires": { + "form-data": "~0.0.3", + "mime": "~1.2.7" + }, + "dependencies": { + "form-data": { + "version": "0.0.3", + "bundled": true, + "requires": { + "async": "~0.1.9", + "combined-stream": "0.0.3", + "mime": "~1.2.2" + }, + "dependencies": { + "async": { + "version": "0.1.9", + "bundled": true + }, + "combined-stream": { + "version": "0.0.3", + "bundled": true, + "requires": { + "delayed-stream": "0.0.5" + }, + "dependencies": { + "delayed-stream": { + "version": "0.0.5", + "bundled": true + } + } + } + } + }, + "mime": { + "version": "1.2.7", + "bundled": true + } + } + } + } + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "twilio": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/twilio/-/twilio-1.11.1.tgz", + "integrity": "sha1-cOYD0aYdNFvWHI7jmid/lgUYjFY=", + "requires": { + "jwt-simple": "0.1.x", + "q": "0.9.7", + "request": "2.27.x", + "scmp": "0.0.3", + "underscore": "1.x" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=" + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=" + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "requires": { + "delayed-stream": "0.0.5" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=" + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=" + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime": "~1.2.11" + } + }, + "hawk": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-1.0.0.tgz", + "integrity": "sha1-uQuxaYByhUEdp//LjdJZhQLTtS0=", + "requires": { + "boom": "0.4.x", + "cryptiles": "0.2.x", + "hoek": "0.9.x", + "sntp": "0.2.x" + } + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "requires": { + "asn1": "0.1.11", + "assert-plus": "^0.1.5", + "ctype": "0.5.3" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=" + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "oauth-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=" + }, + "qs": { + "version": "0.6.6", + "resolved": "https://registry.npmjs.org/qs/-/qs-0.6.6.tgz", + "integrity": "sha1-bgFQmP9RlouKPIGQAdXyyJvEsQc=" + }, + "request": { + "version": "2.27.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.27.0.tgz", + "integrity": "sha1-37GiJN06Wput5DNwElA9cQ5Thmg=", + "requires": { + "aws-sign": "~0.3.0", + "cookie-jar": "~0.3.0", + "forever-agent": "~0.5.0", + "form-data": "~0.1.0", + "hawk": "~1.0.0", + "http-signature": "~0.10.0", + "json-stringify-safe": "~5.0.0", + "mime": "~1.2.9", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.3.0", + "qs": "~0.6.0", + "tunnel-agent": "~0.3.0" + } + }, + "tunnel-agent": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.3.0.tgz", + "integrity": "sha1-rWgbaPUyGtKCfEz7G31d8s/pQu4=" + } + } + }, + "twit": { + "version": "1.1.20", + "resolved": "https://registry.npmjs.org/twit/-/twit-1.1.20.tgz", + "integrity": "sha1-Fw5n0Bh5hILK8pmN1Mb48py1SGE=", + "requires": { + "oauth": "0.9.9" + }, + "dependencies": { + "oauth": { + "version": "0.9.9", + "resolved": "https://registry.npmjs.org/oauth/-/oauth-0.9.9.tgz", + "integrity": "sha1-7/EAAWHbZBrgyCbZl4mV83xG6Gk=" + } + } + }, + "type-detect": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-0.1.1.tgz", + "integrity": "sha1-C6XsKohWQORw6k6FBZcZANrFiCI=", + "dev": true + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "typedarray-to-buffer": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", + "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", + "requires": { + "is-typedarray": "^1.0.0" + } + }, + "uglify-js": { + "version": "2.8.29", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz", + "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", + "requires": { + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=" + } + } + }, + "uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=" + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, + "uid2": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/uid2/-/uid2-0.0.3.tgz", + "integrity": "sha1-SDEm4Rd03y9xuLY53NeZw3YWK4I=" + }, + "undefsafe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.3.tgz", + "integrity": "sha512-nrXZwwXrD/T/JXeygJqdCO6NZZ1L66HrxM/Z7mIq2oPanoN0F1nLx3lwJMu6AwJY69hdixaFQOuoYsMjE5/C2A==", + "requires": { + "debug": "^2.2.0" + } + }, + "underscore": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz", + "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg==" + }, + "unicode": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/unicode/-/unicode-12.1.0.tgz", + "integrity": "sha512-Ty6+Ew21DiYTWLYtd05RF/X4c1ekOvOgANyHbBj0h3MaXpfaGr2Rdmc0hMFuGQLyPLb9cU4ArNxl0bTF5HSzXw==" + }, + "unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "requires": { + "crypto-random-string": "^2.0.0" + } + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "update-notifier": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/update-notifier/-/update-notifier-4.1.0.tgz", + "integrity": "sha512-w3doE1qtI0/ZmgeoDoARmI5fjDoT93IfKgEGqm26dGUOh8oNpaSTsGNdYRN/SjOuo10jcJGwkEL3mroKzktkew==", + "requires": { + "boxen": "^4.2.0", + "chalk": "^3.0.0", + "configstore": "^5.0.1", + "has-yarn": "^2.1.0", + "import-lazy": "^2.1.0", + "is-ci": "^2.0.0", + "is-installed-globally": "^0.3.1", + "is-npm": "^4.0.0", + "is-yarn-global": "^0.3.0", + "latest-version": "^5.0.0", + "pupa": "^2.0.1", + "semver-diff": "^3.1.1", + "xdg-basedir": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, + "url-parse-lax": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-3.0.0.tgz", + "integrity": "sha1-FrXK/Afb42dsGxmZF3gj1lA6yww=", + "requires": { + "prepend-http": "^2.0.0" + } + }, + "utf8-byte-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.4.tgz", + "integrity": "sha1-9F8VDExm7uloGGUFq5P8u4rWv2E=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==" + }, + "validator": { + "version": "3.43.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-3.43.0.tgz", + "integrity": "sha1-lkZLmS1BloM9l6GUv0Cxn/VLrgU=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "void-elements": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz", + "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=" + }, + "when": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/when/-/when-3.1.0.tgz", + "integrity": "sha1-okeWWcoV9yVUHs9S664JG3ge4TQ=" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "which-boxed-primitive": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.1.tgz", + "integrity": "sha512-7BT4TwISdDGBgaemWU0N0OU7FeAEJ9Oo2P1PHRm/FCWoEi2VLWC9b6xvxAA3C/NMpxg3HXVgi0sMmGbNUbNepQ==", + "requires": { + "is-bigint": "^1.0.0", + "is-boolean-object": "^1.0.0", + "is-number-object": "^1.0.3", + "is-string": "^1.0.4", + "is-symbol": "^1.0.2" + } + }, + "which-collection": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", + "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "requires": { + "is-map": "^2.0.1", + "is-set": "^2.0.1", + "is-weakmap": "^2.0.1", + "is-weakset": "^2.0.1" + } + }, + "which-pm-runs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.0.0.tgz", + "integrity": "sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=", + "dev": true + }, + "which-typed-array": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.2.tgz", + "integrity": "sha512-KT6okrd1tE6JdZAy3o2VhMoYPh3+J6EMZLyrxBQsZflI1QCZIxMrIYLkosd8Twf+YfknVIHmYQPgJt238p8dnQ==", + "requires": { + "available-typed-arrays": "^1.0.2", + "es-abstract": "^1.17.5", + "foreach": "^2.0.5", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.1", + "is-typed-array": "^1.1.3" + } + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "requires": { + "string-width": "^4.0.0" + } + }, + "window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0=" + }, + "winston": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/winston/-/winston-0.6.2.tgz", + "integrity": "sha1-QUT+JYbNwZphK/jANVkBMskGS9I=", + "requires": { + "async": "0.1.x", + "colors": "0.x.x", + "cycle": "1.0.x", + "eyes": "0.1.x", + "pkginfo": "0.2.x", + "request": "2.9.x", + "stack-trace": "0.0.x" + }, + "dependencies": { + "async": { + "version": "0.1.22", + "resolved": "https://registry.npmjs.org/async/-/async-0.1.22.tgz", + "integrity": "sha1-D8GqoIig4+8Ovi2IMbqw3PiEUGE=" + }, + "colors": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-0.6.2.tgz", + "integrity": "sha1-JCP+ZnisDF2uiFLl0OW+CMmXq8w=" + }, + "request": { + "version": "2.9.203", + "resolved": "https://registry.npmjs.org/request/-/request-2.9.203.tgz", + "integrity": "sha1-bBcRpUB/uUoRQhlWPkQUW8v0cjo=" + } + } + }, + "with": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/with/-/with-4.0.3.tgz", + "integrity": "sha1-7v0VTp550sjTQXtkeo8U2f7M4U4=", + "requires": { + "acorn": "^1.0.1", + "acorn-globals": "^1.0.3" + }, + "dependencies": { + "acorn": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-1.2.2.tgz", + "integrity": "sha1-yM4n3grMdtiW0rH6099YjZ6C8BQ=" + } + } + }, + "wkx": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", + "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "requires": { + "@types/node": "*" + } + }, + "wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha1-o9XabNXAvAAI03I0u68b7WMFkQc=" + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "requires": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==" + }, + "xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "requires": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "dependencies": { + "xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==" + } + } + }, + "xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==" + }, + "xmldom": { + "version": "0.1.31", + "resolved": "https://registry.npmjs.org/xmldom/-/xmldom-0.1.31.tgz", + "integrity": "sha512-yS2uJflVQs6n+CyjHoaBmVSqIDevTAWrzMmjG1Gc7h1qQ7uVozNhEPJAwZXWyGQ/Gafo3fCwrcaokezLPupVyQ==" + }, + "xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + }, + "xoauth2": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/xoauth2/-/xoauth2-0.1.8.tgz", + "integrity": "sha1-uRb/EOz7VDIPFvJKPpdRIGU6sNI=" + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" + }, + "xtraverse": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/xtraverse/-/xtraverse-0.1.0.tgz", + "integrity": "sha1-t0G60BjveNip0ug63gB7P3lZxzI=", + "requires": { + "xmldom": "0.1.x" + } + }, + "yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" + }, + "yaml": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.0.tgz", + "integrity": "sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg==", + "dev": true + }, + "yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", + "requires": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "ytdl": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ytdl/-/ytdl-1.3.5.tgz", + "integrity": "sha512-1wn5b6R7JJxwzNLLvgc0ptBdSgPLr7nB++i5r3T6ApoZMy/X/sD5QlzkHAeYqjzeGxIK0koOsCddRsADDQ9H4Q==", + "requires": { + "chalk": "^4.0.0", + "cli-progress": "^3.8.2", + "commander": "^5.1.0", + "homedir": "^0.6.0", + "list-it": "^1.3.3", + "lodash.throttle": "^4.1.1", + "sanitize-filename": "^1.6.3", + "streamspeed": "^2.0.0", + "ytdl-core": "^3.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "requires": { + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", + "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" + }, + "m3u8stream": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.7.1.tgz", + "integrity": "sha512-z6ldnAdhbuWOL6LmMkwptSZGzj+qbRytMKLTbNicwF/bJMjf9U9lqD57RNQUFecvWadEkzy6PDjcNJFFgi19uQ==", + "requires": { + "miniget": "^1.6.1", + "sax": "^1.2.4" + }, + "dependencies": { + "miniget": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/miniget/-/miniget-1.7.2.tgz", + "integrity": "sha512-USPNNK2bnHLOplX8BZVMehUkyQizS/DFpBdoH0TS+fM+hQoLNg9tWg4MeY9wE8gfY0pbzmx5UBEODujt3Lz8AA==" + } + } + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "requires": { + "has-flag": "^4.0.0" + } + }, + "ytdl-core": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-3.4.2.tgz", + "integrity": "sha512-R6m1XZQK+iXxb9Q9Wo14/K8mti1r4HnKv4zKrbp5FvMG/jDbeV0xQHUHqqDLk+uiDy/VU6fVATm5x2ms0QaF5w==", + "requires": { + "html-entities": "^1.3.1", + "m3u8stream": "^0.7.1", + "miniget": "^2.0.1", + "sax": "^1.1.3" + } + } + } + }, + "ytdl-core": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.0.3.tgz", + "integrity": "sha512-+pM+EocvdHHTfH3xCr3c41cIm8bD7IE/wv/QKjaO7PwdLaaOMIj7xc/7yWwy9NwUDgIKA1YTotcn0qpQ0FVtMA==", + "requires": { + "html-entities": "^1.3.1", + "m3u8stream": "^0.8.0", + "miniget": "^2.1.0", + "sax": "^1.1.3" + } + }, + "yui": { + "version": "3.18.1", + "resolved": "https://registry.npmjs.org/yui/-/yui-3.18.1.tgz", + "integrity": "sha1-4AAmnsCntvvHQcu4/L0OZRF7AUw=", + "requires": { + "request": "~2.40.0" + }, + "dependencies": { + "asn1": { + "version": "0.1.11", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.1.11.tgz", + "integrity": "sha1-VZvhg3bQik7E2+gId9J4GGObLfc=", + "optional": true + }, + "assert-plus": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.1.5.tgz", + "integrity": "sha1-7nQAlBMALYTOxyGcasgRgS5yMWA=", + "optional": true + }, + "aws-sign2": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz", + "integrity": "sha1-xXED96F/wDfwLXwuZLYC6iI/fWM=", + "optional": true + }, + "combined-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-0.0.7.tgz", + "integrity": "sha1-ATfmV7qlp1QcV6w3rF/AfXO03B8=", + "optional": true, + "requires": { + "delayed-stream": "0.0.5" + } + }, + "delayed-stream": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz", + "integrity": "sha1-1LH0OpPoKW3+AmlPRoC8N6MTxz8=", + "optional": true + }, + "forever-agent": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.5.2.tgz", + "integrity": "sha1-bQ4JxJIflKJ/Y9O0nF/v8epMUTA=" + }, + "form-data": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-0.1.4.tgz", + "integrity": "sha1-kavXiKupcCsaq/qLwBAxoqyeOxI=", + "optional": true, + "requires": { + "async": "~0.9.0", + "combined-stream": "~0.0.4", + "mime": "~1.2.11" + } + }, + "http-signature": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-0.10.1.tgz", + "integrity": "sha1-T72sEyVZqoMjEh5UB3nAoBKyfmY=", + "optional": true, + "requires": { + "asn1": "0.1.11", + "assert-plus": "^0.1.5", + "ctype": "0.5.3" + } + }, + "mime": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.2.11.tgz", + "integrity": "sha1-WCA+7Ybjpe8XrtK32evUfwpg3RA=", + "optional": true + }, + "mime-types": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-1.0.2.tgz", + "integrity": "sha1-mVrhOSq4r/y/yyZB3QVOlDwNXc4=" + }, + "node-uuid": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz", + "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=" + }, + "oauth-sign": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.3.0.tgz", + "integrity": "sha1-y1QPk7srIqfVlBaRoojWDo6pOG4=", + "optional": true + }, + "qs": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-1.0.2.tgz", + "integrity": "sha1-UKk+K1r2aRwxvOpdrnjubqGQN2g=" + }, + "request": { + "version": "2.40.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.40.0.tgz", + "integrity": "sha1-TdZw9pbx5uhC5mtLXoOTAaub62c=", + "requires": { + "aws-sign2": "~0.5.0", + "forever-agent": "~0.5.0", + "form-data": "~0.1.0", + "hawk": "1.1.1", + "http-signature": "~0.10.0", + "json-stringify-safe": "~5.0.0", + "mime-types": "~1.0.1", + "node-uuid": "~1.4.0", + "oauth-sign": "~0.3.0", + "qs": "~1.0.0", + "stringstream": "~0.0.4", + "tough-cookie": ">=0.12.0", + "tunnel-agent": "~0.4.0" + } + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json index 8e216fd..434c01d 100755 --- a/package.json +++ b/package.json @@ -7,38 +7,49 @@ }, "scripts": { "start": "node app.js", - "test": "mocha" + "dev": "nodemon node app.js", + "build": "cd public/js && r.js -o build.js optimize=none && terser main-built.js --compress --mangle -o main-built.min.js && rm main-built.js", + "test": "mocha", + "precommit": "pretty-quick --staged", + "postcommit": "git update-index -g", + "pretty": "prettier --write \"./**/*.{js,jsx,json}\"" }, "dependencies": { "async": "^0.9.0", "bcrypt-nodejs": "^0.0.3", "body-parser": "^1.2.0", + "bson": "^4.0.4", "cheerio": "^0.16.0", "clockwork": "^0.1.1", "compression": "^1.0.2", - "connect-assets": "^3.0.1", - "connect-mongo": "^0.4.1", + "connect-assets": "^5.4.0", + "connect-mongo": "^3.2.0", + "connect-session-sequelize": "^7.0.0", "cookie-parser": "^1.1.0", "csso": "^1.3.11", "errorhandler": "^1.0.1", - "express": "^4.3.1", + "express": "^4.17.1", "express-flash": "^0.0.2", "express-session": "^1.2.0", "express-validator": "^2.1.2", - "formidable": "^1.0.14", "fbgraph": "^0.2.10", + "formidable": "^1.0.14", "github-api": "^0.7.0", + "heroku-ssl-redirect": "0.0.4", "instagram-node": "^0.4.0", "jade": "^1.3.1", "lastfm": "^0.9.0", "less": "^1.7.0", "lusca": "^1.0.0", + "memory-cache": "0.0.5", "method-override": "^1.0.0", - "mongoose": "^3.8.11", + "mkdirp": "~0.5.1", "morgan": "^1.1.1", + "multiparty": "~4.1.2", "node-foursquare": "^0.2.1", "node-linkedin": "^0.2.0", "nodemailer": "^0.6.5", + "nodemon": "^2.0.4", "passport": "^0.2.0", "passport-facebook": "^1.0.3", "passport-github": "^0.1.5", @@ -48,7 +59,15 @@ "passport-local": "^1.0.0", "passport-oauth": "^1.0.0", "passport-twitter": "^1.0.2", + "pg": "^8.3.0", + "pg-hstore": "^2.3.3", + "prettier": "^2.0.5", "request": "^2.36.0", + "requirejs": "^2.3.6", + "sequelize": "^6.3.3", + "shortid": "^2.2.15", + "slug": "~0.9.1", + "sqlite3": "^5.0.0", "stripe": "^2.6.3", "tumblr.js": "^0.0.4", "twilio": "^1.6.0", @@ -56,20 +75,19 @@ "uglify-js": "^2.4.13", "underscore": "^1.6.0", "validator": "^3.12.0", - "ytdl": "^0.2.8", - "yui": "^3.17.1", - "memory-cache": "0.0.5", - "mongoose-minid": "~1.1.1", - "mkdirp": "~0.5.1", - "multiparty": "~4.1.2", - "slug": "~0.9.1" + "ytdl": "^1.3.5", + "ytdl-core": "^4.0.3", + "yui": "^3.17.1" }, "devDependencies": { "blessed": "0.0.29", "chai": "^1.9.1", + "husky": "^4.2.5", "mocha": "^1.19.0", "multiline": "^0.3.4", - "supertest": "^0.13.0" + "pretty-quick": "^2.0.1", + "supertest": "^0.13.0", + "terser": "^4.8.0" }, "description": "placeholder", "bugs": { diff --git a/public/css/base.less b/public/css/base.less index 3ed89a9..abfbcb1 100644 --- a/public/css/base.less +++ b/public/css/base.less @@ -1,5 +1,4 @@ @import "lib/bootstrap/bootstrap"; -@import (less) "lib/font-awesome.min.css"; @import "lib/toastr"; // Customize variables @@ -24,7 +23,6 @@ body { } .navbar-brand { - //background: url(http://192.241.199.43/img/placeholder.png) no-repeat left center; //background-size: 40px; //padding-left: 50px; //margin-left: 15px; diff --git a/public/css/edit-interface.css b/public/css/edit-interface.css index 2d2db7f..f52d4fd 100644 --- a/public/css/edit-interface.css +++ b/public/css/edit-interface.css @@ -3,32 +3,32 @@ /***************/ * { - box-sizing: border-box; + box-sizing: border-box; } body { - font-size: 13px; - width: 100%; - min-width: 1250px; - color: rgb(100, 92, 111); + font-size: 13px; + width: 100%; + min-width: 1250px; + color: rgb(100, 92, 111); } body.viewing { - padding-top: 40px; + padding-top: 40px; } #main-container.container { - width: 100%; - margin: 0; - padding: 0; - position: relative; + width: 100%; + margin: 0; + padding: 0; + position: relative; } -[class*="iconicfill-"]:before { +[class*='iconicfill-']:before { font-family: 'IconicFill', sans-serif; } -[data-ph]:empty:before{ +[data-ph]:empty:before { content: attr(data-ph); color: #888; font-style: italic; @@ -39,293 +39,298 @@ body.viewing { /* published css */ /********************/ body.published .toolbar { - display: none; + display: none; } /********************/ /* video form css */ /********************/ #video-form { - display: none; + display: none; } -#yturl, #tranupload { - display: block; - height: 30px; - width: 100%; - position: static; +#yturl, +#tranupload { + display: block; + height: 30px; + width: 100%; + position: static; } -.yturlgroup, .trangroup, .confirmgroup, .processinggroup { - display: none; +.yturlgroup, +.trangroup, +.uploadtrangroup, +.confirmgroup, +.processinggroup { + display: none; } .first-form .yturlgroup { - display: block; + display: block; } .second-form .trangroup { - display: block; + display: block; } -.third-form .confirmgroup { - display: block; +.third-form .uploadtrangroup { + display: block; } .processing-form .processinggroup { - display: block; + display: block; } .processing-form #upload-video-stuff { - display: none; + display: none; } -.editing #video-form, .viewing #video-form { - display: none; +.editing #video-form, +.viewing #video-form { + display: none; } .yt-header-thumb { - width: 75px; - display: inline; + width: 75px; + display: inline; } .loading-gif { - margin-left: 10px; - display: none; + margin-left: 10px; + display: none !important; } .loading .loading-gif { - display: inline-block; + display: inline-block !important; } #upload-video-stuff { - border: 1px solid #333; - cursor: pointer; - background-color: rgb(252, 248, 252); + border: 1px solid #333; + cursor: pointer; + background-color: rgb(252, 248, 252); } #upload-video-stuff:hover { - background-color: rgb(248, 236, 248); + background-color: rgb(248, 236, 248); } /********************/ /* editor-level css */ /********************/ #editing-interface { - max-width: 1800px; - margin: auto; - min-width: 1200px; + max-width: 1800px; + margin: auto; + min-width: 1200px; } .editing #editing-interface { - max-width: 3000px; - height: inherit; + max-width: 3000px; + height: inherit; } .editor-wrap { - height: inherit; + height: inherit; } /********************/ /* digest-level css */ /********************/ #maintitle { - text-align: left; - color: #645C6F; - font-weight: normal; - line-height: 1em; - min-width: 200px; - position: relative; - padding: 0; - margin: auto; - margin-top: 22px; - margin-bottom: 0; - display: inline; + text-align: left; + color: #645c6f; + font-weight: normal; + line-height: 1em; + min-width: 200px; + position: relative; + padding: 0; + margin: auto; + margin-top: 22px; + margin-bottom: 0; + display: inline; } #videolength { - display: inline; - font-size: 15px; - position: relative; - bottom: 0.3em; - color: #BDBDBD; - margin: 0; - margin-left: 0.4em; + display: inline; + font-size: 15px; + position: relative; + bottom: 0.3em; + color: #bdbdbd; + margin: 0; + margin-left: 0.4em; } #authortitle { - padding-top: 8px; - margin-bottom: 35px; - font-size: 1.5em; - color: #999999; - font-style: italic; - margin-top: -5px; - width: 96%; + padding-top: 8px; + margin-bottom: 35px; + font-size: 1.5em; + color: #999999; + font-style: italic; + margin-top: -5px; + width: 96%; } .digest-title-wrap:focus { - outline: 0; + outline: 0; } -.editor-wrap .digest-title-wrap h1{ - margin: 0; - padding: 0; - display: block; - margin: auto; - margin: 36px auto; +.editor-wrap .digest-title-wrap h1 { + margin: 0; + padding: 0; + display: block; + margin: auto; + margin: 36px auto; } #digest-wrap { - overflow-y: auto; - overflow-x: hidden; - float: left; - width: 60%; - display: inline-block; - height: inherit; - padding-left: 10px; - border-right: 1px solid #E0E0E0; - background: white; - padding-left: 2%; + overflow-y: auto; + overflow-x: hidden; + float: left; + width: 60%; + display: inline-block; + height: inherit; + padding-left: 10px; + border-right: 1px solid #e0e0e0; + background: white; + padding-left: 2%; } .editing #digest-wrap { - padding-top: 2em; + padding-top: 2em; } .viewing #digest-wrap { - width: 89%; - max-width: 1600px; - margin: auto; - float: none; - display: block; - border: none; + width: 89%; + max-width: 1600px; + margin: auto; + float: none; + display: block; + border: none; } .digest-chapters-wrap { - margin-top: 12px; - max-width: 1300px; - display: block; + margin-top: 12px; + max-width: 1300px; + display: block; } - /*************************/ /* chapter-level css */ /************************/ .chapter { - position: relative; - margin-bottom: 40px; + position: relative; + margin-bottom: 40px; } .chapter-header { - font-size: 25px; - position: relative; - padding: 0; - width: 96%; + font-size: 25px; + padding: 0; + width: 96%; } .chapter-header:after { - content: attr(data-content); - position: relative; - bottom: 3px; - left: 7px; - white-space: pre; - font-size: 0.6em; - color: #BDBDBD; + content: attr(data-content); + position: relative; + bottom: 3px; + left: 7px; + white-space: pre; + font-size: 0.6em; + color: #bdbdbd; } .cover { - top: 0; - height: 100%; - width: 100%; - position: absolute; - background: black; - cursor: pointer; + top: 0; + height: 100%; + width: 100%; + position: absolute; + background: black; + cursor: pointer; } .cover img { - height: 100%; - display: block; - margin: auto; + height: 100%; + display: block; + margin: auto; } .cover:hover:before { - content: ""; - position: absolute; - top: 0; - background: rgba(1,1,1, 0.4); - width: inherit; - background-image: url('http://192.241.199.43/img/play-button.png'); - background-repeat: no-repeat; - height: inherit; - z-index: 100; - background-size: 60px; - opacity: 0.9; - background-position: 50%; + content: ''; + position: absolute; + top: 0; + background: rgba(1, 1, 1, 0.4); + width: inherit; + background-image: url('/img/play-button.png'); + background-repeat: no-repeat; + height: inherit; + z-index: 100; + background-size: 60px; + opacity: 0.9; + background-position: 50%; } .aspect-wrap { position: relative; - padding-bottom: 25.3125%; /* 16:9 */ - width: 45%; - height: 0; - float: left; + padding-bottom: 25.3125%; /* 16:9 */ + width: 45%; + height: 0; + float: left; } .aspect-wrap .video-wrap { position: absolute; top: 0; left: 0; - width: 100%; - height: 100%; + width: 100%; + height: 100%; } .active .video-wrap { - box-shadow: 0px 0px 24px rgb(97, 75, 91); + box-shadow: 0px 0px 24px rgb(97, 75, 91); } .summary-column { - position: relative; - top: -1px; - display: inline-block; - margin-left: 8px; - width: 50%; + position: relative; + top: -1px; + display: inline-block; + margin-left: 8px; + width: 50%; } .viewing .summary-column { - margin-left: 22px; + margin-left: 22px; } .viewing .wysiwyg-add-chapter { - display: none; + display: none; } .wysiwyg-add-chapter { - position: absolute; - left: 3px; - bottom: -20px; - cursor: pointer; - opacity: 0.8; + position: absolute; + left: 3px; + bottom: -20px; + cursor: pointer; + opacity: 0.8; } .wysiwyg-add-chapter:hover { - opacity: 1; + opacity: 1; } // SECTION -.editing .section-row, .viewing .section-row { - position: relative; - position: relative; - border: 1px dashed #FFFFFF; - border-width: 1px; - border-left: 0; +.editing .section-row, +.viewing .section-row { + position: relative; + position: relative; + border: 1px dashed #ffffff; + border-width: 1px; + border-left: 0; } .section-row.focused { - border: 1px solid rgba(56, 169, 240, 0.75); - box-shadow: 0px 0px 10px rgba(56, 169, 240, 0.75) !important; + border: 1px solid rgba(56, 169, 240, 0.75); + box-shadow: 0px 0px 10px rgba(56, 169, 240, 0.75) !important; } div.section-row:last-child { - margin-bottom: 0; + margin-bottom: 0; } /* .editing .section-row:hover .split-down, .editing .section-row:hover .merge-up { */ @@ -342,8 +347,8 @@ div.section-row:last-child { /* } */ .editing .section-row:hover .split-down { - background-image: url('http://192.241.199.43/img//split-icon.png'); - top: -12px; + background-image: url('/img/split-icon.png'); + top: -12px; } /* .editing .section-row:hover .merge-up { */ @@ -356,461 +361,640 @@ div.section-row:last-child { /* } */ .viewing .section-row { - cursor: pointer; + cursor: pointer; } .viewing .section-row:after { - cursor: pointer; - content: ' '; - display: block; - height: 3px; + cursor: pointer; + content: ' '; + display: block; + height: 3px; } .viewing .section-row:hover:after { - border-top: 1px solid #dddddd; + border-top: 1px solid #dddddd; } .viewing .section-row:hover .keyframe-col:before { - content: ""; - position: absolute; - top: 0; - background: rgba(1,1,1, 0.4); - background-image: url('http://192.241.199.43/img/play-button.png'); - background-repeat: no-repeat; - height: 100%; - width: 100%; - z-index: 100; - background-size: 30px; - opacity: 0.9; - background-position: 50%; -} - -.editing .section-row.empty, .editing .section-row:hover { - border: 1px dashed #DFDDDD; - border-width: 1px; - border-left: 0; - margin-bottom: 8px; - position: relative; + content: ''; + position: absolute; + top: 0; + background: rgba(1, 1, 1, 0.4); + background-image: url('/img/play-button.png'); + background-repeat: no-repeat; + height: 100%; + width: 100%; + z-index: 100; + background-size: 30px; + opacity: 0.9; + background-position: 50%; +} + +.editing .section-row.empty, +.editing .section-row:hover { + border: 1px dashed #dfdddd; + border-width: 1px; + border-left: 0; + margin-bottom: 8px; + position: relative; } .editing .section-row { - margin-bottom: 8px; - border: 1px solid transparent; - border-left: none; + margin-bottom: 8px; + border: 1px solid transparent; + border-left: none; } -.section-row.active, .viewing .section-row { - border-top: solid 1px transparent; +.section-row.active, +.viewing .section-row { + border-top: solid 1px transparent; } - .section-row.active { - background: rgba(237, 237, 237, 1); - border-top: solid 1px #ddd; - } +.section-row.active { + background: rgba(237, 237, 237, 1); + border-top: solid 1px #ddd; +} .viewing .section-row:hover { - border-top: solid 1px #ddd; + border-top: solid 1px #ddd; } .keyframe-col { - width: 18%; - float: left; - height: inherit; - position: relative; + width: 18%; + float: left; + height: inherit; + position: relative; } .keyframe-col:empty { - border: 1px dashed #A3A1A1; - background-image: url('/camera-icon-2.png'); - background-size: 59px 43px; - background-repeat: no-repeat; - background-position: 5px 3px; + border: 1px dashed #a3a1a1; + background-image: url('/camera-icon-2.png'); + background-size: 59px 43px; + background-repeat: no-repeat; + background-position: 5px 3px; } - /*************************/ /* section level css */ /************************/ .section-text-wrap { - display: inline-block; - vertical-align: text-bottom; - width: 82%; - /* height: inherit; */ - /* height: 40px; */ - padding-left: 8px; - padding-right: 4px; - line-height: 1.25em; + display: inline-block; + vertical-align: text-bottom; + width: 82%; + /* height: inherit; */ + /* height: 40px; */ + padding-left: 8px; + padding-right: 4px; + line-height: 1.25em; } .section-text-wrap .abs-summary { - border: none; - outline: none; - font-size: 13px; - min-height: 35px; - height: 100%; - border-color: rgba(163,161,161,0); + border: none; + outline: none; + font-size: 13px; + min-height: 35px; + height: 100%; + border-color: rgba(163, 161, 161, 0); } .editing .section-text-wrap .abs-summary { - font-size: 11px; + font-size: 11px; } .section-text-wrap .abs-summary:empty { - padding: 3px 4px; + padding: 3px 4px; } .section-thumbnail { - position: relative; - border: 1px solid #555555; - width: 100%; + position: relative; + border: 1px solid #555555; + width: 100%; + min-height: 38px; } .take-thumbnail-image { - cursor: pointer; - color: #444444; - background-color: white; - font-size: 12px; - border: 1px solid #444444; - border-radius: 5px; - padding: 3px; - margin: 0; - position: absolute; - left: 50%; - margin-left: -9px; - bottom: 0; - display: none; + cursor: pointer; + color: #444444; + background-color: white; + font-size: 12px; + border: 1px solid #444444; + border-radius: 5px; + padding: 3px; + margin: 0; + position: absolute; + left: 50%; + margin-left: -9px; + bottom: 0; + display: none; } .take-thumbnail-image:hover { - color: indigo; + color: indigo; } -.take-thumbnail-image:hover, .section-row:hover .take-thumbnail-image { - display: block; +.take-thumbnail-image:hover, +.section-row:hover .take-thumbnail-image { + display: block; } body.viewing .section-row .take-thumbnail-image { - display: none; + display: none; } .remove-section { - display: none; - position: absolute; - top: -12px; - right: -4px; - font-size: 18px; - color: #555555; - cursor: pointer; + display: none; + position: absolute; + top: -12px; + right: -4px; + font-size: 18px; + color: #555555; + cursor: pointer; } .remove-section:hover { - color: rgb(224, 9, 9); + color: rgb(224, 9, 9); } .section-row:hover .remove-section { - display: block; + display: block; } body.viewing .section-row .remove-section { - display: none; + display: none; } - /*************************/ /* transcript-level css */ /************************/ .viewing #transcript-wrap { - display: none; + display: none; } #transcript-wrap { - padding-top: 5px; - width: 39.96%; - line-height: 16px; - height: inherit; - float: left; - position: relative; - background-color: white; - overflow: scroll; + padding-top: 5px; + width: 39.96%; + line-height: 16px; + height: inherit; + float: left; + position: relative; + background-color: white; + overflow: scroll; } /** transcript scrollbar style **/ .jspTrack { - background-color: rgb(232, 234, 246); + background-color: rgb(232, 234, 246); } .jspDrag { - background-color: rgb(184, 189, 216); + background-color: rgb(184, 189, 216); } -.viewing .start-chapter-scroll-marker, .viewing .start-section-scroll-marker { - display: none; +.viewing .start-chapter-scroll-marker, +.viewing .start-section-scroll-marker { + display: none; } -.start-chapter-scroll-marker, .start-section-scroll-marker { - position: absolute; - right: 0; - width: 16px; - height: 3px; +.start-chapter-scroll-marker, +.start-section-scroll-marker { + position: absolute; + right: 0; + width: 16px; + height: 3px; } .start-chapter-scroll-marker { - background-color: red; + background-color: red; } .start-section-scroll-marker { - background-color: blue; + background-color: blue; } /****/ .transcript-words { - float: left; - padding-top: 4px; - background-color: white; - padding-right: 1em; - max-width: 650px; + float: left; + padding-top: 4px; + background-color: white; + padding-right: 1em; + max-width: 650px; } .transcript-words p { - font-size: 10pt; - margin-bottom: 0; - padding: 0 10px; - cursor: default; + font-size: 10pt; + margin-bottom: 0; + padding: 0 10px; + cursor: default; } .bpdrag * { - -webkit-user-select: none; /* Chrome all / Safari all */ - -moz-user-select: none; /* Firefox all */ - -ms-user-select: none; /* IE 10+ */ - user-select: none; + -webkit-user-select: none; /* Chrome all / Safari all */ + -moz-user-select: none; /* Firefox all */ + -ms-user-select: none; /* IE 10+ */ + user-select: none; } .transcript-words p + p { - padding-top: 20px; + padding-top: 10px; } /* so clicking near the word activates the word */ .word { - padding: 0 2px; - line-height: 1.2em; - margin: 0; - margin-left: -5px; - padding-left: 5px; + padding: 0 2px; + line-height: 1.2em; + margin: 0; + margin-left: -5px; + padding-left: 5px; } .word:hover { - color: #BBBBBB; + color: #bbbbbb; } .word.active { - background: rgb(255, 255, 111); + background: rgb(255, 255, 111); } .secword { - background-color: rgb(232, 246, 255); + background-color: rgb(232, 246, 255); } .start-section-marker { - width: 10px; - height: 10px; - background-color: blue; - display: inline-block; - margin: 0 5px + width: 10px; + height: 10px; + background-color: blue; + display: inline-block; + margin: 0 5px; } .start-chapter-marker { - width: 5px; - height: 14px; - background-color: red; - display: inline-block; - margin-right: 18px; + width: 5px; + height: 14px; + background-color: red; + display: inline-block; + margin-right: 18px; } .start-chapter-marker:after { - content: ""; - margin-left: 6px; - height: 10px; - width: 10px; - background-color: blue; - display: inline-block; + content: ''; + margin-left: 6px; + height: 10px; + width: 10px; + background-color: blue; + display: inline-block; } .drag-chapter-word { - color: red; + color: red; } .drag-section-word { - color: blue; + color: blue; } /** Instructions **/ .instructions-text { - display: none; - font-size: 1.1em; - padding: 1em; - background: rgb(254, 255, 240); - border: 1px solid #dddddd; - position: fixed; - bottom: 0; - right: 0; - line-height: 1.1em; - z-index: 1000; + display: none; + font-size: 1.1em; + padding: 1em; + background: rgb(254, 255, 240); + border: 1px solid #dddddd; + position: fixed; + bottom: 0; + right: 0; + line-height: 1.1em; + z-index: 1000; } .editing .instr-shown + .instructions-text { - display: block; + display: block; } .instructions-text ul { - list-style: none; + list-style: none; } -.instructions-text li+li { - margin-top: 1em; +.instructions-text li + li { + margin-top: 1em; } .instructions-minimize { - background-color: #D8D8D8; - width: 20px; - height: 20px; - line-height: 20px; - text-align: center; - position: absolute; - top: 0; - right: 25px; - font-size: 20pt; - cursor: pointer; - z-index: 2000; + background-color: #d8d8d8; + width: 20px; + height: 20px; + line-height: 20px; + text-align: center; + position: absolute; + top: 0; + right: 25px; + font-size: 20pt; + cursor: pointer; + z-index: 2000; } .unminimize-instructions { - display: none; - position: fixed; - right: 0; - bottom: 0; - padding: 0.5em; - border: 1px #D8D8D8 solid; - background: rgb(254, 255, 240); - cursor: pointer; - z-index: 500; + display: none; + position: fixed; + right: 0; + bottom: 0; + padding: 0.5em; + border: 1px #d8d8d8 solid; + background: rgb(254, 255, 240); + cursor: pointer; + z-index: 500; } .editing .unminimize-instructions { - display: block; + display: block; } .editing .unminimize-instructions.instr-shown { - display: none; + display: none; } .instr-task { - display: block; - font-weight: bold; - margin-left: -2em; + display: block; + font-weight: bold; + margin-left: -2em; } /** Edit Toolbar **/ .toolbar { - bottom: 0; - left: 0; - background: white; - position: fixed; - z-index: 10000; - font-size: 20px; - border: 2px solid; - border-width: 1px 1px 0 0; - padding: 3px 6px; - border-radius: 0 5px; + bottom: 0; + left: 0; + background: white; + position: fixed; + z-index: 10000; + font-size: 20px; + border: 2px solid; + border-width: 1px 1px 0 0; + padding: 3px 6px; + border-radius: 0 5px; } .toolbar .fa + .fa { - margin-left: 10px; + margin-left: 10px; } .toolbar-icon { - position: relative; - width: 36px; - height: 36px; - text-align: center; - cursor: pointer; + position: relative; + width: 36px; + height: 36px; + text-align: center; + cursor: pointer; } .falabel { - position: absolute; - bottom: 0; - left: 50%; - width: 34px; - font-size: 9px; - margin-left: -17px; - cursor: pointer; + position: absolute; + bottom: 0; + left: 50%; + width: 34px; + font-size: 9px; + margin-left: -17px; + cursor: pointer; } .toolbar-icon:hover * { - color: teal; + color: teal; } #to-edit-vdigest { - width: 65px; - height: 65px; + width: 65px; + height: 65px; } #to-edit-vdigest .falabel { - width: 75px; - font-size: 12px; - margin-left: -37.5px; + width: 75px; + font-size: 12px; + margin-left: -37.5px; } .viewing .toolbar-icon { - display: none; + display: none; } .viewing #to-edit-vdigest { - display: block; + display: block; } .editing #to-edit-vdigest { - display: none; + display: none; } /** ASSORTED OTHER CSS */ -input[type=file] { - display:none; - height:0; - width:0; - position: absolute; - top: 0; +input[type='file'] { + display: none; + height: 0; + width: 0; + position: absolute; + top: 0; } .floatclear { - clear: both; + clear: both; } .gutterLine { - display: none; + display: none; } .contextMenuPlugin li + li { - border-top: 1px solid #cccccc; + border-top: 1px solid #cccccc; } .editing .contextMenuPlugin > li > span { - padding: 3px 2px; + padding: 3px 2px; } .full-cover-loading { - position: absolute; - top: 25px; - bottom: 0; - left: 0; - right: 0; - background-color: rgba(102, 102, 102, 0.61); - color: white; - font-size: 30pt; - padding-top: 4rem; - text-align: center; + position: absolute; + top: 25px; + bottom: 0; + left: 0; + right: 0; + background-color: rgba(102, 102, 102, 0.61); + color: white; + font-size: 30pt; + padding-top: 4rem; + text-align: center; } - /* LOADING IMG */ #loading-image { - display: none; - position: absolute; - z-index: 10000; - left: 50%; - margin-left: -150px; - top: 80px; - font-size: 20pt; + display: none; + position: absolute; + z-index: 10000; + left: 50%; + margin-left: -150px; + top: 80px; + font-size: 20pt; +} + +/* Modal */ +/**************************\ + Basic Modal Styles +\**************************/ + +.modal { + /* font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, */ + /* helvetica neue, helvetica, ubuntu, roboto, noto, segoe ui, arial, sans-serif; */ +} + +.modal__overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.6); + display: flex; + justify-content: center; + align-items: center; +} + +.modal__container { + background-color: #fff; + padding: 30px; + max-width: 500px; + max-height: 100vh; + border-radius: 4px; + overflow-y: auto; + box-sizing: border-box; +} + +.modal__header { + display: flex; + justify-content: space-between; + align-items: center; +} + +.modal__title { + margin-top: 0; + margin-bottom: 0; + font-weight: 600; + font-size: 1.25rem; + line-height: 1.25; + color: #00449e; + box-sizing: border-box; +} + +.modal__close { + background: transparent; + border: 0; +} + +.modal__header .modal__close:before { + content: '\2715'; +} + +.modal__content { + margin-top: 2rem; + margin-bottom: 2rem; + line-height: 1.5; + color: rgba(0, 0, 0, 0.8); +} + +.modal__footer { + display: grid; + grid-template-columns: auto auto auto; + grid-gap: 30px; +} + +.modal__btn { + font-size: 0.875rem; + padding-left: 1rem; + padding-right: 1rem; + padding-top: 0.5rem; + padding-bottom: 0.5rem; + background-color: #e6e6e6; + color: rgba(0, 0, 0, 0.8); + border-radius: 0.25rem; + border-style: none; + border-width: 0; + cursor: pointer; + -webkit-appearance: button; + text-transform: none; + overflow: visible; + line-height: 1.15; + margin: 0; + will-change: transform; + -moz-osx-font-smoothing: grayscale; + -webkit-backface-visibility: hidden; + backface-visibility: hidden; + -webkit-transform: translateZ(0); + transform: translateZ(0); + transition: -webkit-transform 0.25s ease-out; + transition: transform 0.25s ease-out; + transition: transform 0.25s ease-out, -webkit-transform 0.25s ease-out; +} + +.modal__btn:focus, +.modal__btn:hover { + -webkit-transform: scale(1.05); + transform: scale(1.05); +} + +.modal__btn-primary { + background-color: #00449e; + color: #fff; +} + +/**************************\ + Demo Animation Style + \**************************/ +@keyframes mmfadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} + +@keyframes mmfadeOut { + from { + opacity: 1; + } + to { + opacity: 0; + } } +@keyframes mmslideIn { + from { + transform: translateY(15%); + } + to { + transform: translateY(0); + } +} + +@keyframes mmslideOut { + from { + transform: translateY(0); + } + to { + transform: translateY(-10%); + } +} + +.micromodal-slide { + display: none; +} + +.micromodal-slide.is-open { + display: block; +} + +.micromodal-slide[aria-hidden='false'] .modal__overlay { + animation: mmfadeIn 0.3s cubic-bezier(0, 0, 0.2, 1); +} + +.micromodal-slide[aria-hidden='false'] .modal__container { + animation: mmslideIn 0.3s cubic-bezier(0, 0, 0.2, 1); +} + +.micromodal-slide[aria-hidden='true'] .modal__overlay { + animation: mmfadeOut 0.3s cubic-bezier(0, 0, 0.2, 1); +} + +.micromodal-slide[aria-hidden='true'] .modal__container { + animation: mmslideOut 0.3s cubic-bezier(0, 0, 0.2, 1); +} + +.micromodal-slide .modal__container, +.micromodal-slide .modal__overlay { + will-change: transform; +} diff --git a/public/css/home.less b/public/css/home.less index 851036b..7dcf451 100644 --- a/public/css/home.less +++ b/public/css/home.less @@ -1,7 +1,7 @@ body { position: relative; padding-bottom: 25px; - min-width: 1100px; + // min-width: 1100px; } #main-title { @@ -148,19 +148,9 @@ p.vdescription { margin-top: 0.5rem; } -@paper-icon-width: 80px; -.paper-icon { - width: @paper-icon-width; - float: left; -} - -.paper-icon img { - width: @paper-icon-width; -} - .paper-details { - width: @read-paper-width - @paper-icon-width; - margin-left: @paper-icon-width; + width: @read-paper-width; + margin-left: 80px; } #bg-color-change { diff --git a/public/css/lib/font-awesome.min.css b/public/css/lib/font-awesome.min.css deleted file mode 100644 index 81d6ab0..0000000 --- a/public/css/lib/font-awesome.min.css +++ /dev/null @@ -1,4 +0,0 @@ -/*! - * Font Awesome 4.0.3 by @davegandy - http://fontawesome.io - @fontawesome - * License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License) - */@font-face{font-family:'FontAwesome';src:url('http://192.241.199.43/fonts/fontawesome-webfont.eot?v=4.0.3');src:url('http://192.241.199.43/fonts/fontawesome-webfont.eot?#iefix&v=4.0.3') format('embedded-opentype'),url('http://192.241.199.43/fonts/fontawesome-webfont.woff?v=4.0.3') format('woff'),url('http://192.241.199.43/fonts/fontawesome-webfont.ttf?v=4.0.3') format('truetype'),url('http://192.241.199.43/fonts/fontawesome-webfont.svg?v=4.0.3#fontawesomeregular') format('svg');font-weight:normal;font-style:normal}.fa{display:inline-block;font-family:FontAwesome;font-style:normal;font-weight:normal;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.fa-lg{font-size:1.3333333333333333em;line-height:.75em;vertical-align:-15%}.fa-2x{font-size:2em}.fa-3x{font-size:3em}.fa-4x{font-size:4em}.fa-5x{font-size:5em}.fa-fw{width:1.2857142857142858em;text-align:center}.fa-ul{padding-left:0;margin-left:2.142857142857143em;list-style-type:none}.fa-ul>li{position:relative}.fa-li{position:absolute;left:-2.142857142857143em;width:2.142857142857143em;top:.14285714285714285em;text-align:center}.fa-li.fa-lg{left:-1.8571428571428572em}.fa-border{padding:.2em .25em .15em;border:solid .08em #eee;border-radius:.1em}.pull-right{float:right}.pull-left{float:left}.fa.pull-left{margin-right:.3em}.fa.pull-right{margin-left:.3em}.fa-spin{-webkit-animation:spin 2s infinite linear;-moz-animation:spin 2s infinite linear;-o-animation:spin 2s infinite linear;animation:spin 2s infinite linear}@-moz-keyframes spin{0%{-moz-transform:rotate(0deg)}100%{-moz-transform:rotate(359deg)}}@-webkit-keyframes spin{0%{-webkit-transform:rotate(0deg)}100%{-webkit-transform:rotate(359deg)}}@-o-keyframes spin{0%{-o-transform:rotate(0deg)}100%{-o-transform:rotate(359deg)}}@-ms-keyframes spin{0%{-ms-transform:rotate(0deg)}100%{-ms-transform:rotate(359deg)}}@keyframes spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}.fa-rotate-90{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-ms-transform:rotate(90deg);-o-transform:rotate(90deg);transform:rotate(90deg)}.fa-rotate-180{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2);-webkit-transform:rotate(180deg);-moz-transform:rotate(180deg);-ms-transform:rotate(180deg);-o-transform:rotate(180deg);transform:rotate(180deg)}.fa-rotate-270{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=3);-webkit-transform:rotate(270deg);-moz-transform:rotate(270deg);-ms-transform:rotate(270deg);-o-transform:rotate(270deg);transform:rotate(270deg)}.fa-flip-horizontal{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=0,mirror=1);-webkit-transform:scale(-1,1);-moz-transform:scale(-1,1);-ms-transform:scale(-1,1);-o-transform:scale(-1,1);transform:scale(-1,1)}.fa-flip-vertical{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=2,mirror=1);-webkit-transform:scale(1,-1);-moz-transform:scale(1,-1);-ms-transform:scale(1,-1);-o-transform:scale(1,-1);transform:scale(1,-1)}.fa-stack{position:relative;display:inline-block;width:2em;height:2em;line-height:2em;vertical-align:middle}.fa-stack-1x,.fa-stack-2x{position:absolute;left:0;width:100%;text-align:center}.fa-stack-1x{line-height:inherit}.fa-stack-2x{font-size:2em}.fa-inverse{color:#fff}.fa-glass:before{content:"\f000"}.fa-music:before{content:"\f001"}.fa-search:before{content:"\f002"}.fa-envelope-o:before{content:"\f003"}.fa-heart:before{content:"\f004"}.fa-star:before{content:"\f005"}.fa-star-o:before{content:"\f006"}.fa-user:before{content:"\f007"}.fa-film:before{content:"\f008"}.fa-th-large:before{content:"\f009"}.fa-th:before{content:"\f00a"}.fa-th-list:before{content:"\f00b"}.fa-check:before{content:"\f00c"}.fa-times:before{content:"\f00d"}.fa-search-plus:before{content:"\f00e"}.fa-search-minus:before{content:"\f010"}.fa-power-off:before{content:"\f011"}.fa-signal:before{content:"\f012"}.fa-gear:before,.fa-cog:before{content:"\f013"}.fa-trash-o:before{content:"\f014"}.fa-home:before{content:"\f015"}.fa-file-o:before{content:"\f016"}.fa-clock-o:before{content:"\f017"}.fa-road:before{content:"\f018"}.fa-download:before{content:"\f019"}.fa-arrow-circle-o-down:before{content:"\f01a"}.fa-arrow-circle-o-up:before{content:"\f01b"}.fa-inbox:before{content:"\f01c"}.fa-play-circle-o:before{content:"\f01d"}.fa-rotate-right:before,.fa-repeat:before{content:"\f01e"}.fa-refresh:before{content:"\f021"}.fa-list-alt:before{content:"\f022"}.fa-lock:before{content:"\f023"}.fa-flag:before{content:"\f024"}.fa-headphones:before{content:"\f025"}.fa-volume-off:before{content:"\f026"}.fa-volume-down:before{content:"\f027"}.fa-volume-up:before{content:"\f028"}.fa-qrcode:before{content:"\f029"}.fa-barcode:before{content:"\f02a"}.fa-tag:before{content:"\f02b"}.fa-tags:before{content:"\f02c"}.fa-book:before{content:"\f02d"}.fa-bookmark:before{content:"\f02e"}.fa-print:before{content:"\f02f"}.fa-camera:before{content:"\f030"}.fa-font:before{content:"\f031"}.fa-bold:before{content:"\f032"}.fa-italic:before{content:"\f033"}.fa-text-height:before{content:"\f034"}.fa-text-width:before{content:"\f035"}.fa-align-left:before{content:"\f036"}.fa-align-center:before{content:"\f037"}.fa-align-right:before{content:"\f038"}.fa-align-justify:before{content:"\f039"}.fa-list:before{content:"\f03a"}.fa-dedent:before,.fa-outdent:before{content:"\f03b"}.fa-indent:before{content:"\f03c"}.fa-video-camera:before{content:"\f03d"}.fa-picture-o:before{content:"\f03e"}.fa-pencil:before{content:"\f040"}.fa-map-marker:before{content:"\f041"}.fa-adjust:before{content:"\f042"}.fa-tint:before{content:"\f043"}.fa-edit:before,.fa-pencil-square-o:before{content:"\f044"}.fa-share-square-o:before{content:"\f045"}.fa-check-square-o:before{content:"\f046"}.fa-arrows:before{content:"\f047"}.fa-step-backward:before{content:"\f048"}.fa-fast-backward:before{content:"\f049"}.fa-backward:before{content:"\f04a"}.fa-play:before{content:"\f04b"}.fa-pause:before{content:"\f04c"}.fa-stop:before{content:"\f04d"}.fa-forward:before{content:"\f04e"}.fa-fast-forward:before{content:"\f050"}.fa-step-forward:before{content:"\f051"}.fa-eject:before{content:"\f052"}.fa-chevron-left:before{content:"\f053"}.fa-chevron-right:before{content:"\f054"}.fa-plus-circle:before{content:"\f055"}.fa-minus-circle:before{content:"\f056"}.fa-times-circle:before{content:"\f057"}.fa-check-circle:before{content:"\f058"}.fa-question-circle:before{content:"\f059"}.fa-info-circle:before{content:"\f05a"}.fa-crosshairs:before{content:"\f05b"}.fa-times-circle-o:before{content:"\f05c"}.fa-check-circle-o:before{content:"\f05d"}.fa-ban:before{content:"\f05e"}.fa-arrow-left:before{content:"\f060"}.fa-arrow-right:before{content:"\f061"}.fa-arrow-up:before{content:"\f062"}.fa-arrow-down:before{content:"\f063"}.fa-mail-forward:before,.fa-share:before{content:"\f064"}.fa-expand:before{content:"\f065"}.fa-compress:before{content:"\f066"}.fa-plus:before{content:"\f067"}.fa-minus:before{content:"\f068"}.fa-asterisk:before{content:"\f069"}.fa-exclamation-circle:before{content:"\f06a"}.fa-gift:before{content:"\f06b"}.fa-leaf:before{content:"\f06c"}.fa-fire:before{content:"\f06d"}.fa-eye:before{content:"\f06e"}.fa-eye-slash:before{content:"\f070"}.fa-warning:before,.fa-exclamation-triangle:before{content:"\f071"}.fa-plane:before{content:"\f072"}.fa-calendar:before{content:"\f073"}.fa-random:before{content:"\f074"}.fa-comment:before{content:"\f075"}.fa-magnet:before{content:"\f076"}.fa-chevron-up:before{content:"\f077"}.fa-chevron-down:before{content:"\f078"}.fa-retweet:before{content:"\f079"}.fa-shopping-cart:before{content:"\f07a"}.fa-folder:before{content:"\f07b"}.fa-folder-open:before{content:"\f07c"}.fa-arrows-v:before{content:"\f07d"}.fa-arrows-h:before{content:"\f07e"}.fa-bar-chart-o:before{content:"\f080"}.fa-twitter-square:before{content:"\f081"}.fa-facebook-square:before{content:"\f082"}.fa-camera-retro:before{content:"\f083"}.fa-key:before{content:"\f084"}.fa-gears:before,.fa-cogs:before{content:"\f085"}.fa-comments:before{content:"\f086"}.fa-thumbs-o-up:before{content:"\f087"}.fa-thumbs-o-down:before{content:"\f088"}.fa-star-half:before{content:"\f089"}.fa-heart-o:before{content:"\f08a"}.fa-sign-out:before{content:"\f08b"}.fa-linkedin-square:before{content:"\f08c"}.fa-thumb-tack:before{content:"\f08d"}.fa-external-link:before{content:"\f08e"}.fa-sign-in:before{content:"\f090"}.fa-trophy:before{content:"\f091"}.fa-github-square:before{content:"\f092"}.fa-upload:before{content:"\f093"}.fa-lemon-o:before{content:"\f094"}.fa-phone:before{content:"\f095"}.fa-square-o:before{content:"\f096"}.fa-bookmark-o:before{content:"\f097"}.fa-phone-square:before{content:"\f098"}.fa-twitter:before{content:"\f099"}.fa-facebook:before{content:"\f09a"}.fa-github:before{content:"\f09b"}.fa-unlock:before{content:"\f09c"}.fa-credit-card:before{content:"\f09d"}.fa-rss:before{content:"\f09e"}.fa-hdd-o:before{content:"\f0a0"}.fa-bullhorn:before{content:"\f0a1"}.fa-bell:before{content:"\f0f3"}.fa-certificate:before{content:"\f0a3"}.fa-hand-o-right:before{content:"\f0a4"}.fa-hand-o-left:before{content:"\f0a5"}.fa-hand-o-up:before{content:"\f0a6"}.fa-hand-o-down:before{content:"\f0a7"}.fa-arrow-circle-left:before{content:"\f0a8"}.fa-arrow-circle-right:before{content:"\f0a9"}.fa-arrow-circle-up:before{content:"\f0aa"}.fa-arrow-circle-down:before{content:"\f0ab"}.fa-globe:before{content:"\f0ac"}.fa-wrench:before{content:"\f0ad"}.fa-tasks:before{content:"\f0ae"}.fa-filter:before{content:"\f0b0"}.fa-briefcase:before{content:"\f0b1"}.fa-arrows-alt:before{content:"\f0b2"}.fa-group:before,.fa-users:before{content:"\f0c0"}.fa-chain:before,.fa-link:before{content:"\f0c1"}.fa-cloud:before{content:"\f0c2"}.fa-flask:before{content:"\f0c3"}.fa-cut:before,.fa-scissors:before{content:"\f0c4"}.fa-copy:before,.fa-files-o:before{content:"\f0c5"}.fa-paperclip:before{content:"\f0c6"}.fa-save:before,.fa-floppy-o:before{content:"\f0c7"}.fa-square:before{content:"\f0c8"}.fa-bars:before{content:"\f0c9"}.fa-list-ul:before{content:"\f0ca"}.fa-list-ol:before{content:"\f0cb"}.fa-strikethrough:before{content:"\f0cc"}.fa-underline:before{content:"\f0cd"}.fa-table:before{content:"\f0ce"}.fa-magic:before{content:"\f0d0"}.fa-truck:before{content:"\f0d1"}.fa-pinterest:before{content:"\f0d2"}.fa-pinterest-square:before{content:"\f0d3"}.fa-google-plus-square:before{content:"\f0d4"}.fa-google-plus:before{content:"\f0d5"}.fa-money:before{content:"\f0d6"}.fa-caret-down:before{content:"\f0d7"}.fa-caret-up:before{content:"\f0d8"}.fa-caret-left:before{content:"\f0d9"}.fa-caret-right:before{content:"\f0da"}.fa-columns:before{content:"\f0db"}.fa-unsorted:before,.fa-sort:before{content:"\f0dc"}.fa-sort-down:before,.fa-sort-asc:before{content:"\f0dd"}.fa-sort-up:before,.fa-sort-desc:before{content:"\f0de"}.fa-envelope:before{content:"\f0e0"}.fa-linkedin:before{content:"\f0e1"}.fa-rotate-left:before,.fa-undo:before{content:"\f0e2"}.fa-legal:before,.fa-gavel:before{content:"\f0e3"}.fa-dashboard:before,.fa-tachometer:before{content:"\f0e4"}.fa-comment-o:before{content:"\f0e5"}.fa-comments-o:before{content:"\f0e6"}.fa-flash:before,.fa-bolt:before{content:"\f0e7"}.fa-sitemap:before{content:"\f0e8"}.fa-umbrella:before{content:"\f0e9"}.fa-paste:before,.fa-clipboard:before{content:"\f0ea"}.fa-lightbulb-o:before{content:"\f0eb"}.fa-exchange:before{content:"\f0ec"}.fa-cloud-download:before{content:"\f0ed"}.fa-cloud-upload:before{content:"\f0ee"}.fa-user-md:before{content:"\f0f0"}.fa-stethoscope:before{content:"\f0f1"}.fa-suitcase:before{content:"\f0f2"}.fa-bell-o:before{content:"\f0a2"}.fa-coffee:before{content:"\f0f4"}.fa-cutlery:before{content:"\f0f5"}.fa-file-text-o:before{content:"\f0f6"}.fa-building-o:before{content:"\f0f7"}.fa-hospital-o:before{content:"\f0f8"}.fa-ambulance:before{content:"\f0f9"}.fa-medkit:before{content:"\f0fa"}.fa-fighter-jet:before{content:"\f0fb"}.fa-beer:before{content:"\f0fc"}.fa-h-square:before{content:"\f0fd"}.fa-plus-square:before{content:"\f0fe"}.fa-angle-double-left:before{content:"\f100"}.fa-angle-double-right:before{content:"\f101"}.fa-angle-double-up:before{content:"\f102"}.fa-angle-double-down:before{content:"\f103"}.fa-angle-left:before{content:"\f104"}.fa-angle-right:before{content:"\f105"}.fa-angle-up:before{content:"\f106"}.fa-angle-down:before{content:"\f107"}.fa-desktop:before{content:"\f108"}.fa-laptop:before{content:"\f109"}.fa-tablet:before{content:"\f10a"}.fa-mobile-phone:before,.fa-mobile:before{content:"\f10b"}.fa-circle-o:before{content:"\f10c"}.fa-quote-left:before{content:"\f10d"}.fa-quote-right:before{content:"\f10e"}.fa-spinner:before{content:"\f110"}.fa-circle:before{content:"\f111"}.fa-mail-reply:before,.fa-reply:before{content:"\f112"}.fa-github-alt:before{content:"\f113"}.fa-folder-o:before{content:"\f114"}.fa-folder-open-o:before{content:"\f115"}.fa-smile-o:before{content:"\f118"}.fa-frown-o:before{content:"\f119"}.fa-meh-o:before{content:"\f11a"}.fa-gamepad:before{content:"\f11b"}.fa-keyboard-o:before{content:"\f11c"}.fa-flag-o:before{content:"\f11d"}.fa-flag-checkered:before{content:"\f11e"}.fa-terminal:before{content:"\f120"}.fa-code:before{content:"\f121"}.fa-reply-all:before{content:"\f122"}.fa-mail-reply-all:before{content:"\f122"}.fa-star-half-empty:before,.fa-star-half-full:before,.fa-star-half-o:before{content:"\f123"}.fa-location-arrow:before{content:"\f124"}.fa-crop:before{content:"\f125"}.fa-code-fork:before{content:"\f126"}.fa-unlink:before,.fa-chain-broken:before{content:"\f127"}.fa-question:before{content:"\f128"}.fa-info:before{content:"\f129"}.fa-exclamation:before{content:"\f12a"}.fa-superscript:before{content:"\f12b"}.fa-subscript:before{content:"\f12c"}.fa-eraser:before{content:"\f12d"}.fa-puzzle-piece:before{content:"\f12e"}.fa-microphone:before{content:"\f130"}.fa-microphone-slash:before{content:"\f131"}.fa-shield:before{content:"\f132"}.fa-calendar-o:before{content:"\f133"}.fa-fire-extinguisher:before{content:"\f134"}.fa-rocket:before{content:"\f135"}.fa-maxcdn:before{content:"\f136"}.fa-chevron-circle-left:before{content:"\f137"}.fa-chevron-circle-right:before{content:"\f138"}.fa-chevron-circle-up:before{content:"\f139"}.fa-chevron-circle-down:before{content:"\f13a"}.fa-html5:before{content:"\f13b"}.fa-css3:before{content:"\f13c"}.fa-anchor:before{content:"\f13d"}.fa-unlock-alt:before{content:"\f13e"}.fa-bullseye:before{content:"\f140"}.fa-ellipsis-h:before{content:"\f141"}.fa-ellipsis-v:before{content:"\f142"}.fa-rss-square:before{content:"\f143"}.fa-play-circle:before{content:"\f144"}.fa-ticket:before{content:"\f145"}.fa-minus-square:before{content:"\f146"}.fa-minus-square-o:before{content:"\f147"}.fa-level-up:before{content:"\f148"}.fa-level-down:before{content:"\f149"}.fa-check-square:before{content:"\f14a"}.fa-pencil-square:before{content:"\f14b"}.fa-external-link-square:before{content:"\f14c"}.fa-share-square:before{content:"\f14d"}.fa-compass:before{content:"\f14e"}.fa-toggle-down:before,.fa-caret-square-o-down:before{content:"\f150"}.fa-toggle-up:before,.fa-caret-square-o-up:before{content:"\f151"}.fa-toggle-right:before,.fa-caret-square-o-right:before{content:"\f152"}.fa-euro:before,.fa-eur:before{content:"\f153"}.fa-gbp:before{content:"\f154"}.fa-dollar:before,.fa-usd:before{content:"\f155"}.fa-rupee:before,.fa-inr:before{content:"\f156"}.fa-cny:before,.fa-rmb:before,.fa-yen:before,.fa-jpy:before{content:"\f157"}.fa-ruble:before,.fa-rouble:before,.fa-rub:before{content:"\f158"}.fa-won:before,.fa-krw:before{content:"\f159"}.fa-bitcoin:before,.fa-btc:before{content:"\f15a"}.fa-file:before{content:"\f15b"}.fa-file-text:before{content:"\f15c"}.fa-sort-alpha-asc:before{content:"\f15d"}.fa-sort-alpha-desc:before{content:"\f15e"}.fa-sort-amount-asc:before{content:"\f160"}.fa-sort-amount-desc:before{content:"\f161"}.fa-sort-numeric-asc:before{content:"\f162"}.fa-sort-numeric-desc:before{content:"\f163"}.fa-thumbs-up:before{content:"\f164"}.fa-thumbs-down:before{content:"\f165"}.fa-youtube-square:before{content:"\f166"}.fa-youtube:before{content:"\f167"}.fa-xing:before{content:"\f168"}.fa-xing-square:before{content:"\f169"}.fa-youtube-play:before{content:"\f16a"}.fa-dropbox:before{content:"\f16b"}.fa-stack-overflow:before{content:"\f16c"}.fa-instagram:before{content:"\f16d"}.fa-flickr:before{content:"\f16e"}.fa-adn:before{content:"\f170"}.fa-bitbucket:before{content:"\f171"}.fa-bitbucket-square:before{content:"\f172"}.fa-tumblr:before{content:"\f173"}.fa-tumblr-square:before{content:"\f174"}.fa-long-arrow-down:before{content:"\f175"}.fa-long-arrow-up:before{content:"\f176"}.fa-long-arrow-left:before{content:"\f177"}.fa-long-arrow-right:before{content:"\f178"}.fa-apple:before{content:"\f179"}.fa-windows:before{content:"\f17a"}.fa-android:before{content:"\f17b"}.fa-linux:before{content:"\f17c"}.fa-dribbble:before{content:"\f17d"}.fa-skype:before{content:"\f17e"}.fa-foursquare:before{content:"\f180"}.fa-trello:before{content:"\f181"}.fa-female:before{content:"\f182"}.fa-male:before{content:"\f183"}.fa-gittip:before{content:"\f184"}.fa-sun-o:before{content:"\f185"}.fa-moon-o:before{content:"\f186"}.fa-archive:before{content:"\f187"}.fa-bug:before{content:"\f188"}.fa-vk:before{content:"\f189"}.fa-weibo:before{content:"\f18a"}.fa-renren:before{content:"\f18b"}.fa-pagelines:before{content:"\f18c"}.fa-stack-exchange:before{content:"\f18d"}.fa-arrow-circle-o-right:before{content:"\f18e"}.fa-arrow-circle-o-left:before{content:"\f190"}.fa-toggle-left:before,.fa-caret-square-o-left:before{content:"\f191"}.fa-dot-circle-o:before{content:"\f192"}.fa-wheelchair:before{content:"\f193"}.fa-vimeo-square:before{content:"\f194"}.fa-turkish-lira:before,.fa-try:before{content:"\f195"}.fa-plus-square-o:before{content:"\f196"} diff --git a/public/css/styles.less b/public/css/styles.less index 3d73ec4..4b79cad 100644 --- a/public/css/styles.less +++ b/public/css/styles.less @@ -1,6 +1,5 @@ @import "lib/bootstrap/bootstrap"; @import "themes/flatly"; -@import (less) "lib/font-awesome.min.css"; // Scaffolding // ------------------------- diff --git a/public/fonts/FontAwesome.otf b/public/fonts/FontAwesome.otf deleted file mode 100644 index 8b0f54e..0000000 Binary files a/public/fonts/FontAwesome.otf and /dev/null differ diff --git a/public/fonts/fontawesome-webfont.eot b/public/fonts/fontawesome-webfont.eot deleted file mode 100755 index 7c79c6a..0000000 Binary files a/public/fonts/fontawesome-webfont.eot and /dev/null differ diff --git a/public/fonts/fontawesome-webfont.svg b/public/fonts/fontawesome-webfont.svg deleted file mode 100755 index 45fdf33..0000000 --- a/public/fonts/fontawesome-webfont.svg +++ /dev/null @@ -1,414 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/public/fonts/fontawesome-webfont.ttf b/public/fonts/fontawesome-webfont.ttf deleted file mode 100755 index e89738d..0000000 Binary files a/public/fonts/fontawesome-webfont.ttf and /dev/null differ diff --git a/public/fonts/fontawesome-webfont.woff b/public/fonts/fontawesome-webfont.woff deleted file mode 100755 index 8c1748a..0000000 Binary files a/public/fonts/fontawesome-webfont.woff and /dev/null differ diff --git a/public/img/algbias-thumb.png b/public/img/algbias-thumb.png new file mode 100644 index 0000000..c9233a1 Binary files /dev/null and b/public/img/algbias-thumb.png differ diff --git a/public/img/under-construction.gif b/public/img/under-construction.gif new file mode 100644 index 0000000..9eae818 Binary files /dev/null and b/public/img/under-construction.gif differ diff --git a/public/img/vd-tut-transcript.png b/public/img/vd-tut-transcript.png new file mode 100644 index 0000000..811c6e9 Binary files /dev/null and b/public/img/vd-tut-transcript.png differ diff --git a/public/img/video-digest-browser.png b/public/img/video-digest-browser.png new file mode 100644 index 0000000..db9c844 Binary files /dev/null and b/public/img/video-digest-browser.png differ diff --git a/public/img/whatiscomputation.png b/public/img/whatiscomputation.png new file mode 100644 index 0000000..b4bfed5 Binary files /dev/null and b/public/img/whatiscomputation.png differ diff --git a/public/js/analytics.js b/public/js/analytics.js index dda259e..57ad2d9 100644 --- a/public/js/analytics.js +++ b/public/js/analytics.js @@ -1,7 +1,16 @@ -(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){ -(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o), -m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m) -})(window,document,'script','//www.google-analytics.com/analytics.js','ga'); +(function (i, s, o, g, r, a, m) { + i['GoogleAnalyticsObject'] = r; + (i[r] = + i[r] || + function () { + (i[r].q = i[r].q || []).push(arguments); + }), + (i[r].l = 1 * new Date()); + (a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]); + a.async = 1; + a.src = g; + m.parentNode.insertBefore(a, m); +})(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'); ga('create', 'UA-55492010-1', 'auto'); ga('send', 'pageview'); diff --git a/public/js/build.js b/public/js/build.js index 2b75bc7..83e1842 100644 --- a/public/js/build.js +++ b/public/js/build.js @@ -1,37 +1,38 @@ ({ - name: "editing-interface/main.js", - out: "main-built.js", + name: 'editing-interface/main.js', + out: 'main-built.js', paths: { - jquery:"lib/jquery-1.11.0.min", - underscore: "lib/underscore-min", - backbone: "lib/backbone-min", - canvas2Image: "lib/canvas2image", - text: "lib/text", - jquerySmoothScroll: "lib/jquery.smooth-scroll", - jscrollpane: "lib/jquery.jscrollpane.min", - filesaver: "lib/FileSaver", - jmousewheel: "lib/jquery.mousewheel", - jform: "lib/jquery.form.min", - toastr: "lib/toastr", - jmenu: "lib/jquery.contextmenu" + jquery: 'lib/jquery-1.11.0.min', + underscore: 'lib/underscore-min', + backbone: 'lib/backbone-min', + canvas2Image: 'lib/canvas2image', + text: 'lib/text', + jquerySmoothScroll: 'lib/jquery.smooth-scroll', + jscrollpane: 'lib/jquery.jscrollpane.min', + filesaver: 'lib/FileSaver', + jmousewheel: 'lib/jquery.mousewheel', + jform: 'lib/jquery.form.min', + toastr: 'lib/toastr', + jmenu: 'lib/jquery.contextmenu', + micromodal: 'lib/micromodal.min', }, shim: { - jmenu: ["jquery"], - jmousewheel: ["jquery"], - jform: ["jquery"], + jmenu: ['jquery'], + jmousewheel: ['jquery'], + jform: ['jquery'], filesaver: { - exports: ["saveAs", "Blob"] + exports: ['saveAs', 'Blob'], }, - jscrollpane: ["jquery", "jmousewheel"], + jscrollpane: ['jquery', 'jmousewheel'], underscore: { - exports: "_" + exports: '_', }, jquerySmoothScroll: { - deps: ['jquery'] + deps: ['jquery'], }, backbone: { deps: ['underscore', 'jquery'], - exports: 'Backbone' - } - } -}) + exports: 'Backbone', + }, + }, +}); diff --git a/public/js/editing-interface/collections/chapter-collection.js b/public/js/editing-interface/collections/chapter-collection.js index 70c95d4..dad8087 100644 --- a/public/js/editing-interface/collections/chapter-collection.js +++ b/public/js/editing-interface/collections/chapter-collection.js @@ -1,26 +1,28 @@ - /*global define*/ -define(["backbone", "editing-interface/models/chapter-model"], function(Backbone, ChapterModel){ +define(['backbone', 'editing-interface/models/chapter-model'], function ( + Backbone, + ChapterModel +) { return Backbone.Collection.extend({ model: ChapterModel, initialize: function () { var thisModel = this; - thisModel.on("change:state", function () { - thisModel.trigger.apply("change:state", arguments); + thisModel.on('change:state', function () { + thisModel.trigger.apply('change:state', arguments); }); }, comparator: function (ch1, ch2) { - var c1sw = ch1.get("startWord"), - c2sw = ch2.get("startWord"); + var c1sw = ch1.get('startWord'), + c2sw = ch2.get('startWord'); if (!c1sw) { return 1; } else if (!c2sw) { return -1; } else { - return c1sw.get("start") > c2sw.get("start") ? 1 : -1; + return c1sw.get('start') > c2sw.get('start') ? 1 : -1; } - } + }, }); }); diff --git a/public/js/editing-interface/collections/section-collection.js b/public/js/editing-interface/collections/section-collection.js index 14ece90..b870cc8 100644 --- a/public/js/editing-interface/collections/section-collection.js +++ b/public/js/editing-interface/collections/section-collection.js @@ -1,18 +1,20 @@ - /*global define*/ -define(["backbone", "editing-interface/models/section-model"], function(Backbone, SectionModel){ +define(['backbone', 'editing-interface/models/section-model'], function ( + Backbone, + SectionModel +) { return Backbone.Collection.extend({ model: SectionModel, comparator: function (sec1, sec2) { - var c1sw = sec1.get("startWord"), - c2sw = sec2.get("startWord"); + var c1sw = sec1.get('startWord'), + c2sw = sec2.get('startWord'); if (!c1sw) { return 1; } else if (!c2sw) { return -1; } else { - return c1sw.get("start") > c2sw.get("start") ? 1 : -1; + return c1sw.get('start') > c2sw.get('start') ? 1 : -1; } - } + }, }); }); diff --git a/public/js/editing-interface/collections/word-collection.js b/public/js/editing-interface/collections/word-collection.js index f0c6190..eec3415 100644 --- a/public/js/editing-interface/collections/word-collection.js +++ b/public/js/editing-interface/collections/word-collection.js @@ -1,11 +1,13 @@ - /*global define*/ -define(["backbone", "editing-interface/models/word-model"], function(Backbone, WordModel){ +define(['backbone', 'editing-interface/models/word-model'], function ( + Backbone, + WordModel +) { return Backbone.Collection.extend({ model: WordModel, comparator: function (w1, w2) { // keep the words ordered by start time - return w1.get("start") > w2.get("start") ? 1 : -1; - } + return w1.get('start') > w2.get('start') ? 1 : -1; + }, }); }); diff --git a/public/js/editing-interface/editing-interface/main-built.js b/public/js/editing-interface/editing-interface/main-built.js deleted file mode 100644 index db249da..0000000 --- a/public/js/editing-interface/editing-interface/main-built.js +++ /dev/null @@ -1,60 +0,0 @@ -/*! jQuery v1.11.0 | (c) 2005, 2014 jQuery Foundation, Inc. | jquery.org/license */ - -// Underscore.js 1.6.0 -// http://underscorejs.org -// (c) 2009-2014 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors -// Underscore may be freely distributed under the MIT license. - -/** - * @license RequireJS text 2.0.10 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved. - * Available via the MIT or new BSD license. - * see: http://github.com/requirejs/text for details - */ - -/* - * Toastr - * Copyright 2012-2014 John Papa and Hans Fjällemark. - * All Rights Reserved. - * Use, reproduction, distribution, and modification of this code is subject to the terms and - * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php - * - * Author: John Papa and Hans Fjällemark - * ARIA Support: Greta Krafsig - * Project: https://github.com/CodeSeven/toastr - */ - -/*! Copyright (c) 2013 Brandon Aaron (http://brandon.aaron.sh) - * Licensed under the MIT License (LICENSE.txt). - * - * Version: 3.1.9 - * - * Requires: jQuery 1.2.2+ - */ - -/*! - * jScrollPane - v2.0.19 - 2013-11-16 - * http://jscrollpane.kelvinluck.com/ - * - * Copyright (c) 2013 Kelvin Luck - * Dual licensed under the MIT or GPL licenses. - */ - -/*! FileSaver.js - * A saveAs() FileSaver implementation. - * 2014-01-24 - * - * By Eli Grey, http://eligrey.com - * License: X11/MIT - * See LICENSE.md - */ - -/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */ - -/* -* jQuery Form Plugin; v20140218 -* http://jquery.malsup.com/form/ -* Copyright (c) 2014 M. Alsup; Dual licensed: MIT/GPL -* https://github.com/malsup/form#copyright-and-license -*/ - -!function(e,t){"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(e,t){function y(e){var t=e.length,n=p.type(e);return"function"===n||p.isWindow(e)?!1:1===e.nodeType&&t?!0:"array"===n||0===t||"number"==typeof t&&t>0&&t-1 in e}function x(e,t,n){if(p.isFunction(t))return p.grep(e,function(e,r){return!!t.call(e,r,e)!==n});if(t.nodeType)return p.grep(e,function(e){return e===t!==n});if("string"==typeof t){if(S.test(t))return p.filter(t,e,n);t=p.filter(t,e)}return p.grep(e,function(e){return p.inArray(e,t)>=0!==n})}function O(e,t){do e=e[t];while(e&&1!==e.nodeType);return e}function D(e){var t=_[e]={};return p.each(e.match(M)||[],function(e,n){t[n]=!0}),t}function H(){N.addEventListener?(N.removeEventListener("DOMContentLoaded",B,!1),e.removeEventListener("load",B,!1)):(N.detachEvent("onreadystatechange",B),e.detachEvent("onload",B))}function B(){(N.addEventListener||"load"===event.type||"complete"===N.readyState)&&(H(),p.ready())}function R(e,t,n){if(void 0===n&&1===e.nodeType){var r="data-"+t.replace(q,"-$1").toLowerCase();if(n=e.getAttribute(r),"string"==typeof n){try{n="true"===n?!0:"false"===n?!1:"null"===n?null:+n+""===n?+n:I.test(n)?p.parseJSON(n):n}catch(i){}p.data(e,t,n)}else n=void 0}return n}function U(e){var t;for(t in e)if(("data"!==t||!p.isEmptyObject(e[t]))&&"toJSON"!==t)return!1;return!0}function z(e,t,r,i){if(p.acceptData(e)){var s,o,u=p.expando,a=e.nodeType,f=a?p.cache:e,l=a?e[u]:e[u]&&u;if(l&&f[l]&&(i||f[l].data)||void 0!==r||"string"!=typeof t)return l||(l=a?e[u]=n.pop()||p.guid++:u),f[l]||(f[l]=a?{}:{toJSON:p.noop}),("object"==typeof t||"function"==typeof t)&&(i?f[l]=p.extend(f[l],t):f[l].data=p.extend(f[l].data,t)),o=f[l],i||(o.data||(o.data={}),o=o.data),void 0!==r&&(o[p.camelCase(t)]=r),"string"==typeof t?(s=o[t],null==s&&(s=o[p.camelCase(t)])):s=o,s}}function W(e,t,n){if(p.acceptData(e)){var r,i,s=e.nodeType,o=s?p.cache:e,u=s?e[p.expando]:p.expando;if(o[u]){if(t&&(r=n?o[u]:o[u].data)){p.isArray(t)?t=t.concat(p.map(t,p.camelCase)):t in r?t=[t]:(t=p.camelCase(t),t=t in r?[t]:t.split(" ")),i=t.length;while(i--)delete r[t[i]];if(n?!U(r):!p.isEmptyObject(r))return}(n||(delete o[u].data,U(o[u])))&&(s?p.cleanData([e],!0):c.deleteExpando||o!=o.window?delete o[u]:o[u]=null)}}}function tt(){return!0}function nt(){return!1}function rt(){try{return N.activeElement}catch(e){}}function it(e){var t=st.split("|"),n=e.createDocumentFragment();if(n.createElement)while(t.length)n.createElement(t.pop());return n}function Et(e,t){var n,r,i=0,s=typeof e.getElementsByTagName!==j?e.getElementsByTagName(t||"*"):typeof e.querySelectorAll!==j?e.querySelectorAll(t||"*"):void 0;if(!s)for(s=[],n=e.childNodes||e;null!=(r=n[i]);i++)!t||p.nodeName(r,t)?s.push(r):p.merge(s,Et(r,t));return void 0===t||t&&p.nodeName(e,t)?p.merge([e],s):s}function St(e){K.test(e.type)&&(e.defaultChecked=e.checked)}function xt(e,t){return p.nodeName(e,"table")&&p.nodeName(11!==t.nodeType?t:t.firstChild,"tr")?e.getElementsByTagName("tbody")[0]||e.appendChild(e.ownerDocument.createElement("tbody")):e}function Tt(e){return e.type=(null!==p.find.attr(e,"type"))+"/"+e.type,e}function Nt(e){var t=mt.exec(e.type);return t?e.type=t[1]:e.removeAttribute("type"),e}function Ct(e,t){for(var n,r=0;null!=(n=e[r]);r++)p._data(n,"globalEval",!t||p._data(t[r],"globalEval"))}function kt(e,t){if(1===t.nodeType&&p.hasData(e)){var n,r,i,s=p._data(e),o=p._data(t,s),u=s.events;if(u){delete o.handle,o.events={};for(n in u)for(r=0,i=u[n].length;i>r;r++)p.event.add(t,n,u[n][r])}o.data&&(o.data=p.extend({},o.data))}}function Lt(e,t){var n,r,i;if(1===t.nodeType){if(n=t.nodeName.toLowerCase(),!c.noCloneEvent&&t[p.expando]){i=p._data(t);for(r in i.events)p.removeEvent(t,r,i.handle);t.removeAttribute(p.expando)}"script"===n&&t.text!==e.text?(Tt(t).text=e.text,Nt(t)):"object"===n?(t.parentNode&&(t.outerHTML=e.outerHTML),c.html5Clone&&e.innerHTML&&!p.trim(t.innerHTML)&&(t.innerHTML=e.innerHTML)):"input"===n&&K.test(e.type)?(t.defaultChecked=t.checked=e.checked,t.value!==e.value&&(t.value=e.value)):"option"===n?t.defaultSelected=t.selected=e.defaultSelected:("input"===n||"textarea"===n)&&(t.defaultValue=e.defaultValue)}}function Mt(t,n){var r=p(n.createElement(t)).appendTo(n.body),i=e.getDefaultComputedStyle?e.getDefaultComputedStyle(r[0]).display:p.css(r[0],"display");return r.detach(),i}function _t(e){var t=N,n=Ot[e];return n||(n=Mt(e,t),"none"!==n&&n||(At=(At||p("