diff --git a/config/environments/development.js b/config/environments/development.js index 25988f7..4883003 100644 --- a/config/environments/development.js +++ b/config/environments/development.js @@ -17,8 +17,18 @@ module.exports = { port: process.env.PORT || 18888 }, + cdn: { + hostname: "https://cdnapp2.loquedeverdadimporta.org", + }, + paginate: { limit: 10, maxLimit: 50 + }, + + vimeo: { + CLIENT_ID: '9581f2d0ed211dc1e31b5c825117dc1f00d77ba0', + CLIENT_SECRET: '3kf0hQ63OXSPm7z2X1qyOV4iH57Xha0cyRXn0VJneq8zHbWKjfB1/9H8KcgBgzgkzw0Y9x/xFLUAauuHLEkqHxLBw8QueanCgIZev1L5xoksrKuKX7gMvErqqP+uFNnA', + ACCESS_TOKEN: '2843aed2064f8148d74074dff7807d92' } } diff --git a/config/environments/production.js b/config/environments/production.js index 43d7f12..a62b311 100644 --- a/config/environments/production.js +++ b/config/environments/production.js @@ -15,13 +15,28 @@ module.exports = { */ }, - session: { - secret_token: process.env.SECRET_TOKEN || "B57J=7B`NQ$y98|~5;hc715bo09^5oz8NR+]n9r~215B91Nd9P%25_N6r!GHcOKp|18y5-73Dr5^@9k7n]5l<-41D1o", - token_expires_in: '365d' - }, + session: { + secret_token: process.env.SECRET_TOKEN || "B57J=7B`NQ$y98|~5;hc715bo09^5oz8NR+]n9r~215B91Nd9P%25_N6r!GHcOKp|18y5-73Dr5^@9k7n]5l<-41D1o", + token_expires_in: '365d' + }, - server: { - hostname: process.env.HOSTNAME || '127.0.0.1', - port: process.env.PORT || 18888 - } + server: { + hostname: process.env.HOSTNAME || '127.0.0.1', + port: process.env.PORT || 18888 + }, + + cdn: { + hostname: "https://cdnapp2.loquedeverdadimporta.org", + }, + + paginate: { + limit: 10, + maxLimit: 50 + }, + + vimeo: { + CLIENT_ID: '9581f2d0ed211dc1e31b5c825117dc1f00d77ba0', + CLIENT_SECRET: '3kf0hQ63OXSPm7z2X1qyOV4iH57Xha0cyRXn0VJneq8zHbWKjfB1/9H8KcgBgzgkzw0Y9x/xFLUAauuHLEkqHxLBw8QueanCgIZev1L5xoksrKuKX7gMvErqqP+uFNnA', + ACCESS_TOKEN: '2843aed2064f8148d74074dff7807d92' + } } diff --git a/helpers/cdn.helper.js b/helpers/cdn.helper.js new file mode 100644 index 0000000..2e24b84 --- /dev/null +++ b/helpers/cdn.helper.js @@ -0,0 +1,31 @@ +const config = require('../config'); + +const assetsUrl = config.cdn.hostname; + +const CDN_PATHS = { + BLOG: "blog/", + CITIES: "cities/", + PROFILE: "profile/", + SPEAKERS: "speakers/", + WALLPAPERS: "wallpapers/" +}; + + +const getCDNMediaUrl = (mediaUri) => { + if (mediaUri) { + const pathParsed = mediaUri.indexOf("media") == 0 ? mediaUri.substr("media/".length, mediaUri.length) : mediaUri; + return encodeURI(encodeURI(`${assetsUrl}/${pathParsed}`)); + } + else { + return encodeURI(dummyMedia); + } +} + +const getCDNCityMediaUrl = (cityName) => encodeURI(`${assetsUrl}/${CDN_PATHS.CITIES}/${cityName}.jpg`); + + + +module.exports = { + getCDNCityMediaUrl, + getCDNMediaUrl +} \ No newline at end of file diff --git a/helpers/composes.helper.js b/helpers/composes.helper.js index cfee390..29f2461 100644 --- a/helpers/composes.helper.js +++ b/helpers/composes.helper.js @@ -1,10 +1,22 @@ 'use strict'; +const cdnHelper = require('./cdn.helper'); const valuesComposer = (values) => values.map(value => ({ id: value.id, name: value.name, })); +const commentsComposer = (comments) => comments.map(comment => ({ + ...comment, + userId: undefined, + user: { + ...comment.user, + profile_picture: cdnHelper.getCDNMediaUrl(comment.user.profile_picture) + + } +})) + + const multimediaComposer = (multimedias) => multimedias.map(multimedia => ({ ...multimedia, ...multimedia.MultimediaFile, @@ -14,8 +26,10 @@ const multimediaComposer = (multimedias) => multimedias.map(multimedia => ({ createdAt: undefined, updatedAt: undefined, userId: undefined, + url: (multimedia.MultimediaFile.provider === 'cdn') ? cdnHelper.getCDNMediaUrl(multimedia.MultimediaFile.url) : multimedia.MultimediaFile.url, })); + const socialNetworksComposer = (speaker, context) => { return { rrss: { @@ -35,10 +49,16 @@ const socialNetworksComposer = (speaker, context) => { }; }; + const speakerComposer = (speaker, context) => { - let multimedias = [] + let multimedias = []; if (context.scopes.includes('includeMultimedias')) { - multimedias = multimediaComposer(speaker.multimedias) + multimedias = multimediaComposer(speaker.multimedias); + }; + + let comments = []; + if (context.scopes.includes('includeComments')) { + comments = commentsComposer(speaker.comments); }; speaker.typename = speaker.type.name; @@ -52,6 +72,7 @@ const speakerComposer = (speaker, context) => { speaker, rrss, { multimedias: multimedias }, + { comments: comments }, ) }; @@ -61,6 +82,7 @@ const eventComposer = (event, context) => { if (context.scopes.includes('includeVenue')) { delete event.venue.updatedAt; delete event.venue.createdAt; + event.venue.image_url = cdnHelper.getCDNCityMediaUrl(event.venue.city); }; let multimedias = [] diff --git a/helpers/vimeo.helper.js b/helpers/vimeo.helper.js new file mode 100644 index 0000000..1121b1b --- /dev/null +++ b/helpers/vimeo.helper.js @@ -0,0 +1,22 @@ +const config = require('../config'); +const Vimeo = require('vimeo').Vimeo; +const client = new Vimeo(config.vimeo.CLIENT_ID, config.vimeo.CLIENT_SECRET, config.vimeo.ACCESS_TOKEN); + +function getVimeoVideoInfo(videoId) { + return new Promise(function(resolve, reject) { + client.request({ + method: 'GET', + path: '/videos/' + videoId + }, function (error, body, status_code, headers) { + if (error) { + console.log(error); + resolve({}) + } else { + resolve(body); + } + }) + }); +} + + +module.exports = getVimeoVideoInfo; diff --git a/middlewares/cache.js b/middlewares/cache.js new file mode 100644 index 0000000..a56be49 --- /dev/null +++ b/middlewares/cache.js @@ -0,0 +1,20 @@ +const apicache = require('apicache'); +const redis = require('redis'); + +let cacheWithRedis = apicache + .options({ + debug: true, + defaultDuration: '1 hour', + redisClient: redis.createClient() + }) + .middleware; + +// higher-order function returns false for responses of other status codes (e.g. 403, 404, 500, etc) +const onlyStatus200 = (req, res) => res.statusCode === 200 + +const cacheSuccesses = cacheWithRedis('1 hour', onlyStatus200); + +module.exports = { + cacheSuccesses, +} + diff --git a/modules/blog/blog.routes.js b/modules/blog/blog.routes.js index 4a6f8e2..06f2195 100644 --- a/modules/blog/blog.routes.js +++ b/modules/blog/blog.routes.js @@ -16,7 +16,7 @@ routes.get('/posts', isLoggedUser, }), PaginateMiddleware.middleware(), SortMiddleware.middleware({ default: "date" }), - blogController.find); + blogController.find()); routes.post('/posts', isAdministratorUser, blogController.create); @@ -26,7 +26,8 @@ routes.get('/posts/:id', isLoggedUser, }), //PaginateMiddleware.middleware(), //SortMiddleware.middleware({ default: "date" }), - blogController.findOne); + blogController.findOne() + ); routes.put('/posts/:id', isAdministratorUser, blogController.update); diff --git a/modules/comments/comment.model.js b/modules/comments/comment.model.js index 73d0e1d..ab92f96 100644 --- a/modules/comments/comment.model.js +++ b/modules/comments/comment.model.js @@ -54,7 +54,7 @@ module.exports = function (sequelize, DataTypes) { Comment.associate = function (models) { - Comment.User = Comment.belongsTo(models.User, { foreignKey: 'userId', constraints: false }); + Comment.User = Comment.belongsTo(models.User, { foreignKey: 'userId', constraints: false, as: 'user' }); //Comment.Conference = Comment.belongsTo(models.Conference, { foreignKey: 'conferenceId', constraints: false }); //Comment.Post = Comment.belongsTo(models.Post, { foreignKey: 'postId', constraints: false }); //Comment.Speaker = Comment.belongsTo(models.Speaker, { foreignKey: 'speakerId', constraints: false }); diff --git a/modules/events/event.service.js b/modules/events/event.service.js index 37f18b6..b7d1a74 100644 --- a/modules/events/event.service.js +++ b/modules/events/event.service.js @@ -8,7 +8,6 @@ const Sequelize = require('sequelize'); const models = require('../../core/models'); const { eventComposer } = require('../../helpers/composes.helper'); - const extraMethods = { afterFetchAll: (result, params, context) => { diff --git a/modules/multimedia/multimedia.model.js b/modules/multimedia/multimedia.model.js index 8384628..7795bd4 100644 --- a/modules/multimedia/multimedia.model.js +++ b/modules/multimedia/multimedia.model.js @@ -60,8 +60,22 @@ module.exports = function (sequelize, DataTypes) { timestamps: true, }); + Multimedia.addScope('includeMultimediaFile', () => { + return { + include: [ + { model: sequelize.models.MultimediaFile, as: 'multimediaFile' } + ] + } + }); + Multimedia.associate = function (models) { - Multimedia.MultimediaFile = Multimedia.belongsTo(models.MultimediaFile, { foreignKey: 'multimediafileId' }); + Multimedia.MultimediaFile = Multimedia.belongsTo(models.MultimediaFile, { foreignKey: 'multimediafileId', as: "multimediaFile" }); + + Multimedia.Speaker = Multimedia.hasOne(models.Speaker, { + foreignKey: 'entityId', + as: 'speaker' + }); + }; return Multimedia; diff --git a/modules/multimedia/multimedia.routes.js b/modules/multimedia/multimedia.routes.js index fb88ffd..81e0e6c 100644 --- a/modules/multimedia/multimedia.routes.js +++ b/modules/multimedia/multimedia.routes.js @@ -1,6 +1,8 @@ const routes = require('express').Router(); const { isAdministratorUser, isLoggedUser } = require('../../middlewares/accessValidator'); +const { cacheSuccesses } = require('../../middlewares/cache'); + //const SchemaValidator = require('../../middlewares/schemaValidator'); const PaginateMiddleware = require('../../middlewares/paginate'); @@ -11,23 +13,27 @@ const SortMiddleware = require('../../middlewares/sort'); const multimediaController = require('./multimedia.controller'); -routes.get('/multimedias', +routes.get('/multimedias', //cacheSuccesses, PaginateMiddleware.middleware(), //SortMiddleware.middleware({ default: "init_available_date" }), - multimediaController.find + multimediaController.find({ + scopes: ['includeMultimediaFile'] + }) ); -routes.get('/multimedias/:id', +routes.get('/multimedias/:id', //cacheSuccesses, //PaginateMiddleware.middleware(), //SortMiddleware.middleware({ default: "init_available_date" }), - multimediaController.findOne + multimediaController.findOne({ + scopes: ['includeMultimediaFile'] + }) ); routes.get('/multimedias/:entityId', //PaginateMiddleware.middleware(), //SortMiddleware.middleware({ default: "init_available_date" }), - multimediaController.find + multimediaController.find({}) ); diff --git a/modules/multimedia/multimedia.service.js b/modules/multimedia/multimedia.service.js index 6029a3b..943ff16 100644 --- a/modules/multimedia/multimedia.service.js +++ b/modules/multimedia/multimedia.service.js @@ -4,7 +4,27 @@ const _ = require('lodash'); const { generateService, parseParamsToFindOptions } = require('../../helpers/service.helper'); const models = require('../../core/models'); +const getVimeoVideoInfo = require('../../helpers/vimeo.helper'); -const extraMethods = {}; +const providerComposer = (multimedia) => { + return getVimeoVideoInfo(multimedia.code) +} + +const extraMethods = { + afterFetchOne: async (result, params, context) => { + if (!result) { + return result; + } + + const multimedia = result.toJSON(); + console.log(multimedia); + + if (multimedia.provider === 'vimeo') { + multimedia.providerInfo = await providerComposer(multimedia); + } + return multimedia; + }, + +} module.exports = generateService(models.Multimedia, extraMethods); \ No newline at end of file diff --git a/modules/multimedia/multimedia_file.controller.js b/modules/multimedia/multimedia_file.controller.js new file mode 100644 index 0000000..ac09681 --- /dev/null +++ b/modules/multimedia/multimedia_file.controller.js @@ -0,0 +1,14 @@ +'use strict'; + +const generateControllers = require('../../core/controllers'); +const multimediaFileService = require('./multimedia_file.service'); + + +// Module Name +const MODULE_NAME = '[multimediaFile.controller]'; + +const controllerOptions = { MODULE_NAME }; +const extraControllers = {}; + +module.exports = generateControllers(multimediaFileService, extraControllers, controllerOptions); + diff --git a/modules/multimedia/multimedia_file.model.js b/modules/multimedia/multimedia_file.model.js index 9731313..240e6d9 100644 --- a/modules/multimedia/multimedia_file.model.js +++ b/modules/multimedia/multimedia_file.model.js @@ -37,8 +37,16 @@ module.exports = function (sequelize, DataTypes) { MultimediaFile.associate = function (models) { MultimediaFile.UserCreate = MultimediaFile.belongsTo(models.User, { foreignKey: 'userId' }); - MultimediaFile.Multimedias = MultimediaFile.hasMany(models.Multimedia, { foreignKey: 'multimediafileId' }); + MultimediaFile.Multimedias = MultimediaFile.hasMany(models.Multimedia, { foreignKey: 'multimediafileId', as: "multimedias" }); }; + MultimediaFile.addScope('includeMultimedias', () => { + return { + include: [ + { model: sequelize.models.Multimedia, as: 'multimedias' } + ] + } + }); + return MultimediaFile; }; \ No newline at end of file diff --git a/modules/multimedia/multimedia_file.routes.js b/modules/multimedia/multimedia_file.routes.js new file mode 100644 index 0000000..42fefa0 --- /dev/null +++ b/modules/multimedia/multimedia_file.routes.js @@ -0,0 +1,41 @@ +const routes = require('express').Router(); + +const { isAdministratorUser, isLoggedUser } = require('../../middlewares/accessValidator'); +const { cacheSuccesses } = require('../../middlewares/cache'); + +//const SchemaValidator = require('../../middlewares/schemaValidator'); + +const PaginateMiddleware = require('../../middlewares/paginate'); +const FieldMiddleware = require('../../middlewares/fields'); +const SortMiddleware = require('../../middlewares/sort'); +const multimediaFileController = require('./multimedia_file.controller'); + +const generalInvalidFields = [ + 'userId', 'createdAt', 'updatedAt', +]; + +routes.get('/multimediafiles', //cacheSuccesses, + FieldMiddleware.middleware({ + invalidFields: generalInvalidFields + }), + PaginateMiddleware.middleware(), + //SortMiddleware.middleware({ default: "init_available_date" }), + multimediaFileController.find({ + scopes: ['includeMultimedias'] + }) +); + +routes.get('/multimediafiles/:id', //cacheSuccesses, + FieldMiddleware.middleware({ + invalidFields: generalInvalidFields + }), + //SortMiddleware.middleware({ default: "init_available_date" }), + multimediaFileController.findOne({ + scopes: ['includeMultimedias'] + }) +); + + + + +module.exports = routes; \ No newline at end of file diff --git a/modules/multimedia/multimedia_file.service.js b/modules/multimedia/multimedia_file.service.js new file mode 100644 index 0000000..3375afc --- /dev/null +++ b/modules/multimedia/multimedia_file.service.js @@ -0,0 +1,30 @@ +/* global Venue */ +'use strict'; + +const _ = require('lodash'); +const { generateService, parseParamsToFindOptions } = require('../../helpers/service.helper'); +const models = require('../../core/models'); +const getVimeoVideoInfo = require('../../helpers/vimeo.helper'); + +const providerComposer = (multimedia) => { + return getVimeoVideoInfo(multimedia.code) +} + +const extraMethods = { + afterFetchOne: async (result, params, context) => { + if (!result) { + return result; + } + + const multimedia = result.toJSON(); + console.log(multimedia); + + if (multimedia.provider === 'vimeo') { + multimedia.providerInfo = await providerComposer(multimedia); + } + return multimedia; + }, + +} + +module.exports = generateService(models.MultimediaFile, extraMethods); \ No newline at end of file diff --git a/modules/speakers/speaker.model.js b/modules/speakers/speaker.model.js index 3b54b45..b03ecb9 100644 --- a/modules/speakers/speaker.model.js +++ b/modules/speakers/speaker.model.js @@ -141,6 +141,10 @@ module.exports = function (sequelize, DataTypes) { model: sequelize.models.Comment, as: 'comments', required: false, + include: [{ + model: sequelize.models.User, + as: 'user', + }] }] } }); diff --git a/modules/speakers/speaker.service.js b/modules/speakers/speaker.service.js index d2fefcf..8957886 100644 --- a/modules/speakers/speaker.service.js +++ b/modules/speakers/speaker.service.js @@ -7,8 +7,6 @@ const Sequelize = require('sequelize'); const models = require('../../core/models'); const { speakerComposer } = require('../../helpers/composes.helper'); - - const extraMethods = { afterFetchAll: (result, params, context) => { diff --git a/package.json b/package.json index 88daa76..6e39c7a 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "nodemon": "^1.18.9" }, "dependencies": { + "apicache": "^1.4.0", "args-list": "^0.3.3", "async": "^2.6.2", "bcrypt": "^3.0.6", @@ -51,8 +52,10 @@ "path": "^0.12.7", "pino": "^4.7.1", "rand-token": "^0.4.0", + "redis": "^2.8.0", "response-time": "^2.3.2", "sequelize": "^5.3.5", + "vimeo": "^2.1.1", "vm": "^0.1.0", "winston": "^3.2.1" } diff --git a/yarn.lock b/yarn.lock index 5e829de..674711f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -350,6 +350,11 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +apicache@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/apicache/-/apicache-1.4.0.tgz#3835fbe18717caca3a44cb6272d49b52cac30d3a" + integrity sha512-pX/Sf9q9HNzAC5F+hPgxt8v3eQVZkXL/+8HpAnrDJXFmma80F2aHAAeWTql3BsG87lc3T6A7CFPNWMTl97L/7Q== + aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -472,7 +477,7 @@ bcrypt@^3.0.6: nan "2.13.2" node-pre-gyp "0.12.0" -bignumber.js@^7.0.0: +bignumber.js@7.2.1, bignumber.js@^7.0.0: version "7.2.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f" integrity sha512-S4XzBk5sMB+Rcb/LNcpzXr57VRTxgAvaAEDAl1AwRx27j00hT84O6OkteE7u8UB3NuaaygCRrEpqox4uDOrbdQ== @@ -550,6 +555,11 @@ buffer-equal-constant-time@1.0.1: resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" integrity sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk= +buffer-from@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-0.1.2.tgz#15f4b9bcef012044df31142c14333caf6e0260d0" + integrity sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg== + buffer-from@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" @@ -1047,6 +1057,11 @@ delegates@^1.0.0: resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= +denque@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/denque/-/denque-1.4.1.tgz#6744ff7641c148c3f8a69c307e51235c1f4a37cf" + integrity sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ== + depd@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df" @@ -1153,6 +1168,11 @@ dottie@^2.0.0: resolved "https://registry.yarnpkg.com/dottie/-/dottie-2.0.1.tgz#697ad9d72004db7574d21f892466a3c285893659" integrity sha512-ch5OQgvGDK2u8pSZeSYAQaV/lczImd7pMJ7BcEPXmnFVjy4yJIzP6CsODJUTH8mg1tyH1Z2abOiuJO3DjZ/GBw== +double-ended-queue@^2.1.0-0: + version "2.1.0-0" + resolved "https://registry.yarnpkg.com/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz#103d3527fd31528f40188130c841efdd78264e5c" + integrity sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw= + duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" @@ -1705,6 +1725,13 @@ gcs-resumable-upload@^1.0.0: pumpify "^1.5.1" stream-events "^1.0.4" +generate-function@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" + integrity sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ== + dependencies: + is-property "^1.0.2" + get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -2016,7 +2043,7 @@ iconv-lite@0.4.23: dependencies: safer-buffer ">= 2.1.2 < 3" -iconv-lite@^0.4.17, iconv-lite@^0.4.4: +iconv-lite@^0.4.17, iconv-lite@^0.4.24, iconv-lite@^0.4.4: version "0.4.24" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== @@ -2275,6 +2302,11 @@ is-promise@^2.1.0: resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= +is-property@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-property/-/is-property-1.0.2.tgz#57fe1c4e48474edd65b09911f26b1cd4095dda84" + integrity sha1-V/4cTkhHTt1lsJkR8msc1Ald2oQ= + is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" @@ -2348,6 +2380,11 @@ joi@^14.3.1: isemail "3.x.x" topo "3.x.x" +js-base64@^2.4.9: + version "2.5.1" + resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.5.1.tgz#1efa39ef2c5f7980bb1784ade4a8af2de3291121" + integrity sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw== + js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -2514,6 +2551,11 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ= + lodash@^4.15.0, lodash@^4.17.11, lodash@^4.17.4, lodash@^4.3.0, lodash@^4.9.0: version "4.17.11" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.11.tgz#b39ea6229ef607ecd89e2c8df12536891cac9b8d" @@ -2540,7 +2582,7 @@ lowercase-keys@^1.0.0: resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== -lru-cache@^4.0.1: +lru-cache@^4.0.1, lru-cache@^4.1.3: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== @@ -2746,6 +2788,37 @@ mute-stream@0.0.7: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= +mysql2@^1.6.5: + version "1.6.5" + resolved "https://registry.yarnpkg.com/mysql2/-/mysql2-1.6.5.tgz#6695304fa2ce793dda5c98e8bbec65cbd2e6cb9d" + integrity sha512-zedaOOyb3msuuZcJJnxIX/EGOpmljDG7B+UevRH5lqcv+yhy9eCwkArBz8/AO+/rlY3/oCsOdG8R5oD6k0hNfg== + dependencies: + denque "^1.4.0" + generate-function "^2.3.1" + iconv-lite "^0.4.24" + long "^4.0.0" + lru-cache "^4.1.3" + named-placeholders "^1.1.2" + seq-queue "^0.0.5" + sqlstring "^2.3.1" + +mysql@^2.17.1: + version "2.17.1" + resolved "https://registry.yarnpkg.com/mysql/-/mysql-2.17.1.tgz#62bba4a039a9b2f73638cd1652ce50fc6f682899" + integrity sha512-7vMqHQ673SAk5C8fOzTG2LpPcf3bNt0oL3sFpxPEEFp1mdlDcrLK0On7z8ZYKaaHrHwNcQ/MTUz7/oobZ2OyyA== + dependencies: + bignumber.js "7.2.1" + readable-stream "2.3.6" + safe-buffer "5.1.2" + sqlstring "2.3.1" + +named-placeholders@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/named-placeholders/-/named-placeholders-1.1.2.tgz#ceb1fbff50b6b33492b5cf214ccf5e39cef3d0e8" + integrity sha512-wiFWqxoLL3PGVReSZpjLVxyJ1bRqe+KKJVbr4hGs1KWfTZTQyezHFBbuKj9hsizHyGV2ne7EMjHdxEGAybD5SA== + dependencies: + lru-cache "^4.1.3" + nan@2.13.2, nan@^2.9.2: version "2.13.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" @@ -3268,6 +3341,11 @@ qs@6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +querystringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" + integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== + quick-format-unescaped@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/quick-format-unescaped/-/quick-format-unescaped-1.1.2.tgz#0ca581de3174becef25ac3c2e8956342381db698" @@ -3314,7 +3392,7 @@ rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: string_decoder "^1.1.1" util-deprecate "^1.0.1" -readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: +readable-stream@2.3.6, readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.2.2, readable-stream@^2.3.6, readable-stream@~2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" integrity sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw== @@ -3355,6 +3433,25 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +redis-commands@^1.2.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.5.0.tgz#80d2e20698fe688f227127ff9e5164a7dd17e785" + integrity sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg== + +redis-parser@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/redis-parser/-/redis-parser-2.6.0.tgz#52ed09dacac108f1a631c07e9b69941e7a19504b" + integrity sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs= + +redis@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/redis/-/redis-2.8.0.tgz#202288e3f58c49f6079d97af7a10e1303ae14b02" + integrity sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A== + dependencies: + double-ended-queue "^2.1.0-0" + redis-commands "^1.2.0" + redis-parser "^2.6.0" + referrer-policy@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/referrer-policy/-/referrer-policy-1.1.0.tgz#35774eb735bf50fb6c078e83334b472350207d79" @@ -3411,6 +3508,11 @@ require-uncached@^1.0.3: caller-path "^0.1.0" resolve-from "^1.0.0" +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + resolve-from@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-1.0.1.tgz#26cbfe935d1aeeeabb29bc3fe5aeb01e93d44226" @@ -3546,6 +3648,11 @@ send@0.16.2: range-parser "~1.2.0" statuses "~1.4.0" +seq-queue@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/seq-queue/-/seq-queue-0.0.5.tgz#d56812e1c017a6e4e7c3e3a37a1da6d78dd3c93e" + integrity sha1-1WgS4cAXpuTnw+Ojeh2m143TyT4= + sequelize-pool@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/sequelize-pool/-/sequelize-pool-1.0.2.tgz#89c767882bbdb8a41dac66922ed9820939a5401e" @@ -3732,6 +3839,11 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= +sqlstring@2.3.1, sqlstring@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40" + integrity sha1-R1OT/56RR5rqYtyvDKPRSYOn+0A= + stack-trace@0.0.x: version "0.0.10" resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-0.0.10.tgz#547c70b347e8d32b4e108ea1a2a159e5fdde19c0" @@ -3986,6 +4098,17 @@ tslib@1.9.3: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286" integrity sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ== +tus-js-client@^1.5.1: + version "1.7.1" + resolved "https://registry.yarnpkg.com/tus-js-client/-/tus-js-client-1.7.1.tgz#1485176052f9a360a957f475edf8e5076e339881" + integrity sha512-38NMOvjZm/HQTdmwLctXqctsUUsiuZsdUGBew6xn3/s1D7ofzjW/VBRAp+uAWrzN0ziAmo2WuiZ9FMP9UeU0UQ== + dependencies: + buffer-from "^0.1.1" + extend "^3.0.0" + js-base64 "^2.4.9" + lodash.throttle "^4.1.1" + url-parse "^1.4.3" + type-check@~0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" @@ -4086,6 +4209,14 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" +url-parse@^1.4.3: + version "1.4.7" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" + integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -4123,6 +4254,13 @@ vary@^1, vary@~1.1.2: resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= +vimeo@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/vimeo/-/vimeo-2.1.1.tgz#3cfcb75e7cbe5bcce578f832760aed55c7cc3903" + integrity sha512-6aBlIOdnCgGSigkH54DHsb1n+mW0NIAgxmh+AVEC5hwjfy6zaUtkSIrlMJbYSOwwEfkjpIBR7L8gfWDRmLaEmw== + dependencies: + tus-js-client "^1.5.1" + vm@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/vm/-/vm-0.1.0.tgz#0060d485e8b89858946c40b01a6ba07945db70a8"