From 2aace854188e5c0be78cc77050be7cb5aa7cca05 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Fri, 19 Aug 2022 10:41:44 +0200 Subject: [PATCH 01/26] Automaticly fixable eslint issues, mostly 3 -> 2 space indentation --- src/cache/redis.js | 4 +- src/config/environmentVariables.js | 18 ++-- src/config/field.js | 86 ++++++++++--------- src/config/filters.js | 48 +++++------ src/git/gitRepository.js | 9 +- src/media_classes/media.js | 25 +++--- src/media_classes/mediaInfo.js | 22 ++--- src/media_classes/player.js | 16 ++-- src/media_classes/user.js | 8 +- src/notifications/sms.js | 2 +- src/pirate/pirateRepository.js | 4 +- src/plex/convertPlexToSeasoned.js | 8 +- src/plex/mailTemplate.js | 30 +++---- src/plex/plex.js | 40 ++++----- src/plex/plexRepository.js | 4 +- src/plex/requestRepository.js | 4 +- src/plex/stream/convertStreamToPlayback.js | 20 ++--- src/plex/types/episode.js | 6 +- src/plex/types/movie.js | 4 +- src/plex/types/show.js | 2 +- src/request/request.js | 11 +-- src/request/utils.js | 36 +++++--- src/seasoned/stray.js | 6 +- src/seasoned/strayRepository.js | 2 +- src/tmdb/tmdb.js | 18 ++-- src/tmdb/types.js | 12 +-- src/tmdb/types/credits.js | 10 ++- src/tmdb/types/movie.js | 76 +++++++++++++--- src/tmdb/types/releaseDates.js | 58 ++++++++----- src/tmdb/types/show.js | 59 ++++++++++--- src/user/token.js | 6 +- src/user/user.js | 8 +- src/webserver/app.js | 4 +- .../controllers/list/listController.js | 4 +- src/webserver/controllers/movie/credits.js | 9 +- .../controllers/movie/releaseDates.js | 9 +- src/webserver/controllers/person/credits.js | 1 + src/webserver/controllers/person/info.js | 3 +- src/webserver/controllers/pirate/addMagnet.js | 6 +- src/webserver/controllers/plex/hookDump.js | 12 +-- src/webserver/controllers/plex/readRequest.js | 2 +- src/webserver/controllers/plex/search.js | 11 ++- src/webserver/controllers/plex/searchMedia.js | 10 +-- .../controllers/plex/submitRequest.js | 3 +- .../controllers/plex/updateRequested.js | 4 +- .../controllers/plex/watchDirectLink.js | 1 + .../controllers/request/fetchAllRequests.js | 5 +- .../controllers/request/getRequest.js | 3 +- .../controllers/request/requestTmdbId.js | 3 +- .../controllers/search/movieSearch.js | 3 +- .../controllers/search/multiSearch.js | 5 +- .../controllers/search/personSearch.js | 3 +- .../controllers/search/showSearch.js | 3 +- src/webserver/controllers/show/credits.js | 9 +- src/webserver/controllers/show/info.js | 3 +- .../user/authenticatePlexAccount.js | 1 + src/webserver/controllers/user/login.js | 8 +- src/webserver/controllers/user/register.js | 2 +- src/webserver/controllers/user/settings.js | 1 + src/webserver/controllers/user/viewHistory.js | 10 +-- src/webserver/middleware/mustBeAdmin.js | 31 ++++--- .../middleware/mustHaveAccountLinkedToPlex.js | 42 +++++---- 62 files changed, 498 insertions(+), 375 deletions(-) diff --git a/src/cache/redis.js b/src/cache/redis.js index 75e098c..340d884 100644 --- a/src/cache/redis.js +++ b/src/cache/redis.js @@ -21,11 +21,11 @@ try { console.error("Unable to connect to redis, setting up redis-mock."); client = { - get: function () { + get() { console.log("redis-dummy get", arguments[0]); return Promise.resolve(); }, - set: function () { + set() { console.log("redis-dummy set", arguments[0]); return Promise.resolve(); } diff --git a/src/config/environmentVariables.js b/src/config/environmentVariables.js index b7fc3f2..22d467f 100644 --- a/src/config/environmentVariables.js +++ b/src/config/environmentVariables.js @@ -1,15 +1,15 @@ class EnvironmentVariables { - constructor(variables) { - this.variables = variables || process.env; - } + constructor(variables) { + this.variables = variables || process.env; + } - get(variable) { - return this.variables[variable]; - } + get(variable) { + return this.variables[variable]; + } - has(variable) { - return this.get(variable) !== undefined; - } + has(variable) { + return this.get(variable) !== undefined; + } } module.exports = EnvironmentVariables; diff --git a/src/config/field.js b/src/config/field.js index 42eb8cd..546513b 100644 --- a/src/config/field.js +++ b/src/config/field.js @@ -1,49 +1,53 @@ -const Filters = require('./filters.js'); -const EnvironmentVariables = require('./environmentVariables.js'); +const Filters = require("./filters.js"); +const EnvironmentVariables = require("./environmentVariables.js"); class Field { - constructor(rawValue, environmentVariables) { - this.rawValue = rawValue; - this.filters = new Filters(rawValue); - this.valueWithoutFilters = this.filters.removeFiltersFromValue(); - this.environmentVariables = new EnvironmentVariables(environmentVariables); - } - - get value() { - if (this.filters.isEmpty()) { - return this.valueWithoutFilters; - } - - if (this.filters.has('base64') && !this.filters.has('env')) { - return Field.base64Decode(this.valueWithoutFilters); - } - - if (this.environmentVariables.has(this.valueWithoutFilters) && - this.environmentVariables.get(this.valueWithoutFilters) === '') { - return undefined; - } - - if (!this.filters.has('base64') && this.filters.has('env')) { - if (this.environmentVariables.has(this.valueWithoutFilters)) { - return this.environmentVariables.get(this.valueWithoutFilters); - } - return undefined; - } - - if (this.filters.has('env') && this.filters.has('base64')) { - if (this.environmentVariables.has(this.valueWithoutFilters)) { - const encodedEnvironmentVariable = this.environmentVariables.get(this.valueWithoutFilters); - return Field.base64Decode(encodedEnvironmentVariable); - } - return undefined; - } + constructor(rawValue, environmentVariables) { + this.rawValue = rawValue; + this.filters = new Filters(rawValue); + this.valueWithoutFilters = this.filters.removeFiltersFromValue(); + this.environmentVariables = new EnvironmentVariables(environmentVariables); + } + get value() { + if (this.filters.isEmpty()) { return this.valueWithoutFilters; - } + } - static base64Decode(string) { - return new Buffer(string, 'base64').toString('utf-8'); - } + if (this.filters.has("base64") && !this.filters.has("env")) { + return Field.base64Decode(this.valueWithoutFilters); + } + + if ( + this.environmentVariables.has(this.valueWithoutFilters) && + this.environmentVariables.get(this.valueWithoutFilters) === "" + ) { + return undefined; + } + + if (!this.filters.has("base64") && this.filters.has("env")) { + if (this.environmentVariables.has(this.valueWithoutFilters)) { + return this.environmentVariables.get(this.valueWithoutFilters); + } + return undefined; + } + + if (this.filters.has("env") && this.filters.has("base64")) { + if (this.environmentVariables.has(this.valueWithoutFilters)) { + const encodedEnvironmentVariable = this.environmentVariables.get( + this.valueWithoutFilters + ); + return Field.base64Decode(encodedEnvironmentVariable); + } + return undefined; + } + + return this.valueWithoutFilters; + } + + static base64Decode(string) { + return new Buffer(string, "base64").toString("utf-8"); + } } module.exports = Field; diff --git a/src/config/filters.js b/src/config/filters.js index b4ec359..8d5fad1 100644 --- a/src/config/filters.js +++ b/src/config/filters.js @@ -1,34 +1,34 @@ class Filters { - constructor(value) { - this.value = value; - this.delimiter = '|'; - } + constructor(value) { + this.value = value; + this.delimiter = "|"; + } - get filters() { - return this.value.split(this.delimiter).slice(0, -1); - } + get filters() { + return this.value.split(this.delimiter).slice(0, -1); + } - isEmpty() { - return !this.hasValidType() || this.value.length === 0; - } + isEmpty() { + return !this.hasValidType() || this.value.length === 0; + } - has(filter) { - return this.filters.includes(filter); - } + has(filter) { + return this.filters.includes(filter); + } - hasValidType() { - return (typeof this.value === 'string'); - } + hasValidType() { + return typeof this.value === "string"; + } - removeFiltersFromValue() { - if (this.hasValidType() === false) { - return this.value; - } + removeFiltersFromValue() { + if (this.hasValidType() === false) { + return this.value; + } - let filtersCombined = this.filters.join(this.delimiter); - filtersCombined += this.filters.length >= 1 ? this.delimiter : ''; - return this.value.replace(filtersCombined, ''); - } + let filtersCombined = this.filters.join(this.delimiter); + filtersCombined += this.filters.length >= 1 ? this.delimiter : ""; + return this.value.replace(filtersCombined, ""); + } } module.exports = Filters; diff --git a/src/git/gitRepository.js b/src/git/gitRepository.js index 703ce2c..7659561 100644 --- a/src/git/gitRepository.js +++ b/src/git/gitRepository.js @@ -1,9 +1,8 @@ - class GitRepository { - static dumpHook(body) { - /* eslint-disable no-console */ - console.log(body); - } + static dumpHook(body) { + /* eslint-disable no-console */ + console.log(body); + } } module.exports = GitRepository; diff --git a/src/media_classes/media.js b/src/media_classes/media.js index 4ec1627..e68f670 100644 --- a/src/media_classes/media.js +++ b/src/media_classes/media.js @@ -1,19 +1,18 @@ - class Media { - constructor(title, year, type) { - this.title = title; - this.year = year; - this.type = type; - } + constructor(title, year, type) { + this.title = title; + this.year = year; + this.type = type; + } - toString() { - return `N: ${this.title} | Y: ${this.year} | T: ${this.type}`; - } + toString() { + return `N: ${this.title} | Y: ${this.year} | T: ${this.type}`; + } - print() { - /* eslint-disable no-console */ - console.log(this.toString()); - } + print() { + /* eslint-disable no-console */ + console.log(this.toString()); + } } module.exports = Media; diff --git a/src/media_classes/mediaInfo.js b/src/media_classes/mediaInfo.js index 3cbe69d..663bcb8 100644 --- a/src/media_classes/mediaInfo.js +++ b/src/media_classes/mediaInfo.js @@ -1,15 +1,15 @@ class MediaInfo { - constructor() { - this.duration = undefined; - this.height = undefined; - this.width = undefined; - this.bitrate = undefined; - this.resolution = undefined; - this.framerate = undefined; - this.protocol = undefined; - this.container = undefined; - this.audioCodec = undefined; - } + constructor() { + this.duration = undefined; + this.height = undefined; + this.width = undefined; + this.bitrate = undefined; + this.resolution = undefined; + this.framerate = undefined; + this.protocol = undefined; + this.container = undefined; + this.audioCodec = undefined; + } } module.exports = MediaInfo; diff --git a/src/media_classes/player.js b/src/media_classes/player.js index e675f85..6f9a22f 100644 --- a/src/media_classes/player.js +++ b/src/media_classes/player.js @@ -1,12 +1,12 @@ class Player { - constructor(device, address) { - this.device = device; - this.ip = address; - this.platform = undefined; - this.product = undefined; - this.title = undefined; - this.state = undefined; - } + constructor(device, address) { + this.device = device; + this.ip = address; + this.platform = undefined; + this.product = undefined; + this.title = undefined; + this.state = undefined; + } } module.exports = Player; diff --git a/src/media_classes/user.js b/src/media_classes/user.js index fc09d7d..62a5f3e 100644 --- a/src/media_classes/user.js +++ b/src/media_classes/user.js @@ -1,8 +1,8 @@ class User { - constructor(id, title) { - this.id = id; - this.title = title; - } + constructor(id, title) { + this.id = id; + this.title = title; + } } module.exports = User; diff --git a/src/notifications/sms.js b/src/notifications/sms.js index 7e78b05..a56587f 100644 --- a/src/notifications/sms.js +++ b/src/notifications/sms.js @@ -24,7 +24,7 @@ const sendSMS = message => { } }, function (err, r, body) { - console.log(err ? err : body); + console.log(err || body); console.log("sms provider response:", body); resolve(); } diff --git a/src/pirate/pirateRepository.js b/src/pirate/pirateRepository.js index ba01bfa..70a030c 100644 --- a/src/pirate/pirateRepository.js +++ b/src/pirate/pirateRepository.js @@ -92,8 +92,8 @@ async function AddMagnet(magnet, name, tmdb_id) { "INSERT INTO requested_torrent(magnet,torrent_name,tmdb_id) \ VALUES (?,?,?)"; - let response = database.run(insert_query, [magnet, name, tmdb_id]); - console.log("Response from requsted_torrent insert: " + response); + const response = database.run(insert_query, [magnet, name, tmdb_id]); + console.log(`Response from requsted_torrent insert: ${response}`); resolve({ success: true }); }) diff --git a/src/plex/convertPlexToSeasoned.js b/src/plex/convertPlexToSeasoned.js index 148fe7c..40f1dcc 100644 --- a/src/plex/convertPlexToSeasoned.js +++ b/src/plex/convertPlexToSeasoned.js @@ -5,10 +5,10 @@ function translateAdded(date_string) { } function convertPlexToSeasoned(plex) { - const title = plex.title; - const year = plex.year; - const type = plex.type; - const summary = plex.summary; + const { title } = plex; + const { year } = plex; + const { type } = plex; + const { summary } = plex; const poster_path = plex.thumb; const background_path = plex.art; const added = translateAdded(plex.addedAt); diff --git a/src/plex/mailTemplate.js b/src/plex/mailTemplate.js index 64d38a9..fa0a355 100644 --- a/src/plex/mailTemplate.js +++ b/src/plex/mailTemplate.js @@ -1,25 +1,25 @@ class mailTemplate { - constructor(mediaItem) { - this.mediaItem = mediaItem; - this.posterURL = 'https://image.tmdb.org/t/p/w600'; - } + constructor(mediaItem) { + this.mediaItem = mediaItem; + this.posterURL = "https://image.tmdb.org/t/p/w600"; + } - toText() { - return `${this.mediaItem.title} (${this.mediaItem.year})`; // plain text body - } + toText() { + return `${this.mediaItem.title} (${this.mediaItem.year})`; // plain text body + } - toHTML() { - const info = { - name: this.mediaItem.title, - year: `(${this.mediaItem.year})`, - poster: this.posterURL + this.mediaItem.poster, - }; + toHTML() { + const info = { + name: this.mediaItem.title, + year: `(${this.mediaItem.year})`, + poster: this.posterURL + this.mediaItem.poster + }; - return ` + return `

${info.name} ${info.year}

`; - } + } } module.exports = mailTemplate; diff --git a/src/plex/plex.js b/src/plex/plex.js index 159fd00..9108dcb 100644 --- a/src/plex/plex.js +++ b/src/plex/plex.js @@ -11,23 +11,22 @@ const sanitize = string => string.toLowerCase().replace(/[^\w]/gi, ""); function fixedEncodeURIComponent(str) { return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { - return "%" + c.charCodeAt(0).toString(16).toUpperCase(); + return `%${c.charCodeAt(0).toString(16).toUpperCase()}`; }); } const matchingTitleAndYear = (plex, tmdb) => { - let matchingTitle, matchingYear; + let matchingTitle; + let matchingYear; - if (plex["title"] != null && tmdb["title"] != null) { + if (plex.title != null && tmdb.title != null) { const plexTitle = sanitize(plex.title); const tmdbTitle = sanitize(tmdb.title); matchingTitle = plexTitle == tmdbTitle; - matchingTitle = matchingTitle - ? matchingTitle - : plexTitle.startsWith(tmdbTitle); + matchingTitle = matchingTitle || plexTitle.startsWith(tmdbTitle); } else matchingTitle = false; - if (plex["year"] != null && tmdb["year"] != null) + if (plex.year != null && tmdb.year != null) matchingYear = plex.year == tmdb.year; else matchingYear = false; @@ -35,12 +34,12 @@ const matchingTitleAndYear = (plex, tmdb) => { }; const successfullResponse = response => { - if (response && response["MediaContainer"]) return response; + if (response && response.MediaContainer) return response; if ( response == null || - response["status"] == null || - response["statusText"] == null + response.status == null || + response.statusText == null ) { throw Error("Unable to decode response"); } @@ -49,9 +48,8 @@ const successfullResponse = response => { if (status === 200) { return response.json(); - } else { - throw { message: statusText, status: status }; } + throw { message: statusText, status }; }; class Plex { @@ -77,13 +75,13 @@ class Plex { return new Promise((resolve, reject) => this.cache .get(cacheKey) - .then(machineInfo => resolve(machineInfo["machineIdentifier"])) + .then(machineInfo => resolve(machineInfo.machineIdentifier)) .catch(() => fetch(url, options)) .then(response => response.json()) .then(machineInfo => - this.cache.set(cacheKey, machineInfo["MediaContainer"], 2628000) + this.cache.set(cacheKey, machineInfo.MediaContainer, 2628000) ) - .then(machineInfo => resolve(machineInfo["machineIdentifier"])) + .then(machineInfo => resolve(machineInfo.machineIdentifier)) .catch(error => { if (error != undefined && error.type === "request-timeout") { reject({ @@ -104,7 +102,7 @@ class Plex { if (plex == null || tmdb == null) return false; if (plex instanceof Array) { - let possibleMatches = plex.map(plexItem => + const possibleMatches = plex.map(plexItem => matchingTitleAndYear(plexItem, tmdb) ); match = possibleMatches.includes(true); @@ -120,7 +118,7 @@ class Plex { tmdb.title, tmdb.year ); - return plexMatch ? true : false; + return !!plexMatch; } findPlexItemByTitleAndYear(title, year) { @@ -149,7 +147,7 @@ class Plex { if ( matchingObjectInPlex == false || matchingObjectInPlex == null || - matchingObjectInPlex["key"] == null || + matchingObjectInPlex.key == null || machineIdentifier == null ) return false; @@ -227,9 +225,11 @@ class Plex { .map(category => { if (category.type === "movie") { return category.Metadata; - } else if (category.type === "show") { + } + if (category.type === "show") { return category.Metadata.map(convertPlexToShow); - } else if (category.type === "episode") { + } + if (category.type === "episode") { return category.Metadata.map(convertPlexToEpisode); } }) diff --git a/src/plex/plexRepository.js b/src/plex/plexRepository.js index 4433fa2..3bc29ac 100644 --- a/src/plex/plexRepository.js +++ b/src/plex/plexRepository.js @@ -1,6 +1,6 @@ +const rp = require("request-promise"); const convertPlexToSeasoned = require("./convertPlexToSeasoned"); const convertPlexToStream = require("./convertPlexToStream"); -const rp = require("request-promise"); class PlexRepository { constructor(plexIP) { @@ -24,7 +24,7 @@ class PlexRepository { `http://${this.plexIP}:32400/search?query=${queryUri}` ); const options = { - uri: uri, + uri, headers: { Accept: "application/json" }, diff --git a/src/plex/requestRepository.js b/src/plex/requestRepository.js index 357ad40..fcf480e 100644 --- a/src/plex/requestRepository.js +++ b/src/plex/requestRepository.js @@ -56,7 +56,7 @@ class RequestRepository { if (error) { throw new Error(error); } - tmdbMovie.requested = result ? true : false; + tmdbMovie.requested = !!result; return tmdbMovie; }); } @@ -98,7 +98,7 @@ class RequestRepository { type, page ]); - else return this.database.all(this.queries.fetchRequestedItems, page); + return this.database.all(this.queries.fetchRequestedItems, page); }); } diff --git a/src/plex/stream/convertStreamToPlayback.js b/src/plex/stream/convertStreamToPlayback.js index cdabee4..c07d439 100644 --- a/src/plex/stream/convertStreamToPlayback.js +++ b/src/plex/stream/convertStreamToPlayback.js @@ -1,14 +1,14 @@ class convertStreamToPlayback { - constructor(plexStream) { - this.bitrate = plexStream.bitrate; - this.width = plexStream.width; - this.height = plexStream.height; - this.decision = plexStream.decision; - this.audioProfile = plexStream.audioProfile; - this.videoProfile = plexStream.videoProfile; - this.duration = plexStream.duration; - this.container = plexStream.container; - } + constructor(plexStream) { + this.bitrate = plexStream.bitrate; + this.width = plexStream.width; + this.height = plexStream.height; + this.decision = plexStream.decision; + this.audioProfile = plexStream.audioProfile; + this.videoProfile = plexStream.videoProfile; + this.duration = plexStream.duration; + this.container = plexStream.container; + } } module.exports = convertStreamToPlayback; diff --git a/src/plex/types/episode.js b/src/plex/types/episode.js index a99fa8f..69ce4fe 100644 --- a/src/plex/types/episode.js +++ b/src/plex/types/episode.js @@ -8,9 +8,9 @@ class Episode { this.summary = null; this.rating = null; this.views = null; - this.aired = null; - this.type = 'episode'; + this.aired = null; + this.type = "episode"; } } -module.exports = Episode; \ No newline at end of file +module.exports = Episode; diff --git a/src/plex/types/movie.js b/src/plex/types/movie.js index 8a2b6fa..aa62ca6 100644 --- a/src/plex/types/movie.js +++ b/src/plex/types/movie.js @@ -5,8 +5,8 @@ class Movie { this.summary = null; this.rating = null; this.tagline = null; - this.type = 'movie'; + this.type = "movie"; } } -module.exports = Movie; \ No newline at end of file +module.exports = Movie; diff --git a/src/plex/types/show.js b/src/plex/types/show.js index 86c1ef4..426fd7c 100644 --- a/src/plex/types/show.js +++ b/src/plex/types/show.js @@ -9,4 +9,4 @@ class Show { } } -module.exports = Show; \ No newline at end of file +module.exports = Show; diff --git a/src/request/request.js b/src/request/request.js index 97afb05..14ca0dc 100644 --- a/src/request/request.js +++ b/src/request/request.js @@ -1,6 +1,7 @@ const assert = require("assert"); const configuration = require("../config/configuration").getInstance(); const TMDB = require("../tmdb/tmdb"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const establishedDatabase = require("../database/database"); const utils = require("./utils"); @@ -33,7 +34,7 @@ class RequestRepository { } sortAndFilterToDbQuery(by, direction, filter, query) { - let dbQuery = undefined; + let dbQuery; if (query !== undefined) { const dbParams = [query, query]; @@ -87,7 +88,7 @@ class RequestRepository { mapToTmdbByType(rows) { return rows.map(row => { if (row.type === "movie") return tmdb.movieInfo(row.id); - else if (row.type === "show") return tmdb.showInfo(row.id); + if (row.type === "show") return tmdb.showInfo(row.id); }); } @@ -189,9 +190,9 @@ class RequestRepository { .then(async rows => { const sqliteResponse = await this.database.get( fetchTotalResults, - filter ? filter : undefined + filter || undefined ); - const totalRequests = sqliteResponse["totalRequests"]; + const { totalRequests } = sqliteResponse; const totalPages = Math.ceil(totalRequests / 26); return [ @@ -211,7 +212,7 @@ class RequestRepository { Promise.resolve({ results: result, total_results: totalRequests, - page: page, + page, total_pages: totalPages }) ) diff --git a/src/request/utils.js b/src/request/utils.js index 0f92156..6cbe37a 100644 --- a/src/request/utils.js +++ b/src/request/utils.js @@ -1,34 +1,48 @@ // TODO : test title and date are valid matches to columns in the database -const validSortParams = ['title', 'date'] -const validSortDirs = ['asc', 'desc'] -const validFilterParams = ['movie', 'show', 'seeding', 'downloading', 'paused', 'finished', 'downloaded'] +const validSortParams = ["title", "date"]; +const validSortDirs = ["asc", "desc"]; +const validFilterParams = [ + "movie", + "show", + "seeding", + "downloading", + "paused", + "finished", + "downloaded" +]; function validSort(by, direction) { return new Promise((resolve, reject) => { if (by === undefined) { - resolve() + resolve(); } if (validSortParams.includes(by) && validSortDirs.includes(direction)) { - resolve() + resolve(); } else { - reject(new Error(`invalid sort parameter, must be of: ${validSortParams} with optional sort directions: ${validSortDirs} appended with ':'`)) + reject( + new Error( + `invalid sort parameter, must be of: ${validSortParams} with optional sort directions: ${validSortDirs} appended with ':'` + ) + ); } }); } function validFilter(filter_param) { return new Promise((resolve, reject) => { - if (filter_param === undefined) { - resolve() + if (filter_param === undefined) { + resolve(); } if (filter_param && validFilterParams.includes(filter_param)) { - resolve() + resolve(); } else { - reject(new Error(`filter parameteres must be of type: ${validFilterParams}`)) + reject( + new Error(`filter parameteres must be of type: ${validFilterParams}`) + ); } }); } -module.exports = { validSort, validFilter } \ No newline at end of file +module.exports = { validSort, validFilter }; diff --git a/src/seasoned/stray.js b/src/seasoned/stray.js index f33e2ac..c2620fa 100644 --- a/src/seasoned/stray.js +++ b/src/seasoned/stray.js @@ -1,7 +1,7 @@ class Stray { - constructor(id) { - this.id = id; - } + constructor(id) { + this.id = id; + } } module.exports = Stray; diff --git a/src/seasoned/strayRepository.js b/src/seasoned/strayRepository.js index 8474295..9239736 100644 --- a/src/seasoned/strayRepository.js +++ b/src/seasoned/strayRepository.js @@ -1,7 +1,7 @@ const assert = require("assert"); +const pythonShell = require("python-shell"); const Stray = require("./stray"); const establishedDatabase = require("../database/database"); -const pythonShell = require("python-shell"); class StrayRepository { constructor(database) { diff --git a/src/tmdb/tmdb.js b/src/tmdb/tmdb.js index d549d0e..9110167 100644 --- a/src/tmdb/tmdb.js +++ b/src/tmdb/tmdb.js @@ -5,11 +5,11 @@ const { Movie, Show, Person, Credits, ReleaseDates } = require("./types"); const tmdbErrorResponse = (error, typeString = undefined) => { if (error.status === 404) { - let message = error.response.body.status_message; + const message = error.response.body.status_message; throw { status: 404, - message: message.slice(0, -1) + " in tmdb." + message: `${message.slice(0, -1)} in tmdb.` }; } else if (error.status === 401) { throw { @@ -221,7 +221,7 @@ class TMDB { } movieList(listname, page = 1) { - const query = { page: page }; + const query = { page }; const cacheKey = `tmdb/${this.cacheTags[listname]}:${page}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, listname, query) @@ -230,7 +230,7 @@ class TMDB { } showList(listname, page = 1) { - const query = { page: page }; + const query = { page }; const cacheKey = `tmdb/${this.cacheTags[listname]}:${page}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query) @@ -245,21 +245,23 @@ class TMDB { * @returns {Promise} dict with tmdb results, mapped as movie/show objects. */ mapResults(response, type = undefined) { - let results = response.results.map(result => { + const results = response.results.map(result => { if (type === "movie" || result.media_type === "movie") { const movie = Movie.convertFromTmdbResponse(result); return movie.createJsonResponse(); - } else if (type === "show" || result.media_type === "tv") { + } + if (type === "show" || result.media_type === "tv") { const show = Show.convertFromTmdbResponse(result); return show.createJsonResponse(); - } else if (type === "person" || result.media_type === "person") { + } + if (type === "person" || result.media_type === "person") { const person = Person.convertFromTmdbResponse(result); return person.createJsonResponse(); } }); return { - results: results, + results, page: response.page, total_results: response.total_results, total_pages: response.total_pages diff --git a/src/tmdb/types.js b/src/tmdb/types.js index 0c7ae23..f3a831a 100644 --- a/src/tmdb/types.js +++ b/src/tmdb/types.js @@ -1,7 +1,7 @@ -const Movie = require('./types/movie.js') -const Show = require('./types/show.js') -const Person = require('./types/person.js') -const Credits = require('./types/credits.js') -const ReleaseDates = require('./types/releaseDates.js') +const Movie = require("./types/movie.js"); +const Show = require("./types/show.js"); +const Person = require("./types/person.js"); +const Credits = require("./types/credits.js"); +const ReleaseDates = require("./types/releaseDates.js"); -module.exports = { Movie, Show, Person, Credits, ReleaseDates } +module.exports = { Movie, Show, Person, Credits, ReleaseDates }; diff --git a/src/tmdb/types/credits.js b/src/tmdb/types/credits.js index 0c47e51..b32a557 100644 --- a/src/tmdb/types/credits.js +++ b/src/tmdb/types/credits.js @@ -13,10 +13,11 @@ class Credits { const { id, cast, crew } = response; const allCast = cast.map(cast => { - if (cast["media_type"]) { + if (cast.media_type) { if (cast.media_type === "movie") { return CreditedMovie.convertFromTmdbResponse(cast); - } else if (cast.media_type === "tv") { + } + if (cast.media_type === "tv") { return CreditedShow.convertFromTmdbResponse(cast); } } @@ -31,10 +32,11 @@ class Credits { }); const allCrew = crew.map(crew => { - if (cast["media_type"]) { + if (cast.media_type) { if (cast.media_type === "movie") { return CreditedMovie.convertFromTmdbResponse(cast); - } else if (cast.media_type === "tv") { + } + if (cast.media_type === "tv") { return CreditedShow.convertFromTmdbResponse(cast); } } diff --git a/src/tmdb/types/movie.js b/src/tmdb/types/movie.js index 4663245..09b5816 100644 --- a/src/tmdb/types/movie.js +++ b/src/tmdb/types/movie.js @@ -1,7 +1,20 @@ class Movie { - constructor(id, title, year=undefined, overview=undefined, poster=undefined, backdrop=undefined, - releaseDate=undefined, rating=undefined, genres=undefined, productionStatus=undefined, - tagline=undefined, runtime=undefined, imdb_id=undefined, popularity=undefined) { + constructor( + id, + title, + year = undefined, + overview = undefined, + poster = undefined, + backdrop = undefined, + releaseDate = undefined, + rating = undefined, + genres = undefined, + productionStatus = undefined, + tagline = undefined, + runtime = undefined, + imdb_id = undefined, + popularity = undefined + ) { this.id = id; this.title = title; this.year = year; @@ -16,27 +29,66 @@ class Movie { this.runtime = runtime; this.imdb_id = imdb_id; this.popularity = popularity; - this.type = 'movie'; + this.type = "movie"; } static convertFromTmdbResponse(response) { - const { id, title, release_date, overview, poster_path, backdrop_path, vote_average, genres, status, - tagline, runtime, imdb_id, popularity } = response; + const { + id, + title, + release_date, + overview, + poster_path, + backdrop_path, + vote_average, + genres, + status, + tagline, + runtime, + imdb_id, + popularity + } = response; const releaseDate = new Date(release_date); const year = releaseDate.getFullYear(); - const genreNames = genres ? genres.map(g => g.name) : undefined + const genreNames = genres ? genres.map(g => g.name) : undefined; - return new Movie(id, title, year, overview, poster_path, backdrop_path, releaseDate, vote_average, genreNames, status, - tagline, runtime, imdb_id, popularity) + return new Movie( + id, + title, + year, + overview, + poster_path, + backdrop_path, + releaseDate, + vote_average, + genreNames, + status, + tagline, + runtime, + imdb_id, + popularity + ); } static convertFromPlexResponse(response) { // console.log('response', response) const { title, year, rating, tagline, summary } = response; - const _ = undefined + const _ = undefined; - return new Movie(null, title, year, summary, _, _, _, rating, _, _, tagline) + return new Movie( + null, + title, + year, + summary, + _, + _, + _, + rating, + _, + _, + tagline + ); } createJsonResponse() { @@ -55,7 +107,7 @@ class Movie { runtime: this.runtime, imdb_id: this.imdb_id, type: this.type - } + }; } } diff --git a/src/tmdb/types/releaseDates.js b/src/tmdb/types/releaseDates.js index 340479e..02b6a4a 100644 --- a/src/tmdb/types/releaseDates.js +++ b/src/tmdb/types/releaseDates.js @@ -1,4 +1,4 @@ -class ReleaseDates { +class ReleaseDates { constructor(id, releases) { this.id = id; this.releases = releases; @@ -7,24 +7,35 @@ class ReleaseDates { static convertFromTmdbResponse(response) { const { id, results } = response; - const releases = results.map(countryRelease => - new Release( - countryRelease.iso_3166_1, - countryRelease.release_dates.map(rd => new ReleaseDate(rd.certification, rd.iso_639_1, rd.release_date, rd.type, rd.note)) - )) + const releases = results.map( + countryRelease => + new Release( + countryRelease.iso_3166_1, + countryRelease.release_dates.map( + rd => + new ReleaseDate( + rd.certification, + rd.iso_639_1, + rd.release_date, + rd.type, + rd.note + ) + ) + ) + ); - return new ReleaseDates(id, releases) + return new ReleaseDates(id, releases); } createJsonResponse() { return { id: this.id, results: this.releases.map(release => release.createJsonResponse()) - } + }; } } -class Release { +class Release { constructor(country, releaseDates) { this.country = country; this.releaseDates = releaseDates; @@ -33,8 +44,10 @@ class Release { createJsonResponse() { return { country: this.country, - release_dates: this.releaseDates.map(releaseDate => releaseDate.createJsonResponse()) - } + release_dates: this.releaseDates.map(releaseDate => + releaseDate.createJsonResponse() + ) + }; } } @@ -49,19 +62,18 @@ class ReleaseDate { releaseTypeLookup(releaseTypeKey) { const releaseTypeEnum = { - 1: 'Premier', - 2: 'Limited theatrical', - 3: 'Theatrical', - 4: 'Digital', - 5: 'Physical', - 6: 'TV' - } + 1: "Premier", + 2: "Limited theatrical", + 3: "Theatrical", + 4: "Digital", + 5: "Physical", + 6: "TV" + }; if (releaseTypeKey <= Object.keys(releaseTypeEnum).length) { - return releaseTypeEnum[releaseTypeKey] - } else { - // TODO log | Release type not defined, does this need updating? - return null + return releaseTypeEnum[releaseTypeKey]; } + // TODO log | Release type not defined, does this need updating? + return null; } createJsonResponse() { @@ -71,7 +83,7 @@ class ReleaseDate { release_date: this.releaseDate, type: this.type, note: this.note - } + }; } } diff --git a/src/tmdb/types/show.js b/src/tmdb/types/show.js index 176c59a..995a4de 100644 --- a/src/tmdb/types/show.js +++ b/src/tmdb/types/show.js @@ -1,7 +1,18 @@ class Show { - constructor(id, title, year=undefined, overview=undefined, poster=undefined, backdrop=undefined, - seasons=undefined, episodes=undefined, rank=undefined, genres=undefined, status=undefined, - runtime=undefined) { + constructor( + id, + title, + year = undefined, + overview = undefined, + poster = undefined, + backdrop = undefined, + seasons = undefined, + episodes = undefined, + rank = undefined, + genres = undefined, + status = undefined, + runtime = undefined + ) { this.id = id; this.title = title; this.year = year; @@ -14,18 +25,44 @@ class Show { this.genres = genres; this.productionStatus = status; this.runtime = runtime; - this.type = 'show'; + this.type = "show"; } static convertFromTmdbResponse(response) { - const { id, name, first_air_date, overview, poster_path, backdrop_path, number_of_seasons, number_of_episodes, - rank, genres, status, episode_run_time, popularity } = response; + const { + id, + name, + first_air_date, + overview, + poster_path, + backdrop_path, + number_of_seasons, + number_of_episodes, + rank, + genres, + status, + episode_run_time, + popularity + } = response; - const year = new Date(first_air_date).getFullYear() - const genreNames = genres ? genres.map(g => g.name) : undefined + const year = new Date(first_air_date).getFullYear(); + const genreNames = genres ? genres.map(g => g.name) : undefined; - return new Show(id, name, year, overview, poster_path, backdrop_path, number_of_seasons, number_of_episodes, - rank, genreNames, status, episode_run_time, popularity) + return new Show( + id, + name, + year, + overview, + poster_path, + backdrop_path, + number_of_seasons, + number_of_episodes, + rank, + genreNames, + status, + episode_run_time, + popularity + ); } createJsonResponse() { @@ -43,7 +80,7 @@ class Show { production_status: this.productionStatus, runtime: this.runtime, type: this.type - } + }; } } diff --git a/src/user/token.js b/src/user/token.js index d99baac..3f80aad 100644 --- a/src/user/token.js +++ b/src/user/token.js @@ -1,5 +1,5 @@ -const User = require("./user"); const jwt = require("jsonwebtoken"); +const User = require("./user"); class Token { constructor(user, admin = false, settings = null) { @@ -16,8 +16,8 @@ class Token { toString(secret) { const { user, admin, settings } = this; - let data = { username: user.username, settings }; - if (admin) data["admin"] = admin; + const data = { username: user.username, settings }; + if (admin) data.admin = admin; return jwt.sign(data, secret, { expiresIn: "90d" }); } diff --git a/src/user/user.js b/src/user/user.js index bdf326a..0c24602 100644 --- a/src/user/user.js +++ b/src/user/user.js @@ -1,8 +1,8 @@ class User { - constructor(username, email=undefined) { - this.username = username; - this.email = email; - } + constructor(username, email = undefined) { + this.username = username; + this.email = email; + } } module.exports = User; diff --git a/src/webserver/app.js b/src/webserver/app.js index 270c9ff..e184f5c 100644 --- a/src/webserver/app.js +++ b/src/webserver/app.js @@ -59,7 +59,7 @@ router.get("/", (req, res) => { app.use(Raven.errorHandler()); app.use((err, req, res, next) => { res.statusCode = 500; - res.end(res.sentry + "\n"); + res.end(`${res.sentry}\n`); }); /** @@ -68,6 +68,7 @@ app.use((err, req, res, next) => { router.post("/v1/user", require("./controllers/user/register.js")); router.post("/v1/user/login", require("./controllers/user/login.js")); router.post("/v1/user/logout", require("./controllers/user/logout.js")); + router.get( "/v1/user/settings", mustBeAuthenticated, @@ -88,6 +89,7 @@ router.get( mustBeAuthenticated, require("./controllers/user/requests.js") ); + router.post( "/v1/user/link_plex", mustBeAuthenticated, diff --git a/src/webserver/controllers/list/listController.js b/src/webserver/controllers/list/listController.js index 9ec287e..9557099 100644 --- a/src/webserver/controllers/list/listController.js +++ b/src/webserver/controllers/list/listController.js @@ -1,5 +1,6 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); // there should be a translate function from query params to @@ -39,7 +40,8 @@ function fetchTmdbList(req, res, listname, type) { .movieList(listname, page) .then(listResponse => res.send(listResponse)) .catch(error => handleError(error, res)); - } else if (type === "show") { + } + if (type === "show") { return tmdb .showList(listname, page) .then(listResponse => res.send(listResponse)) diff --git a/src/webserver/controllers/movie/credits.js b/src/webserver/controllers/movie/credits.js index a33b2fa..f8ec6c1 100644 --- a/src/webserver/controllers/movie/credits.js +++ b/src/webserver/controllers/movie/credits.js @@ -17,12 +17,9 @@ const movieCreditsController = (req, res) => { } else { // TODO log unhandled errors console.log("caugth movie credits controller error", error); - res - .status(500) - .send({ - message: - "An unexpected error occured while requesting movie credits" - }); + res.status(500).send({ + message: "An unexpected error occured while requesting movie credits" + }); } }); }; diff --git a/src/webserver/controllers/movie/releaseDates.js b/src/webserver/controllers/movie/releaseDates.js index d8eb2e0..84bd43b 100644 --- a/src/webserver/controllers/movie/releaseDates.js +++ b/src/webserver/controllers/movie/releaseDates.js @@ -17,12 +17,9 @@ const movieReleaseDatesController = (req, res) => { } else { // TODO log unhandled errors : here our at tmdbReleaseError ? console.log("caugth release dates controller error", error); - res - .status(500) - .send({ - message: - "An unexpected error occured while requesting movie credits" - }); + res.status(500).send({ + message: "An unexpected error occured while requesting movie credits" + }); } }); }; diff --git a/src/webserver/controllers/person/credits.js b/src/webserver/controllers/person/credits.js index 91a79e5..19eb5c2 100644 --- a/src/webserver/controllers/person/credits.js +++ b/src/webserver/controllers/person/credits.js @@ -1,5 +1,6 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const personCreditsController = (req, res) => { diff --git a/src/webserver/controllers/person/info.js b/src/webserver/controllers/person/info.js index be1dad0..87c91ff 100644 --- a/src/webserver/controllers/person/info.js +++ b/src/webserver/controllers/person/info.js @@ -1,5 +1,6 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); function handleError(error, res) { @@ -31,7 +32,7 @@ async function personInfoController(req, res) { ? (credits = true) : (credits = false); - let tmdbQueue = [tmdb.personInfo(personId)]; + const tmdbQueue = [tmdb.personInfo(personId)]; if (credits) tmdbQueue.push(tmdb.personCredits(personId)); try { diff --git a/src/webserver/controllers/pirate/addMagnet.js b/src/webserver/controllers/pirate/addMagnet.js index 0ce38d0..7dfbbdd 100644 --- a/src/webserver/controllers/pirate/addMagnet.js +++ b/src/webserver/controllers/pirate/addMagnet.js @@ -8,9 +8,9 @@ const PirateRepository = require("../../../pirate/pirateRepository"); function addMagnet(req, res) { - const magnet = req.body.magnet; - const name = req.body.name; - const tmdb_id = req.body.tmdb_id; + const { magnet } = req.body; + const { name } = req.body; + const { tmdb_id } = req.body; PirateRepository.AddMagnet(magnet, name, tmdb_id) .then(result => { diff --git a/src/webserver/controllers/plex/hookDump.js b/src/webserver/controllers/plex/hookDump.js index 82d4e69..15682a0 100644 --- a/src/webserver/controllers/plex/hookDump.js +++ b/src/webserver/controllers/plex/hookDump.js @@ -1,12 +1,12 @@ /* -* @Author: KevinMidboe -* @Date: 2017-05-03 23:26:46 -* @Last Modified by: KevinMidboe -* @Last Modified time: 2018-02-06 20:54:22 -*/ + * @Author: KevinMidboe + * @Date: 2017-05-03 23:26:46 + * @Last Modified by: KevinMidboe + * @Last Modified time: 2018-02-06 20:54:22 + */ function hookDumpController(req, res) { - console.log(req); + console.log(req); } module.exports = hookDumpController; diff --git a/src/webserver/controllers/plex/readRequest.js b/src/webserver/controllers/plex/readRequest.js index db29647..04d8c98 100644 --- a/src/webserver/controllers/plex/readRequest.js +++ b/src/webserver/controllers/plex/readRequest.js @@ -9,7 +9,7 @@ const requestRepository = new RequestRepository(); * @returns {Callback} */ function readRequestController(req, res) { - const mediaId = req.params.mediaId; + const { mediaId } = req.params; const { type } = req.query; requestRepository .lookup(mediaId, type) diff --git a/src/webserver/controllers/plex/search.js b/src/webserver/controllers/plex/search.js index 0d7b577..50162e9 100644 --- a/src/webserver/controllers/plex/search.js +++ b/src/webserver/controllers/plex/search.js @@ -1,5 +1,6 @@ const configuration = require("../../../config/configuration").getInstance(); const Plex = require("../../../plex/plex"); + const plex = new Plex(configuration.get("plex", "ip")); /** @@ -16,12 +17,10 @@ function searchPlexController(req, res) { if (movies.length > 0) { res.send(movies); } else { - res - .status(404) - .send({ - success: false, - message: "Search query did not give any results from plex." - }); + res.status(404).send({ + success: false, + message: "Search query did not give any results from plex." + }); } }) .catch(error => { diff --git a/src/webserver/controllers/plex/searchMedia.js b/src/webserver/controllers/plex/searchMedia.js index c4d9698..d64cefe 100644 --- a/src/webserver/controllers/plex/searchMedia.js +++ b/src/webserver/controllers/plex/searchMedia.js @@ -19,12 +19,10 @@ function searchMediaController(req, res) { if (media !== undefined || media.length > 0) { res.send(media); } else { - res - .status(404) - .send({ - success: false, - message: "Search query did not return any results." - }); + res.status(404).send({ + success: false, + message: "Search query did not return any results." + }); } }) .catch(error => { diff --git a/src/webserver/controllers/plex/submitRequest.js b/src/webserver/controllers/plex/submitRequest.js index 2d78018..c06083a 100644 --- a/src/webserver/controllers/plex/submitRequest.js +++ b/src/webserver/controllers/plex/submitRequest.js @@ -1,6 +1,7 @@ const configuration = require("../../../config/configuration").getInstance(); const RequestRepository = require("../../../request/request"); const TMDB = require("../../../tmdb/tmdb"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const request = new RequestRepository(); @@ -26,7 +27,7 @@ function submitRequestController(req, res) { const user_agent = req.headers["user-agent"]; const username = req.loggedInUser ? req.loggedInUser.username : null; - let mediaFunction = undefined; + let mediaFunction; if (type === "movie") { console.log("movie"); diff --git a/src/webserver/controllers/plex/updateRequested.js b/src/webserver/controllers/plex/updateRequested.js index 3194a03..0fd4b18 100644 --- a/src/webserver/controllers/plex/updateRequested.js +++ b/src/webserver/controllers/plex/updateRequested.js @@ -10,8 +10,8 @@ const requestRepository = new RequestRepository(); */ function updateRequested(req, res) { const id = req.params.requestId; - const type = req.body.type; - const status = req.body.status; + const { type } = req.body; + const { status } = req.body; requestRepository .updateRequestedById(id, type, status) diff --git a/src/webserver/controllers/plex/watchDirectLink.js b/src/webserver/controllers/plex/watchDirectLink.js index a56f85d..13c4eb1 100644 --- a/src/webserver/controllers/plex/watchDirectLink.js +++ b/src/webserver/controllers/plex/watchDirectLink.js @@ -1,5 +1,6 @@ const configuration = require("../../../config/configuration").getInstance(); const Plex = require("../../../plex/plex"); + const plex = new Plex(configuration.get("plex", "ip")); /** diff --git a/src/webserver/controllers/request/fetchAllRequests.js b/src/webserver/controllers/request/fetchAllRequests.js index 7679169..c6f8ae2 100644 --- a/src/webserver/controllers/request/fetchAllRequests.js +++ b/src/webserver/controllers/request/fetchAllRequests.js @@ -1,4 +1,5 @@ const RequestRepository = require("../../../request/request"); + const request = new RequestRepository(); /** @@ -8,9 +9,9 @@ const request = new RequestRepository(); * @returns {Callback} */ function fetchAllRequests(req, res) { - let { page, filter, sort, query } = req.query; + const { page, filter, sort, query } = req.query; let sort_by = sort; - let sort_direction = undefined; + let sort_direction; if (sort !== undefined && sort.includes(":")) { [sort_by, sort_direction] = sort.split(":"); diff --git a/src/webserver/controllers/request/getRequest.js b/src/webserver/controllers/request/getRequest.js index 9167e95..ec79520 100644 --- a/src/webserver/controllers/request/getRequest.js +++ b/src/webserver/controllers/request/getRequest.js @@ -1,4 +1,5 @@ const RequestRepository = require("../../../request/request"); + const request = new RequestRepository(); /** @@ -8,7 +9,7 @@ const request = new RequestRepository(); * @returns {Callback} */ function fetchAllRequests(req, res) { - const id = req.params.id; + const { id } = req.params; const { type } = req.query; request diff --git a/src/webserver/controllers/request/requestTmdbId.js b/src/webserver/controllers/request/requestTmdbId.js index a4e6185..139e560 100644 --- a/src/webserver/controllers/request/requestTmdbId.js +++ b/src/webserver/controllers/request/requestTmdbId.js @@ -1,6 +1,7 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); const RequestRepository = require("../../../request/request"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const request = new RequestRepository(); // const { sendSMS } = require("src/notifications/sms"); @@ -26,7 +27,7 @@ function requestTmdbIdController(req, res) { const user_agent = req.headers["user-agent"]; const username = req.loggedInUser ? req.loggedInUser.username : null; - let mediaFunction = undefined; + let mediaFunction; if (id === undefined || type === undefined) { res.status(422).send({ diff --git a/src/webserver/controllers/search/movieSearch.js b/src/webserver/controllers/search/movieSearch.js index bfee6d1..3fa329d 100644 --- a/src/webserver/controllers/search/movieSearch.js +++ b/src/webserver/controllers/search/movieSearch.js @@ -1,6 +1,7 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); const SearchHistory = require("../../../searchHistory/searchHistory"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const searchHistory = new SearchHistory(); @@ -13,7 +14,7 @@ const searchHistory = new SearchHistory(); function movieSearchController(req, res) { const { query, page, adult } = req.query; const username = req.loggedInUser ? req.loggedInUser.username : null; - const includeAdult = adult == "true" ? true : false; + const includeAdult = adult == "true"; if (username) { searchHistory.create(username, query); diff --git a/src/webserver/controllers/search/multiSearch.js b/src/webserver/controllers/search/multiSearch.js index db977c7..5172612 100644 --- a/src/webserver/controllers/search/multiSearch.js +++ b/src/webserver/controllers/search/multiSearch.js @@ -1,11 +1,12 @@ -const configuration = require("../../..//config/configuration").getInstance(); +const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); const SearchHistory = require("../../../searchHistory/searchHistory"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const searchHistory = new SearchHistory(); function checkAndCreateJsonResponse(result) { - if (typeof result["createJsonResponse"] === "function") { + if (typeof result.createJsonResponse === "function") { return result.createJsonResponse(); } return result; diff --git a/src/webserver/controllers/search/personSearch.js b/src/webserver/controllers/search/personSearch.js index dbd11c1..4a3699f 100644 --- a/src/webserver/controllers/search/personSearch.js +++ b/src/webserver/controllers/search/personSearch.js @@ -1,6 +1,7 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); const SearchHistory = require("../../../searchHistory/searchHistory"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const searchHistory = new SearchHistory(); @@ -13,7 +14,7 @@ const searchHistory = new SearchHistory(); function personSearchController(req, res) { const { query, page, adult } = req.query; const username = req.loggedInUser ? req.loggedInUser.username : null; - const includeAdult = adult == "true" ? true : false; + const includeAdult = adult == "true"; if (username) { searchHistory.create(username, query); diff --git a/src/webserver/controllers/search/showSearch.js b/src/webserver/controllers/search/showSearch.js index cd420c4..2566010 100644 --- a/src/webserver/controllers/search/showSearch.js +++ b/src/webserver/controllers/search/showSearch.js @@ -1,6 +1,7 @@ const SearchHistory = require("../../../searchHistory/searchHistory"); const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const searchHistory = new SearchHistory(); @@ -13,7 +14,7 @@ const searchHistory = new SearchHistory(); function showSearchController(req, res) { const { query, page, adult } = req.query; const username = req.loggedInUser ? req.loggedInUser.username : null; - const includeAdult = adult == "true" ? true : false; + const includeAdult = adult == "true"; if (username) { searchHistory.create(username, query); diff --git a/src/webserver/controllers/show/credits.js b/src/webserver/controllers/show/credits.js index b7014a5..f381efd 100644 --- a/src/webserver/controllers/show/credits.js +++ b/src/webserver/controllers/show/credits.js @@ -1,5 +1,6 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const showCreditsController = (req, res) => { @@ -16,11 +17,9 @@ const showCreditsController = (req, res) => { } else { // TODO log unhandled errors console.log("caugth show credits controller error", error); - res - .status(500) - .send({ - message: "An unexpected error occured while requesting show credits" - }); + res.status(500).send({ + message: "An unexpected error occured while requesting show credits" + }); } }); }; diff --git a/src/webserver/controllers/show/info.js b/src/webserver/controllers/show/info.js index 322c381..9ae9e58 100644 --- a/src/webserver/controllers/show/info.js +++ b/src/webserver/controllers/show/info.js @@ -1,6 +1,7 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); const Plex = require("../../../plex/plex"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const plex = new Plex(configuration.get("plex", "ip")); @@ -35,7 +36,7 @@ async function showInfoController(req, res) { ? (check_existance = true) : (check_existance = false); - let tmdbQueue = [tmdb.showInfo(showId)]; + const tmdbQueue = [tmdb.showInfo(showId)]; if (credits) tmdbQueue.push(tmdb.showCredits(showId)); try { diff --git a/src/webserver/controllers/user/authenticatePlexAccount.js b/src/webserver/controllers/user/authenticatePlexAccount.js index 19a2749..4e5a09c 100644 --- a/src/webserver/controllers/user/authenticatePlexAccount.js +++ b/src/webserver/controllers/user/authenticatePlexAccount.js @@ -1,4 +1,5 @@ const UserRepository = require("../../../user/userRepository"); + const userRepository = new UserRepository(); const fetch = require("node-fetch"); const FormData = require("form-data"); diff --git a/src/webserver/controllers/user/login.js b/src/webserver/controllers/user/login.js index c0098ca..0438a89 100644 --- a/src/webserver/controllers/user/login.js +++ b/src/webserver/controllers/user/login.js @@ -27,7 +27,7 @@ const cookieOptions = { */ async function loginController(req, res) { const user = new User(req.body.username); - const password = req.body.password; + const { password } = req.body; try { const [loggedIn, isAdmin, settings] = await Promise.all([ @@ -43,11 +43,7 @@ async function loginController(req, res) { }); } - const token = new Token( - user, - isAdmin === 1 ? true : false, - settings - ).toString(secret); + const token = new Token(user, isAdmin === 1, settings).toString(secret); return res.cookie("authorization", token, cookieOptions).status(200).send({ success: true, diff --git a/src/webserver/controllers/user/register.js b/src/webserver/controllers/user/register.js index e3a5d71..2c36f4e 100644 --- a/src/webserver/controllers/user/register.js +++ b/src/webserver/controllers/user/register.js @@ -24,7 +24,7 @@ const cookieOptions = { */ function registerController(req, res) { const user = new User(req.body.username, req.body.email); - const password = req.body.password; + const { password } = req.body; userSecurity .createNewUser(user, password) diff --git a/src/webserver/controllers/user/settings.js b/src/webserver/controllers/user/settings.js index b69b322..caf55f8 100644 --- a/src/webserver/controllers/user/settings.js +++ b/src/webserver/controllers/user/settings.js @@ -1,4 +1,5 @@ const UserRepository = require("../../../user/userRepository"); + const userRepository = new UserRepository(); /** * Controller: Retrieves settings of a logged in user diff --git a/src/webserver/controllers/user/viewHistory.js b/src/webserver/controllers/user/viewHistory.js index 8a5334e..99725e5 100644 --- a/src/webserver/controllers/user/viewHistory.js +++ b/src/webserver/controllers/user/viewHistory.js @@ -1,5 +1,6 @@ const configuration = require("../../../config/configuration").getInstance(); const Tautulli = require("../../../tautulli/tautulli"); + const apiKey = configuration.get("tautulli", "apiKey"); const ip = configuration.get("tautulli", "ip"); const port = configuration.get("tautulli", "port"); @@ -10,12 +11,11 @@ function handleError(error, res) { if (status && message) { return res.status(status).send({ success: false, message }); - } else { - console.log("caught view history controller error", error); - return res.status(500).send({ - message: "An unexpected error occured while fetching view history" - }); } + console.log("caught view history controller error", error); + return res.status(500).send({ + message: "An unexpected error occured while fetching view history" + }); } function watchTimeStatsController(req, res) { diff --git a/src/webserver/middleware/mustBeAdmin.js b/src/webserver/middleware/mustBeAdmin.js index be516c6..4ee3bb6 100644 --- a/src/webserver/middleware/mustBeAdmin.js +++ b/src/webserver/middleware/mustBeAdmin.js @@ -1,29 +1,28 @@ const establishedDatabase = require("../../database/database"); const mustBeAdmin = (req, res, next) => { - let database = establishedDatabase; + const database = establishedDatabase; if (req.loggedInUser === undefined) { return res.status(401).send({ success: false, message: "You must be logged in." }); - } else { - database - .get( - `SELECT admin FROM user WHERE user_name IS ?`, - req.loggedInUser.username - ) - .then(isAdmin => { - console.log(isAdmin, req.loggedInUser); - if (isAdmin.admin == 0) { - return res.status(401).send({ - success: false, - message: "You must be logged in as a admin." - }); - } - }); } + database + .get( + `SELECT admin FROM user WHERE user_name IS ?`, + req.loggedInUser.username + ) + .then(isAdmin => { + console.log(isAdmin, req.loggedInUser); + if (isAdmin.admin == 0) { + return res.status(401).send({ + success: false, + message: "You must be logged in as a admin." + }); + } + }); return next(); }; diff --git a/src/webserver/middleware/mustHaveAccountLinkedToPlex.js b/src/webserver/middleware/mustHaveAccountLinkedToPlex.js index d3413d0..c1ce4a5 100644 --- a/src/webserver/middleware/mustHaveAccountLinkedToPlex.js +++ b/src/webserver/middleware/mustHaveAccountLinkedToPlex.js @@ -1,35 +1,33 @@ const establishedDatabase = require("../../database/database"); const mustHaveAccountLinkedToPlex = (req, res, next) => { - let database = establishedDatabase; - const loggedInUser = req.loggedInUser; + const database = establishedDatabase; + const { loggedInUser } = req; if (loggedInUser === undefined) { return res.status(401).send({ success: false, message: "You must have your account linked to a plex account." }); - } else { - database - .get( - `SELECT plex_userid FROM settings WHERE user_name IS ?`, - loggedInUser.username - ) - .then(row => { - const plex_userid = row.plex_userid; - - if (plex_userid === null || plex_userid === undefined) { - return res.status(403).send({ - success: false, - message: - "No plex account user id found for your user. Please authenticate your plex account at /user/authenticate." - }); - } else { - req.loggedInUser.plex_userid = plex_userid; - return next(); - } - }); } + database + .get( + `SELECT plex_userid FROM settings WHERE user_name IS ?`, + loggedInUser.username + ) + .then(row => { + const { plex_userid } = row; + + if (plex_userid === null || plex_userid === undefined) { + return res.status(403).send({ + success: false, + message: + "No plex account user id found for your user. Please authenticate your plex account at /user/authenticate." + }); + } + req.loggedInUser.plex_userid = plex_userid; + return next(); + }); }; module.exports = mustHaveAccountLinkedToPlex; -- 2.34.1 From e8ad9367c978a851ae888ec8b23c6983e8aa2b78 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Fri, 19 Aug 2022 10:49:58 +0200 Subject: [PATCH 02/26] fix: updated plex_userid to camelcase --- src/tautulli/tautulli.js | 16 ++++++++-------- src/webserver/controllers/user/viewHistory.js | 8 ++++---- .../middleware/mustHaveAccountLinkedToPlex.js | 6 +++--- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/tautulli/tautulli.js b/src/tautulli/tautulli.js index 3ac47bc..85adc6d 100644 --- a/src/tautulli/tautulli.js +++ b/src/tautulli/tautulli.js @@ -22,10 +22,10 @@ class Tautulli { throw error; } - getPlaysByDayOfWeek(plex_userid, days, y_axis) { + getPlaysByDayOfWeek(plexUserId, days, y_axis) { const url = this.buildUrlWithCmdAndUserid( "get_plays_by_dayofweek", - plex_userid + plexUserId ); url.searchParams.append("time_range", days); url.searchParams.append("y_axis", y_axis); @@ -35,8 +35,8 @@ class Tautulli { .catch(error => this.logTautulliError(error)); } - getPlaysByDays(plex_userid, days, y_axis) { - const url = this.buildUrlWithCmdAndUserid("get_plays_by_date", plex_userid); + getPlaysByDays(plexUserId, days, y_axis) { + const url = this.buildUrlWithCmdAndUserid("get_plays_by_date", plexUserId); url.searchParams.append("time_range", days); url.searchParams.append("y_axis", y_axis); @@ -45,10 +45,10 @@ class Tautulli { .catch(error => this.logTautulliError(error)); } - watchTimeStats(plex_userid) { + watchTimeStats(plexUserId) { const url = this.buildUrlWithCmdAndUserid( "get_user_watch_time_stats", - plex_userid + plexUserId ); url.searchParams.append("grouping", 0); @@ -57,8 +57,8 @@ class Tautulli { .catch(error => this.logTautulliError(error)); } - viewHistory(plex_userid) { - const url = this.buildUrlWithCmdAndUserid("get_history", plex_userid); + viewHistory(plexUserId) { + const url = this.buildUrlWithCmdAndUserid("get_history", plexUserId); url.searchParams.append("start", 0); url.searchParams.append("length", 50); diff --git a/src/webserver/controllers/user/viewHistory.js b/src/webserver/controllers/user/viewHistory.js index 99725e5..55b3077 100644 --- a/src/webserver/controllers/user/viewHistory.js +++ b/src/webserver/controllers/user/viewHistory.js @@ -22,7 +22,7 @@ function watchTimeStatsController(req, res) { const user = req.loggedInUser; return tautulli - .watchTimeStats(user.plex_userid) + .watchTimeStats(user.plexUserId) .then(data => { return res.send({ success: true, @@ -38,7 +38,7 @@ function getPlaysByDayOfWeekController(req, res) { const { days, y_axis } = req.query; return tautulli - .getPlaysByDayOfWeek(user.plex_userid, days, y_axis) + .getPlaysByDayOfWeek(user.plexUserId, days, y_axis) .then(data => res.send({ success: true, @@ -69,7 +69,7 @@ function getPlaysByDaysController(req, res) { } return tautulli - .getPlaysByDays(user.plex_userid, days, y_axis) + .getPlaysByDays(user.plexUserId, days, y_axis) .then(data => res.send({ success: true, @@ -86,7 +86,7 @@ function userViewHistoryController(req, res) { // and then return 501 Not implemented return tautulli - .viewHistory(user.plex_userid) + .viewHistory(user.plexUserId) .then(data => { return res.send({ success: true, diff --git a/src/webserver/middleware/mustHaveAccountLinkedToPlex.js b/src/webserver/middleware/mustHaveAccountLinkedToPlex.js index c1ce4a5..d7006d8 100644 --- a/src/webserver/middleware/mustHaveAccountLinkedToPlex.js +++ b/src/webserver/middleware/mustHaveAccountLinkedToPlex.js @@ -16,16 +16,16 @@ const mustHaveAccountLinkedToPlex = (req, res, next) => { loggedInUser.username ) .then(row => { - const { plex_userid } = row; + const plexUserId = row?.plex_userid; - if (plex_userid === null || plex_userid === undefined) { + if (plexUserId === null || plexUserId === undefined) { return res.status(403).send({ success: false, message: "No plex account user id found for your user. Please authenticate your plex account at /user/authenticate." }); } - req.loggedInUser.plex_userid = plex_userid; + req.loggedInUser.plexUserId = plexUserId; return next(); }); }; -- 2.34.1 From a98797088a05d66bcc5cf68cdae255da68c70549 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Fri, 19 Aug 2022 11:22:29 +0200 Subject: [PATCH 03/26] Linted and some consistency refactor on middleware --- src/webserver/middleware/mustBeAdmin.js | 11 +++++---- .../middleware/mustBeAuthenticated.js | 4 +++- .../middleware/mustHaveAccountLinkedToPlex.js | 13 ++++++---- src/webserver/middleware/reqTokenToUser.js | 24 ++++++++----------- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/webserver/middleware/mustBeAdmin.js b/src/webserver/middleware/mustBeAdmin.js index 4ee3bb6..50e9c71 100644 --- a/src/webserver/middleware/mustBeAdmin.js +++ b/src/webserver/middleware/mustBeAdmin.js @@ -1,30 +1,31 @@ const establishedDatabase = require("../../database/database"); +// eslint-disable-next-line consistent-return const mustBeAdmin = (req, res, next) => { const database = establishedDatabase; if (req.loggedInUser === undefined) { - return res.status(401).send({ + res.status(401).send({ success: false, message: "You must be logged in." }); } + database .get( `SELECT admin FROM user WHERE user_name IS ?`, req.loggedInUser.username ) .then(isAdmin => { - console.log(isAdmin, req.loggedInUser); - if (isAdmin.admin == 0) { + if (isAdmin.admin === 0) { return res.status(401).send({ success: false, message: "You must be logged in as a admin." }); } - }); - return next(); + return next(); + }); }; module.exports = mustBeAdmin; diff --git a/src/webserver/middleware/mustBeAuthenticated.js b/src/webserver/middleware/mustBeAuthenticated.js index 6af925b..9a470db 100644 --- a/src/webserver/middleware/mustBeAuthenticated.js +++ b/src/webserver/middleware/mustBeAuthenticated.js @@ -1,3 +1,4 @@ +// eslint-disable-next-line consistent-return const mustBeAuthenticated = (req, res, next) => { if (req.loggedInUser === undefined) { return res.status(401).send({ @@ -5,7 +6,8 @@ const mustBeAuthenticated = (req, res, next) => { message: "You must be logged in." }); } - return next(); + + next(); }; module.exports = mustBeAuthenticated; diff --git a/src/webserver/middleware/mustHaveAccountLinkedToPlex.js b/src/webserver/middleware/mustHaveAccountLinkedToPlex.js index d7006d8..49e4849 100644 --- a/src/webserver/middleware/mustHaveAccountLinkedToPlex.js +++ b/src/webserver/middleware/mustHaveAccountLinkedToPlex.js @@ -1,33 +1,36 @@ const establishedDatabase = require("../../database/database"); +/* eslint-disable consistent-return */ const mustHaveAccountLinkedToPlex = (req, res, next) => { const database = establishedDatabase; const { loggedInUser } = req; - if (loggedInUser === undefined) { + if (loggedInUser === null) { return res.status(401).send({ success: false, message: "You must have your account linked to a plex account." }); } + database .get( `SELECT plex_userid FROM settings WHERE user_name IS ?`, loggedInUser.username ) .then(row => { - const plexUserId = row?.plex_userid; - - if (plexUserId === null || plexUserId === undefined) { + const plexUserId = row.plex_userid; + if (plexUserId === null) { return res.status(403).send({ success: false, message: "No plex account user id found for your user. Please authenticate your plex account at /user/authenticate." }); } + req.loggedInUser.plexUserId = plexUserId; - return next(); + next(); }); }; +/* eslint-enable consistent-return */ module.exports = mustHaveAccountLinkedToPlex; diff --git a/src/webserver/middleware/reqTokenToUser.js b/src/webserver/middleware/reqTokenToUser.js index 0b92cef..bde99f6 100644 --- a/src/webserver/middleware/reqTokenToUser.js +++ b/src/webserver/middleware/reqTokenToUser.js @@ -11,22 +11,18 @@ const reqTokenToUser = (req, res, next) => { const cookieAuthToken = req.cookies.authorization; const headerAuthToken = req.headers.authorization; - if (cookieAuthToken || headerAuthToken) { - try { - const token = Token.fromString( - cookieAuthToken || headerAuthToken, - secret - ); - req.loggedInUser = token.user; - } catch (error) { - req.loggedInUser = undefined; - } - } else { - // guest session - console.debug("No auth token in header or cookie."); + if (!(cookieAuthToken || headerAuthToken)) { + return next(); } - next(); + try { + const token = Token.fromString(cookieAuthToken || headerAuthToken, secret); + req.loggedInUser = token.user; + } catch (error) { + req.loggedInUser = null; + } + + return next(); }; module.exports = reqTokenToUser; -- 2.34.1 From 64dbec1f145c1d4bb11cf83aba8fa253508f2442 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Fri, 19 Aug 2022 13:45:50 +0200 Subject: [PATCH 04/26] eslint uses ecmaversion 2020 & allow empty catch rule --- .eslintrc.json | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index 9bbe884..e64f9ff 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,13 +1,17 @@ { "root": true, "parserOptions": { + "ecmaVersion": 2020, "sourceType": "module" }, - "extends": [ - "eslint-config-airbnb-base", - "plugin:prettier/recommended" - ], + "extends": ["eslint-config-airbnb-base", "plugin:prettier/recommended"], "rules": { + "no-empty": [ + 2, + { + "allowEmptyCatch": true + } + ], "no-underscore-dangle": "off", "no-shadow": "off" } -- 2.34.1 From b1d959389d77bdc24c42a507f377911f5db241f6 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Fri, 19 Aug 2022 13:47:08 +0200 Subject: [PATCH 05/26] Started linting source files --- src/cache/redis.js | 11 +- src/config/configuration.js | 2 +- src/config/field.js | 4 +- src/database/sqliteDatabase.js | 5 +- src/media_classes/plex.js | 2 + src/media_classes/tmdb.js | 2 + src/notifications/sms.js | 13 +- src/pirate/pirateRepository.js | 14 +- src/plex/convertPlexToSeasoned.js | 3 +- src/plex/hookDump.js | 7 - src/plex/plex.js | 43 ++-- src/plex/requestRepository.js | 4 +- src/request/request.js | 99 ++------- src/request/utils.js | 6 +- src/searchHistory/searchHistory.js | 39 ++-- src/tautulli/tautulli.js | 29 ++- src/tmdb/tmdb.js | 95 ++++++--- src/tmdb/types.js | 10 +- src/tmdb/types.ts | 2 +- src/tmdb/types/credits.js | 103 +++++----- src/tmdb/types/movie.js | 2 + src/tmdb/types/person.js | 2 + src/tmdb/types/releaseDates.js | 106 +++++----- src/tmdb/types/show.js | 2 + src/user/userRepository.js | 48 ++--- src/user/userSecurity.js | 4 +- src/webserver/app.js | 86 ++++---- src/webserver/controllers/git/dumpHook.js | 8 +- .../controllers/list/listController.js | 7 +- src/webserver/controllers/movie/credits.js | 2 - src/webserver/controllers/movie/info.js | 40 ++-- .../controllers/movie/releaseDates.js | 2 - src/webserver/controllers/person/credits.js | 2 - src/webserver/controllers/person/info.js | 8 +- src/webserver/controllers/pirate/addMagnet.js | 11 +- .../controllers/plex/fetchRequested.js | 2 +- src/webserver/controllers/plex/hookDump.js | 12 +- .../controllers/plex/searchRequest.js | 6 +- .../controllers/plex/submitRequest.js | 6 +- .../controllers/plex/watchDirectLink.js | 2 +- .../controllers/request/fetchAllRequests.js | 12 +- .../controllers/request/requestTmdbId.js | 4 +- .../controllers/search/movieSearch.js | 4 +- .../controllers/search/multiSearch.js | 12 +- .../controllers/search/personSearch.js | 4 +- .../controllers/search/showSearch.js | 2 +- src/webserver/controllers/show/credits.js | 2 - src/webserver/controllers/show/info.js | 19 +- .../user/authenticatePlexAccount.js | 33 +-- src/webserver/controllers/user/register.js | 2 - src/webserver/controllers/user/requests.js | 2 +- src/webserver/controllers/user/settings.js | 7 +- src/webserver/controllers/user/viewHistory.js | 14 +- ...ade_runner_2049-info-success-response.json | 90 +++++++- ...rstellar-query-movie-success-response.json | 194 +++++++++++++++++- 55 files changed, 726 insertions(+), 526 deletions(-) delete mode 100644 src/plex/hookDump.js diff --git a/src/cache/redis.js b/src/cache/redis.js index 340d884..9318a31 100644 --- a/src/cache/redis.js +++ b/src/cache/redis.js @@ -1,4 +1,3 @@ -const { promisify } = require("util"); const configuration = require("../config/configuration").getInstance(); let client; @@ -16,7 +15,7 @@ try { client.on("connect", () => console.log("Redis connection established!")); - client.on("error", function (err) { + client.on("error", () => { client.quit(); console.error("Unable to connect to redis, setting up redis-mock."); @@ -38,7 +37,7 @@ function set(key, value, TTL = 10800) { const json = JSON.stringify(value); client.set(key, json, (error, reply) => { - if (reply == "OK") { + if (reply === "OK") { // successfully set value with key, now set TTL for key client.expire(key, TTL, e => { if (e) @@ -55,14 +54,14 @@ function set(key, value, TTL = 10800) { return value; } -function get() { +function get(key) { return new Promise((resolve, reject) => { client.get(key, (error, reply) => { - if (reply == null) { + if (reply === null) { return reject(); } - resolve(JSON.parse(reply)); + return resolve(JSON.parse(reply)); }); }); } diff --git a/src/config/configuration.js b/src/config/configuration.js index 0414dc4..9b9a192 100644 --- a/src/config/configuration.js +++ b/src/config/configuration.js @@ -1,5 +1,5 @@ const path = require("path"); -const Field = require("./field.js"); +const Field = require("./field"); let instance = null; diff --git a/src/config/field.js b/src/config/field.js index 546513b..4b86c80 100644 --- a/src/config/field.js +++ b/src/config/field.js @@ -1,5 +1,5 @@ -const Filters = require("./filters.js"); -const EnvironmentVariables = require("./environmentVariables.js"); +const Filters = require("./filters"); +const EnvironmentVariables = require("./environmentVariables"); class Field { constructor(rawValue, environmentVariables) { diff --git a/src/database/sqliteDatabase.js b/src/database/sqliteDatabase.js index a330487..a6f8e53 100644 --- a/src/database/sqliteDatabase.js +++ b/src/database/sqliteDatabase.js @@ -72,12 +72,11 @@ class SqliteDatabase { /** * Run a SQL query against the database and retrieve the status. * @param {String} sql SQL query - * @param {Array} parameters in the SQL query * @returns {Promise} */ execute(sql) { - return new Promise(resolve => { - this.connection.exec(sql, (err, database) => { + return new Promise((resolve, reject) => { + this.connection.exec(sql, err => { if (err) { console.log("ERROR: ", err); reject(err); diff --git a/src/media_classes/plex.js b/src/media_classes/plex.js index 2df0f77..2626e39 100644 --- a/src/media_classes/plex.js +++ b/src/media_classes/plex.js @@ -1,3 +1,5 @@ +/* eslint-disable camelcase */ + const Media = require("./media"); class Plex extends Media { diff --git a/src/media_classes/tmdb.js b/src/media_classes/tmdb.js index 724ac86..63a0c40 100644 --- a/src/media_classes/tmdb.js +++ b/src/media_classes/tmdb.js @@ -1,3 +1,5 @@ +/* eslint-disable camelcase */ + const Media = require("./media"); class TMDB extends Media { diff --git a/src/notifications/sms.js b/src/notifications/sms.js index a56587f..a8c80d7 100644 --- a/src/notifications/sms.js +++ b/src/notifications/sms.js @@ -1,6 +1,15 @@ const request = require("request"); const configuration = require("../config/configuration").getInstance(); +class SMSUnexpectedError extends Error { + constructor(errorMessage) { + const message = "Unexpected error from sms provider."; + super(message); + + this.errorMessage = errorMessage; + } +} + const sendSMS = message => { const apiKey = configuration.get("sms", "apikey"); @@ -24,8 +33,8 @@ const sendSMS = message => { } }, function (err, r, body) { - console.log(err || body); - console.log("sms provider response:", body); + const smsError = new SMSUnexpectedError(err || body); + console.error(smsError.message); resolve(); } ); diff --git a/src/pirate/pirateRepository.js b/src/pirate/pirateRepository.js index 70a030c..455ad0a 100644 --- a/src/pirate/pirateRepository.js +++ b/src/pirate/pirateRepository.js @@ -1,4 +1,3 @@ -const assert = require("assert"); const http = require("http"); const { URL } = require("url"); const PythonShell = require("python-shell"); @@ -8,12 +7,12 @@ const establishedDatabase = require("../database/database"); const cache = require("../cache/redis"); function getMagnetFromURL(url) { - return new Promise((resolve, reject) => { + return new Promise(resolve => { const options = new URL(url); if (options.protocol.includes("magnet")) resolve(url); http.get(options, res => { - if (res.statusCode == 301 || res.statusCode == 302) { + if (res.statusCode === 301 || res.statusCode === 302) { resolve(res.headers.location); } }); @@ -43,7 +42,6 @@ async function callPythonAddMagnet(url, callback) { PythonShell.run("deluge_cli.py", options, callback); }) .catch(err => { - console.log(err); throw new Error(err); }); } @@ -76,7 +74,7 @@ async function SearchPiratebay(query) { ); } -async function AddMagnet(magnet, name, tmdb_id) { +async function AddMagnet(magnet, name, tmdbId) { return await new Promise((resolve, reject) => callPythonAddMagnet(magnet, (err, results) => { if (err) { @@ -87,12 +85,12 @@ async function AddMagnet(magnet, name, tmdb_id) { /* eslint-disable no-console */ console.log("result/error:", err, results); - database = establishedDatabase; - insert_query = + const database = establishedDatabase; + const insert_query = "INSERT INTO requested_torrent(magnet,torrent_name,tmdb_id) \ VALUES (?,?,?)"; - const response = database.run(insert_query, [magnet, name, tmdb_id]); + const response = database.run(insert_query, [magnet, name, tmdbId]); console.log(`Response from requsted_torrent insert: ${response}`); resolve({ success: true }); diff --git a/src/plex/convertPlexToSeasoned.js b/src/plex/convertPlexToSeasoned.js index 40f1dcc..d216c23 100644 --- a/src/plex/convertPlexToSeasoned.js +++ b/src/plex/convertPlexToSeasoned.js @@ -1,3 +1,5 @@ +/* eslint-disable camelcase */ + const Plex = require("../media_classes/plex"); function translateAdded(date_string) { @@ -27,7 +29,6 @@ function convertPlexToSeasoned(plex) { seasons, episodes ); - // seasoned.print(); return seasoned; } diff --git a/src/plex/hookDump.js b/src/plex/hookDump.js deleted file mode 100644 index 5a34b2e..0000000 --- a/src/plex/hookDump.js +++ /dev/null @@ -1,7 +0,0 @@ -const configuration = require("../config/configuration").getInstance(); - -function hookDumpController(req, res) { - console.log(req); -} - -module.exports = hookDumpController; diff --git a/src/plex/plex.js b/src/plex/plex.js index 9108dcb..628c862 100644 --- a/src/plex/plex.js +++ b/src/plex/plex.js @@ -3,8 +3,6 @@ const convertPlexToMovie = require("./convertPlexToMovie"); const convertPlexToShow = require("./convertPlexToShow"); const convertPlexToEpisode = require("./convertPlexToEpisode"); -const { Movie, Show, Person } = require("../tmdb/types"); - const redisCache = require("../cache/redis"); const sanitize = string => string.toLowerCase().replace(/[^\w]/gi, ""); @@ -19,15 +17,14 @@ const matchingTitleAndYear = (plex, tmdb) => { let matchingTitle; let matchingYear; - if (plex.title != null && tmdb.title != null) { + if (plex?.title && tmdb?.title) { const plexTitle = sanitize(plex.title); const tmdbTitle = sanitize(tmdb.title); - matchingTitle = plexTitle == tmdbTitle; + matchingTitle = plexTitle === tmdbTitle; matchingTitle = matchingTitle || plexTitle.startsWith(tmdbTitle); } else matchingTitle = false; - if (plex.year != null && tmdb.year != null) - matchingYear = plex.year == tmdb.year; + if (plex?.year && tmdb?.year) matchingYear = plex.year === tmdb.year; else matchingYear = false; return matchingTitle && matchingYear; @@ -37,9 +34,9 @@ const successfullResponse = response => { if (response && response.MediaContainer) return response; if ( - response == null || - response.status == null || - response.statusText == null + response === null || + response.status === null || + response.statusText === null ) { throw Error("Unable to decode response"); } @@ -83,7 +80,7 @@ class Plex { ) .then(machineInfo => resolve(machineInfo.machineIdentifier)) .catch(error => { - if (error != undefined && error.type === "request-timeout") { + if (error !== undefined && error.type === "request-timeout") { reject({ message: "Plex did not respond", status: 408, @@ -99,7 +96,7 @@ class Plex { matchTmdbAndPlexMedia(plex, tmdb) { let match; - if (plex == null || tmdb == null) return false; + if (plex === null || tmdb === null) return false; if (plex instanceof Array) { const possibleMatches = plex.map(plexItem => @@ -129,7 +126,7 @@ class Plex { this.matchTmdbAndPlexMedia(plex, query) ); const matchesIndex = matchesInPlex.findIndex(el => el === true); - return matchesInPlex != -1 ? plexResults[matchesIndex] : null; + return matchesInPlex !== -1 ? plexResults[matchesIndex] : null; }); } @@ -145,10 +142,10 @@ class Plex { matchingObjectInPlexPromise ]).then(([machineIdentifier, matchingObjectInPlex]) => { if ( - matchingObjectInPlex == false || - matchingObjectInPlex == null || - matchingObjectInPlex.key == null || - machineIdentifier == null + matchingObjectInPlex === false || + matchingObjectInPlex === null || + matchingObjectInPlex.key === null || + machineIdentifier === null ) return false; @@ -177,7 +174,7 @@ class Plex { .then(this.mapResults) .then(resolve) .catch(error => { - if (error != undefined && error.type === "request-timeout") { + if (error !== undefined && error.type === "request-timeout") { reject({ message: "Plex did not respond", status: 408, @@ -202,7 +199,7 @@ class Plex { cacheKey, (error, response => { - if (response == 1) return true; + if (response === 1) return true; // TODO improve cache key matching by lowercasing it on the backend. // what do we actually need to check for if the key was deleted or not @@ -213,11 +210,7 @@ class Plex { } mapResults(response) { - if ( - response == null || - response.MediaContainer == null || - response.MediaContainer.Hub == null - ) { + if (response?.MediaContainer?.Hub === null) { return []; } @@ -232,8 +225,10 @@ class Plex { if (category.type === "episode") { return category.Metadata.map(convertPlexToEpisode); } + + return null; }) - .filter(result => result !== undefined); + .filter(result => result !== null); } } diff --git a/src/plex/requestRepository.js b/src/plex/requestRepository.js index fcf480e..8a01d5f 100644 --- a/src/plex/requestRepository.js +++ b/src/plex/requestRepository.js @@ -66,7 +66,7 @@ class RequestRepository { * @param {identifier, type} the id of the media object and type of media must be defined * @returns {Promise} If nothing has gone wrong. */ - sendRequest(identifier, type, ip, user_agent, user) { + sendRequest(identifier, type, ip, userAgent, user) { return Promise.resolve() .then(() => tmdb.lookup(identifier, type)) .then(movie => { @@ -80,7 +80,7 @@ class RequestRepository { movie.background_path, username, ip, - user_agent, + userAgent, movie.type ]); }); diff --git a/src/request/request.js b/src/request/request.js index 14ca0dc..922e933 100644 --- a/src/request/request.js +++ b/src/request/request.js @@ -4,7 +4,6 @@ const TMDB = require("../tmdb/tmdb"); const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const establishedDatabase = require("../database/database"); -const utils = require("./utils"); class RequestRepository { constructor(database) { @@ -19,76 +18,23 @@ class RequestRepository { 'select count(*) as totalRequests from requests where status != "downloaded"', totalRequestsFilteredStatus: "select count(*) as totalRequests from requests where status = ?", - fetchAllSort: `select id, type from request order by ? ?`, - fetchAllFilter: `select id, type from request where ? is "?"`, - fetchAllQuery: `select id, type from request where title like "%?%" or year like "%?%"`, - fetchAllFilterAndSort: `select id, type from request where ? is "?" order by ? ?`, - downloaded: - "(select status from requests where id is request.id and type is request.type limit 1)", + // fetchAllSort: `select id, type from request order by ? ?`, + // fetchAllFilter: `select id, type from request where ? is "?"`, + // fetchAllQuery: `select id, type from request where title like "%?%" or year like "%?%"`, + // fetchAllFilterAndSort: `select id, type from request where ? is "?" order by ? ?`, + // downloaded: "(select status from requests where id is request.id and type is request.type limit 1)", // deluge: '(select status from deluge_torrent where id is request.id and type is request.type limit 1)', // fetchAllFilterStatus: 'select * from request where ' - readWithoutUserData: - "select id, title, year, type, status, date from requests where id is ? and type is ?", + // readWithoutUserData: "select id, title, year, type, status, date from requests where id is ? and type is ?", read: "select id, title, year, type, status, requested_by, ip, date, user_agent from requests where id is ? and type is ?" }; } - sortAndFilterToDbQuery(by, direction, filter, query) { - let dbQuery; - - if (query !== undefined) { - const dbParams = [query, query]; - const dbquery = this.queries.fetchAllQuery; - - dbQuery = dbquery - .split("") - .map(char => (char === "?" ? dbParams.shift() : char)) - .join(""); - } else if (by !== undefined && filter !== undefined) { - const paramToColumnAndValue = { - movie: ["type", "movie"], - show: ["type", "show"] - }; - const dbParams = paramToColumnAndValue[filter].concat([by, direction]); - const query = this.queries.fetchAllFilterAndSort; - - dbQuery = query - .split("") - .map(char => (char === "?" ? dbParams.shift() : char)) - .join(""); - } else if (by !== undefined) { - const dbParams = [by, direction]; - const query = this.queries.fetchAllSort; - - dbQuery = query - .split("") - .map(char => (char === "?" ? dbParams.shift() : char)) - .join(""); - } else if (filter !== undefined) { - const paramToColumnAndValue = { - movie: ["type", "movie"], - show: ["type", "show"], - downloaded: [this.queries.downloaded, "downloaded"] - // downloading: [this.database.delugeStatus, 'downloading'] - }; - const dbParams = paramToColumnAndValue[filter]; - const query = this.queries.fetchAllFilter; - - dbQuery = query - .split("") - .map(char => (char === "?" ? dbParams.shift() : char)) - .join(""); - } else { - dbQuery = this.queries.fetchAll; - } - - return dbQuery; - } - mapToTmdbByType(rows) { return rows.map(row => { if (row.type === "movie") return tmdb.movieInfo(row.id); if (row.type === "show") return tmdb.showInfo(row.id); + return null; }); } @@ -97,7 +43,7 @@ class RequestRepository { * @param {tmdb} tmdb class of movie|show to add * @returns {Promise} */ - requestFromTmdb(tmdb, ip, user_agent, username) { + requestFromTmdb(tmdb, ip, userAgent, username) { return Promise.resolve() .then(() => this.database.get(this.queries.read, [tmdb.id, tmdb.type])) .then(row => @@ -112,7 +58,7 @@ class RequestRepository { tmdb.backdrop, username, ip, - user_agent, + userAgent, tmdb.type ]) ) @@ -153,20 +99,12 @@ class RequestRepository { /** * Fetch all requests with optional sort and filter params * @param {String} what we are sorting by - * @param {String} direction that can be either 'asc' or 'desc', default 'asc'. * @param {String} params to filter by - * @param {String} query param to filter result on. Filters on title and year * @returns {Promise} */ - fetchAll( - page = 1, - sort_by = undefined, - sort_direction = "asc", - filter = undefined, - query = undefined - ) { + fetchAll(_page = 1, filter = null) { // TODO implemented sort and filter - page = parseInt(page); + const page = parseInt(_page); let fetchQuery = this.queries.fetchAll; let fetchTotalResults = this.queries.totalRequests; let fetchParams = [page]; @@ -177,26 +115,24 @@ class RequestRepository { filter === "downloaded" || filter === "requested") ) { - console.log("tes"); fetchQuery = this.queries.fetchAllFilteredStatus; fetchTotalResults = this.queries.totalRequestsFilteredStatus; fetchParams = [filter, page]; - } else { - filter = undefined; } - return Promise.resolve() - .then(dbQuery => this.database.all(fetchQuery, fetchParams)) + return this.database + .all(fetchQuery, fetchParams) .then(async rows => { const sqliteResponse = await this.database.get( fetchTotalResults, - filter || undefined + filter || null ); const { totalRequests } = sqliteResponse; const totalPages = Math.ceil(totalRequests / 26); return [ - rows.map(item => { + rows.map(_item => { + const item = _item; item.poster = item.poster_path; delete item.poster_path; item.backdrop = item.background_path; @@ -206,7 +142,8 @@ class RequestRepository { totalPages, totalRequests ]; - return Promise.all(this.mapToTmdbByType(rows)); + + return this.mapToTmdbByType(rows); }) .then(([result, totalPages, totalRequests]) => Promise.resolve({ diff --git a/src/request/utils.js b/src/request/utils.js index 6cbe37a..67756c0 100644 --- a/src/request/utils.js +++ b/src/request/utils.js @@ -29,13 +29,13 @@ function validSort(by, direction) { }); } -function validFilter(filter_param) { +function validFilter(filterParam) { return new Promise((resolve, reject) => { - if (filter_param === undefined) { + if (filterParam === undefined) { resolve(); } - if (filter_param && validFilterParams.includes(filter_param)) { + if (filterParam && validFilterParams.includes(filterParam)) { resolve(); } else { reject( diff --git a/src/searchHistory/searchHistory.js b/src/searchHistory/searchHistory.js index 15fdcb1..9c25380 100644 --- a/src/searchHistory/searchHistory.js +++ b/src/searchHistory/searchHistory.js @@ -1,5 +1,15 @@ const establishedDatabase = require("../database/database"); +class SearchHistoryCreateDatabaseError extends Error { + constructor(message = "an unexpected error occured", errorResponse = null) { + super(message); + + this.source = "database"; + this.statusCode = 500; + this.errorResponse = errorResponse; + } +} + class SearchHistory { constructor(database) { this.database = database || establishedDatabase; @@ -16,18 +26,12 @@ class SearchHistory { * @returns {Promise} */ read(user) { - return new Promise((resolve, reject) => - this.database - .all(this.queries.read, user) - .then((result, error) => { - if (error) throw new Error(error); - resolve(result.map(row => row.search_query)); - }) - .catch(error => { - console.log("Error when fetching history from database:", error); - reject("Unable to get history."); - }) - ); + return this.database + .all(this.queries.read, user) + .then(result => result.map(row => row.search_query)) + .catch(error => { + throw new Error("Unable to get history.", error); + }); } /** @@ -41,15 +45,12 @@ class SearchHistory { .run(this.queries.create, [searchQuery, username]) .catch(error => { if (error.message.includes("FOREIGN")) { - throw new Error("Could not create search history."); + throw new SearchHistoryCreateDatabaseError( + "Could not create search history." + ); } - throw { - success: false, - status: 500, - message: "An unexpected error occured", - source: "database" - }; + throw new SearchHistoryCreateDatabaseError(); }); } } diff --git a/src/tautulli/tautulli.js b/src/tautulli/tautulli.js index 85adc6d..cccd8a7 100644 --- a/src/tautulli/tautulli.js +++ b/src/tautulli/tautulli.js @@ -1,5 +1,15 @@ const fetch = require("node-fetch"); +class TautulliUnexpectedError extends Error { + constructor(errorMessage) { + const message = "Unexpected error fetching from tautulli."; + super(message); + + this.statusCode = 500; + this.errorMessage = errorMessage; + } +} + class Tautulli { constructor(apiKey, ip, port) { this.apiKey = apiKey; @@ -7,38 +17,37 @@ class Tautulli { this.port = port; } - buildUrlWithCmdAndUserid(cmd, user_id) { + buildUrlWithCmdAndUserid(cmd, userId) { const url = new URL("api/v2", `http://${this.ip}:${this.port}`); url.searchParams.append("apikey", this.apiKey); url.searchParams.append("cmd", cmd); - url.searchParams.append("user_id", user_id); + url.searchParams.append("user_id", userId); return url; } + /* eslint-disable-next-line class-methods-use-this */ logTautulliError(error) { - console.error("error fetching from tautulli"); - - throw error; + throw new TautulliUnexpectedError(error); } - getPlaysByDayOfWeek(plexUserId, days, y_axis) { + getPlaysByDayOfWeek(plexUserId, days, yAxis) { const url = this.buildUrlWithCmdAndUserid( "get_plays_by_dayofweek", plexUserId ); url.searchParams.append("time_range", days); - url.searchParams.append("y_axis", y_axis); + url.searchParams.append("y_axis", yAxis); return fetch(url.href) .then(resp => resp.json()) .catch(error => this.logTautulliError(error)); } - getPlaysByDays(plexUserId, days, y_axis) { + getPlaysByDays(plexUserId, days, yAxis) { const url = this.buildUrlWithCmdAndUserid("get_plays_by_date", plexUserId); url.searchParams.append("time_range", days); - url.searchParams.append("y_axis", y_axis); + url.searchParams.append("y_axis", yAxis); return fetch(url.href) .then(resp => resp.json()) @@ -63,8 +72,6 @@ class Tautulli { url.searchParams.append("start", 0); url.searchParams.append("length", 50); - console.log("fetching url", url.href); - return fetch(url.href) .then(resp => resp.json()) .catch(error => this.logTautulliError(error)); diff --git a/src/tmdb/tmdb.js b/src/tmdb/tmdb.js index 9110167..bddb86f 100644 --- a/src/tmdb/tmdb.js +++ b/src/tmdb/tmdb.js @@ -3,25 +3,41 @@ const redisCache = require("../cache/redis"); const { Movie, Show, Person, Credits, ReleaseDates } = require("./types"); -const tmdbErrorResponse = (error, typeString = undefined) => { +class TMDBNotFoundError extends Error { + constructor(message) { + super(message); + + this.statusCode = 404; + } +} + +class TMDBUnauthorizedError extends Error { + constructor(message = "TMDB returned access denied, requires api token.") { + super(message); + + this.statusCode = 401; + } +} + +class TMDBUnexpectedError extends Error { + constructor(type) { + const message = `An unexpected error occured while fetching ${type} from tmdb`; + super(message); + + this.statusCode = 500; + } +} + +const tmdbErrorResponse = (error, type = null) => { if (error.status === 404) { const message = error.response.body.status_message; - throw { - status: 404, - message: `${message.slice(0, -1)} in tmdb.` - }; + throw new TMDBNotFoundError(`${message.slice(0, -1)} in tmdb.`); } else if (error.status === 401) { - throw { - status: 401, - message: error.response.body.status_message - }; + throw new TMDBUnauthorizedError(error?.response?.body?.status_message); } - throw { - status: 500, - message: `An unexpected error occured while fetching ${typeString} from tmdb` - }; + throw new TMDBUnexpectedError(type); }; class TMDB { @@ -166,9 +182,9 @@ class TMDB { .then(credits => Credits.convertFromTmdbResponse(credits)); } - multiSearch(search_query, page = 1, include_adult = true) { - const query = { query: search_query, page, include_adult }; - const cacheKey = `tmdb/${this.cacheTags.multiSearch}:${page}:${search_query}:${include_adult}`; + multiSearch(searchQuery, page = 1, includeAdult = true) { + const query = { query: searchQuery, page, include_adult: includeAdult }; + const cacheKey = `tmdb/${this.cacheTags.multiSearch}:${page}:${searchQuery}:${includeAdult}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, "searchMulti", query) .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) @@ -181,9 +197,13 @@ class TMDB { * @param {Number} page representing pagination of results * @returns {Promise} dict with query results, current page and total_pages */ - movieSearch(search_query, page = 1, include_adult = true) { - const tmdbquery = { query: search_query, page, include_adult }; - const cacheKey = `tmdb/${this.cacheTags.movieSearch}:${page}:${search_query}:${include_adult}`; + movieSearch(searchQuery, page = 1, includeAdult = true) { + const tmdbquery = { + query: searchQuery, + page, + include_adult: includeAdult + }; + const cacheKey = `tmdb/${this.cacheTags.movieSearch}:${page}:${searchQuery}:${includeAdult}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, "searchMovie", tmdbquery) .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) @@ -196,9 +216,13 @@ class TMDB { * @param {Number} page representing pagination of results * @returns {Promise} dict with query results, current page and total_pages */ - showSearch(search_query, page = 1, include_adult = true) { - const tmdbquery = { query: search_query, page, include_adult }; - const cacheKey = `tmdb/${this.cacheTags.showSearch}:${page}:${search_query}:${include_adult}`; + showSearch(searchQuery, page = 1, includeAdult = true) { + const tmdbquery = { + query: searchQuery, + page, + include_adult: includeAdult + }; + const cacheKey = `tmdb/${this.cacheTags.showSearch}:${page}:${searchQuery}:${includeAdult}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, "searchTv", tmdbquery) .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) @@ -211,27 +235,31 @@ class TMDB { * @param {Number} page representing pagination of results * @returns {Promise} dict with query results, current page and total_pages */ - personSearch(search_query, page = 1, include_adult = true) { - const tmdbquery = { query: search_query, page, include_adult }; - const cacheKey = `tmdb/${this.cacheTags.personSearch}:${page}:${search_query}:${include_adult}`; + personSearch(searchQuery, page = 1, includeAdult = true) { + const tmdbquery = { + query: searchQuery, + page, + include_adult: includeAdult + }; + const cacheKey = `tmdb/${this.cacheTags.personSearch}:${page}:${searchQuery}:${includeAdult}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, "searchPerson", tmdbquery) .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) .then(response => this.mapResults(response, "person")); } - movieList(listname, page = 1) { + movieList(listName, page = 1) { const query = { page }; - const cacheKey = `tmdb/${this.cacheTags[listname]}:${page}`; + const cacheKey = `tmdb/${this.cacheTags[listName]}:${page}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, listname, query) + return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query) .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) .then(response => this.mapResults(response, "movie")); } - showList(listname, page = 1) { + showList(listName, page = 1) { const query = { page }; - const cacheKey = `tmdb/${this.cacheTags[listname]}:${page}`; + const cacheKey = `tmdb/${this.cacheTags[listName]}:${page}`; return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query) .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) @@ -244,8 +272,9 @@ class TMDB { * @param {String} The type declared in listSearch. * @returns {Promise} dict with tmdb results, mapped as movie/show objects. */ + // eslint-disable-next-line class-methods-use-this mapResults(response, type = undefined) { - const results = response.results.map(result => { + const results = response?.results?.map(result => { if (type === "movie" || result.media_type === "movie") { const movie = Movie.convertFromTmdbResponse(result); return movie.createJsonResponse(); @@ -258,6 +287,8 @@ class TMDB { const person = Person.convertFromTmdbResponse(result); return person.createJsonResponse(); } + + return {}; }); return { @@ -280,7 +311,7 @@ class TMDB { if (error) { return reject(error); } - resolve(reponse); + return resolve(reponse); }; if (!argument) { diff --git a/src/tmdb/types.js b/src/tmdb/types.js index f3a831a..cbf5cbc 100644 --- a/src/tmdb/types.js +++ b/src/tmdb/types.js @@ -1,7 +1,7 @@ -const Movie = require("./types/movie.js"); -const Show = require("./types/show.js"); -const Person = require("./types/person.js"); -const Credits = require("./types/credits.js"); -const ReleaseDates = require("./types/releaseDates.js"); +const Movie = require("./types/movie"); +const Show = require("./types/show"); +const Person = require("./types/person"); +const Credits = require("./types/credits"); +const ReleaseDates = require("./types/releaseDates"); module.exports = { Movie, Show, Person, Credits, ReleaseDates }; diff --git a/src/tmdb/types.ts b/src/tmdb/types.ts index 89e2f8a..e079157 100644 --- a/src/tmdb/types.ts +++ b/src/tmdb/types.ts @@ -61,4 +61,4 @@ interface Genre { name: string; } -export { Movie, Show, Person, Genre } +export { Movie, Show, Person, Genre }; diff --git a/src/tmdb/types/credits.js b/src/tmdb/types/credits.js index b32a557..8740b6d 100644 --- a/src/tmdb/types/credits.js +++ b/src/tmdb/types/credits.js @@ -1,5 +1,55 @@ -import Movie from "./movie"; -import Show from "./show"; +/* eslint-disable camelcase */ +const Movie = require("./movie"); +const Show = require("./show"); + +class CreditedMovie extends Movie {} +class CreditedShow extends Show {} + +class CastMember { + constructor(character, gender, id, name, profile_path) { + this.character = character; + this.gender = gender; + this.id = id; + this.name = name; + this.profile_path = profile_path; + this.type = "person"; + } + + createJsonResponse() { + return { + character: this.character, + gender: this.gender, + id: this.id, + name: this.name, + profile_path: this.profile_path, + type: this.type + }; + } +} + +class CrewMember { + constructor(department, gender, id, job, name, profile_path) { + this.department = department; + this.gender = gender; + this.id = id; + this.job = job; + this.name = name; + this.profile_path = profile_path; + this.type = "person"; + } + + createJsonResponse() { + return { + department: this.department, + gender: this.gender, + id: this.id, + job: this.job, + name: this.name, + profile_path: this.profile_path, + type: this.type + }; + } +} class Credits { constructor(id, cast = [], crew = []) { @@ -63,53 +113,4 @@ class Credits { } } -class CastMember { - constructor(character, gender, id, name, profile_path) { - this.character = character; - this.gender = gender; - this.id = id; - this.name = name; - this.profile_path = profile_path; - this.type = "person"; - } - - createJsonResponse() { - return { - character: this.character, - gender: this.gender, - id: this.id, - name: this.name, - profile_path: this.profile_path, - type: this.type - }; - } -} - -class CrewMember { - constructor(department, gender, id, job, name, profile_path) { - this.department = department; - this.gender = gender; - this.id = id; - this.job = job; - this.name = name; - this.profile_path = profile_path; - this.type = "person"; - } - - createJsonResponse() { - return { - department: this.department, - gender: this.gender, - id: this.id, - job: this.job, - name: this.name, - profile_path: this.profile_path, - type: this.type - }; - } -} - -class CreditedMovie extends Movie {} -class CreditedShow extends Show {} - module.exports = Credits; diff --git a/src/tmdb/types/movie.js b/src/tmdb/types/movie.js index 09b5816..db78856 100644 --- a/src/tmdb/types/movie.js +++ b/src/tmdb/types/movie.js @@ -1,3 +1,5 @@ +/* eslint-disable camelcase */ + class Movie { constructor( id, diff --git a/src/tmdb/types/person.js b/src/tmdb/types/person.js index 67ca569..2cd24d9 100644 --- a/src/tmdb/types/person.js +++ b/src/tmdb/types/person.js @@ -1,3 +1,5 @@ +/* eslint-disable camelcase */ + class Person { constructor( id, diff --git a/src/tmdb/types/releaseDates.js b/src/tmdb/types/releaseDates.js index 02b6a4a..94ffa31 100644 --- a/src/tmdb/types/releaseDates.js +++ b/src/tmdb/types/releaseDates.js @@ -1,3 +1,57 @@ +const releaseTypeEnum = { + 1: "Premier", + 2: "Limited theatrical", + 3: "Theatrical", + 4: "Digital", + 5: "Physical", + 6: "TV" +}; + +class Release { + constructor(country, releaseDates) { + this.country = country; + this.releaseDates = releaseDates; + } + + createJsonResponse() { + return { + country: this.country, + release_dates: this.releaseDates.map(releaseDate => + releaseDate.createJsonResponse() + ) + }; + } +} + +class ReleaseDate { + constructor(certification, language, releaseDate, type, note) { + this.certification = certification; + this.language = language; + this.releaseDate = releaseDate; + this.type = this.releaseTypeLookup(type); + this.note = note; + } + + static releaseTypeLookup(releaseTypeKey) { + if (releaseTypeKey <= Object.keys(releaseTypeEnum).length) { + return releaseTypeEnum[releaseTypeKey]; + } + + // TODO log | Release type not defined, does this need updating? + return null; + } + + createJsonResponse() { + return { + certification: this.certification, + language: this.language, + release_date: this.releaseDate, + type: this.type, + note: this.note + }; + } +} + class ReleaseDates { constructor(id, releases) { this.id = id; @@ -35,56 +89,4 @@ class ReleaseDates { } } -class Release { - constructor(country, releaseDates) { - this.country = country; - this.releaseDates = releaseDates; - } - - createJsonResponse() { - return { - country: this.country, - release_dates: this.releaseDates.map(releaseDate => - releaseDate.createJsonResponse() - ) - }; - } -} - -class ReleaseDate { - constructor(certification, language, releaseDate, type, note) { - this.certification = certification; - this.language = language; - this.releaseDate = releaseDate; - this.type = this.releaseTypeLookup(type); - this.note = note; - } - - releaseTypeLookup(releaseTypeKey) { - const releaseTypeEnum = { - 1: "Premier", - 2: "Limited theatrical", - 3: "Theatrical", - 4: "Digital", - 5: "Physical", - 6: "TV" - }; - if (releaseTypeKey <= Object.keys(releaseTypeEnum).length) { - return releaseTypeEnum[releaseTypeKey]; - } - // TODO log | Release type not defined, does this need updating? - return null; - } - - createJsonResponse() { - return { - certification: this.certification, - language: this.language, - release_date: this.releaseDate, - type: this.type, - note: this.note - }; - } -} - module.exports = ReleaseDates; diff --git a/src/tmdb/types/show.js b/src/tmdb/types/show.js index 995a4de..cbbf434 100644 --- a/src/tmdb/types/show.js +++ b/src/tmdb/types/show.js @@ -1,3 +1,5 @@ +/* eslint-disable camelcase */ + class Show { constructor( id, diff --git a/src/user/userRepository.js b/src/user/userRepository.js index 4f9683c..6022f48 100644 --- a/src/user/userRepository.js +++ b/src/user/userRepository.js @@ -51,8 +51,7 @@ class UserRepository { assert(row, "The user does not exist."); return row.password; }) - .catch(err => { - console.log(error); + .catch(() => { throw new Error("Unable to find your user."); }); } @@ -78,17 +77,14 @@ class UserRepository { this.database .run(this.queries.link, [plexUserID, username]) .then(row => resolve(row)) - .catch(error => { - // TODO log this unknown db error - console.error("db error", error); - + .catch(error => reject({ status: 500, message: "An unexpected error occured while linking plex and seasoned accounts", source: "seasoned database" - }); - }); + }) + ); }); } @@ -102,17 +98,14 @@ class UserRepository { this.database .run(this.queries.unlink, username) .then(row => resolve(row)) - .catch(error => { - // TODO log this unknown db error - console.log("db error", error); - + .catch(error => reject({ status: 500, message: "An unexpected error occured while unlinking plex and seasoned accounts", source: "seasoned database" - }); - }); + }) + ); }); } @@ -162,18 +155,14 @@ class UserRepository { resolve(row); }) - .catch(error => { - console.error( - "Unexpected error occured while fetching settings for your account. Error:", - error - ); + .catch(() => reject({ status: 500, message: "An unexpected error occured while fetching settings for your account", source: "seasoned database" - }); - }); + }) + ); }); } @@ -184,12 +173,12 @@ class UserRepository { * @param {String} emoji * @returns {Promsie} */ - updateSettings(username, dark_mode = undefined, emoji = undefined) { + updateSettings(username, darkMode = null, emoji = null) { const settings = this.getSettings(username); - dark_mode = dark_mode !== undefined ? dark_mode : settings.dark_mode; - emoji = emoji !== undefined ? emoji : settings.emoji; + darkMode = darkMode ? darkMode : settings.darkMode; + emoji = emoji ? emoji : settings.emoji; - return this.dbUpdateSettings(username, dark_mode, emoji).catch(error => { + return this.dbUpdateSettings(username, darkMode, emoji).catch(error => { if (error.status && error.message) { return error; } @@ -225,10 +214,10 @@ class UserRepository { * @param {String} username * @returns {Promsie} */ - dbUpdateSettings(username, dark_mode, emoji) { - return new Promise((resolve, reject) => + dbUpdateSettings(username, darkMode, emoji) { + return new Promise(resolve => this.database - .run(this.queries.updateSettings, [username, dark_mode, emoji]) + .run(this.queries.updateSettings, [username, darkMode, emoji]) .then(row => resolve(row)) ); } @@ -240,7 +229,6 @@ const rejectUnexpectedDatabaseError = ( error, reject = null ) => { - console.error(error); const body = { status, message, @@ -248,7 +236,7 @@ const rejectUnexpectedDatabaseError = ( }; if (reject == null) { - return new Promise((resolve, reject) => reject(body)); + return new Promise((_, reject) => reject(body)); } reject(body); }; diff --git a/src/user/userSecurity.js b/src/user/userSecurity.js index ea07bb8..5caef59 100644 --- a/src/user/userSecurity.js +++ b/src/user/userSecurity.js @@ -50,7 +50,7 @@ class UserSecurity { return new Promise((resolve, reject) => { bcrypt.compare(clearPassword, hash, (error, match) => { if (match) resolve(true); - reject(false); + reject(error); }); }); } @@ -61,7 +61,7 @@ class UserSecurity { * @returns {Promise} */ static hashPassword(clearPassword) { - return new Promise(resolve => { + return new Promise((resolve, reject) => { const saltRounds = 10; bcrypt.hash(clearPassword, saltRounds, (error, hash) => { if (error) reject(error); diff --git a/src/webserver/app.js b/src/webserver/app.js index e184f5c..859c4a4 100644 --- a/src/webserver/app.js +++ b/src/webserver/app.js @@ -11,7 +11,7 @@ const mustBeAdmin = require("./middleware/mustBeAdmin"); const mustHaveAccountLinkedToPlex = require("./middleware/mustHaveAccountLinkedToPlex"); const listController = require("./controllers/list/listController"); -const tautulli = require("./controllers/user/viewHistory.js"); +const tautulli = require("./controllers/user/viewHistory"); const SettingsController = require("./controllers/user/settings"); const AuthenticatePlexAccountController = require("./controllers/user/authenticatePlexAccount"); @@ -24,7 +24,7 @@ app.use(bodyParser.json()); app.use(cookieParser()); const router = express.Router(); -const allowedOrigins = configuration.get("webserver", "origins"); +// const allowedOrigins = configuration.get("webserver", "origins"); // TODO: All JSON handling in a single router // router.use(bodyParser.json()); @@ -57,7 +57,7 @@ router.get("/", (req, res) => { }); app.use(Raven.errorHandler()); -app.use((err, req, res, next) => { +app.use((err, req, res) => { res.statusCode = 500; res.end(`${res.sentry}\n`); }); @@ -65,9 +65,9 @@ app.use((err, req, res, next) => { /** * User */ -router.post("/v1/user", require("./controllers/user/register.js")); -router.post("/v1/user/login", require("./controllers/user/login.js")); -router.post("/v1/user/logout", require("./controllers/user/logout.js")); +router.post("/v1/user", require("./controllers/user/register")); +router.post("/v1/user/login", require("./controllers/user/login")); +router.post("/v1/user/logout", require("./controllers/user/logout")); router.get( "/v1/user/settings", @@ -82,12 +82,12 @@ router.put( router.get( "/v1/user/search_history", mustBeAuthenticated, - require("./controllers/user/searchHistory.js") + require("./controllers/user/searchHistory") ); router.get( "/v1/user/requests", mustBeAuthenticated, - require("./controllers/user/requests.js") + require("./controllers/user/requests") ); router.post( @@ -125,46 +125,40 @@ router.get( /** * Seasoned */ -router.get("/v1/seasoned/all", require("./controllers/seasoned/readStrays.js")); +router.get("/v1/seasoned/all", require("./controllers/seasoned/readStrays")); router.get( "/v1/seasoned/:strayId", - require("./controllers/seasoned/strayById.js") + require("./controllers/seasoned/strayById") ); router.post( "/v1/seasoned/verify/:strayId", - require("./controllers/seasoned/verifyStray.js") + require("./controllers/seasoned/verifyStray") ); -router.get("/v2/search/", require("./controllers/search/multiSearch.js")); -router.get("/v2/search/movie", require("./controllers/search/movieSearch.js")); -router.get("/v2/search/show", require("./controllers/search/showSearch.js")); -router.get( - "/v2/search/person", - require("./controllers/search/personSearch.js") -); +router.get("/v2/search/", require("./controllers/search/multiSearch")); +router.get("/v2/search/movie", require("./controllers/search/movieSearch")); +router.get("/v2/search/show", require("./controllers/search/showSearch")); +router.get("/v2/search/person", require("./controllers/search/personSearch")); router.get("/v2/movie/now_playing", listController.nowPlayingMovies); router.get("/v2/movie/popular", listController.popularMovies); router.get("/v2/movie/top_rated", listController.topRatedMovies); router.get("/v2/movie/upcoming", listController.upcomingMovies); -router.get("/v2/movie/:id/credits", require("./controllers/movie/credits.js")); +router.get("/v2/movie/:id/credits", require("./controllers/movie/credits")); router.get( "/v2/movie/:id/release_dates", - require("./controllers/movie/releaseDates.js") + require("./controllers/movie/releaseDates") ); -router.get("/v2/movie/:id", require("./controllers/movie/info.js")); +router.get("/v2/movie/:id", require("./controllers/movie/info")); router.get("/v2/show/now_playing", listController.nowPlayingShows); router.get("/v2/show/popular", listController.popularShows); router.get("/v2/show/top_rated", listController.topRatedShows); -router.get("/v2/show/:id/credits", require("./controllers/show/credits.js")); -router.get("/v2/show/:id", require("./controllers/show/info.js")); +router.get("/v2/show/:id/credits", require("./controllers/show/credits")); +router.get("/v2/show/:id", require("./controllers/show/info")); -router.get( - "/v2/person/:id/credits", - require("./controllers/person/credits.js") -); -router.get("/v2/person/:id", require("./controllers/person/info.js")); +router.get("/v2/person/:id/credits", require("./controllers/person/credits")); +router.get("/v2/person/:id", require("./controllers/person/info")); /** * Plex @@ -174,40 +168,40 @@ router.get("/v2/plex/search", require("./controllers/plex/search")); /** * List */ -router.get("/v1/plex/search", require("./controllers/plex/searchMedia.js")); -router.get("/v1/plex/playing", require("./controllers/plex/plexPlaying.js")); -router.get("/v1/plex/request", require("./controllers/plex/searchRequest.js")); +router.get("/v1/plex/search", require("./controllers/plex/searchMedia")); +router.get("/v1/plex/playing", require("./controllers/plex/plexPlaying")); +router.get("/v1/plex/request", require("./controllers/plex/searchRequest")); router.get( "/v1/plex/request/:mediaId", - require("./controllers/plex/readRequest.js") + require("./controllers/plex/readRequest") ); router.post( "/v1/plex/request/:mediaId", - require("./controllers/plex/submitRequest.js") + require("./controllers/plex/submitRequest") ); -router.post("/v1/plex/hook", require("./controllers/plex/hookDump.js")); +router.post("/v1/plex/hook", require("./controllers/plex/hookDump")); router.get( "/v1/plex/watch-link", mustBeAuthenticated, - require("./controllers/plex/watchDirectLink.js") + require("./controllers/plex/watchDirectLink") ); /** * Requests */ -router.get("/v2/request", require("./controllers/request/fetchAllRequests.js")); -router.get("/v2/request/:id", require("./controllers/request/getRequest.js")); -router.post("/v2/request", require("./controllers/request/requestTmdbId.js")); +router.get("/v2/request", require("./controllers/request/fetchAllRequests")); +router.get("/v2/request/:id", require("./controllers/request/getRequest")); +router.post("/v2/request", require("./controllers/request/requestTmdbId")); router.get( "/v1/plex/requests/all", - require("./controllers/plex/fetchRequested.js") + require("./controllers/plex/fetchRequested") ); router.put( "/v1/plex/request/:requestId", mustBeAuthenticated, - require("./controllers/plex/updateRequested.js") + require("./controllers/plex/updateRequested") ); /** @@ -215,24 +209,24 @@ router.put( */ router.get( "/v1/pirate/search", - mustBeAuthenticated, - require("./controllers/pirate/searchTheBay.js") + mustBeAdmin, + require("./controllers/pirate/searchTheBay") ); router.post( "/v1/pirate/add", - mustBeAuthenticated, - require("./controllers/pirate/addMagnet.js") + mustBeAdmin, + require("./controllers/pirate/addMagnet") ); /** * git */ -router.post("/v1/git/dump", require("./controllers/git/dumpHook.js")); +router.post("/v1/git/dump", require("./controllers/git/dumpHook")); /** * misc */ -router.get("/v1/emoji", require("./controllers/misc/emoji.js")); +router.get("/v1/emoji", require("./controllers/misc/emoji")); // REGISTER OUR ROUTES ------------------------------- // all of our routes will be prefixed with /api diff --git a/src/webserver/controllers/git/dumpHook.js b/src/webserver/controllers/git/dumpHook.js index bed04f5..5016893 100644 --- a/src/webserver/controllers/git/dumpHook.js +++ b/src/webserver/controllers/git/dumpHook.js @@ -5,12 +5,8 @@ const gitRepository = new GitRepository(); function dumpHookController(req, res) { gitRepository .dumpHook(req.body) - .then(() => { - res.status(200); - }) - .catch(error => { - res.status(500); - }); + .then(() => res.status(200)) + .catch(() => res.status(500)); } module.exports = dumpHookController; diff --git a/src/webserver/controllers/list/listController.js b/src/webserver/controllers/list/listController.js index 9557099..2b55c59 100644 --- a/src/webserver/controllers/list/listController.js +++ b/src/webserver/controllers/list/listController.js @@ -21,17 +21,12 @@ function handleError(error, res) { if (status && message) { res.status(status).send({ success: false, message }); } else { - console.log("caught list controller error", error); res .status(500) .send({ message: "An unexpected error occured while requesting list" }); } } -function handleListResponse(response, res) { - return res.send(response).catch(error => handleError(error, res)); -} - function fetchTmdbList(req, res, listname, type) { const { page } = req.query; @@ -48,7 +43,7 @@ function fetchTmdbList(req, res, listname, type) { .catch(error => handleError(error, res)); } - handleError( + return handleError( { status: 400, message: `'${type}' is not a valid list type.` diff --git a/src/webserver/controllers/movie/credits.js b/src/webserver/controllers/movie/credits.js index f8ec6c1..ce33c5f 100644 --- a/src/webserver/controllers/movie/credits.js +++ b/src/webserver/controllers/movie/credits.js @@ -15,8 +15,6 @@ const movieCreditsController = (req, res) => { if (status && message) { res.status(status).send({ success: false, message }); } else { - // TODO log unhandled errors - console.log("caugth movie credits controller error", error); res.status(500).send({ message: "An unexpected error occured while requesting movie credits" }); diff --git a/src/webserver/controllers/movie/info.js b/src/webserver/controllers/movie/info.js index 5d31b7e..f22889f 100644 --- a/src/webserver/controllers/movie/info.js +++ b/src/webserver/controllers/movie/info.js @@ -1,6 +1,7 @@ const configuration = require("../../../config/configuration").getInstance(); const TMDB = require("../../../tmdb/tmdb"); const Plex = require("../../../plex/plex"); + const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const plex = new Plex(configuration.get("plex", "ip")); @@ -10,9 +11,10 @@ function handleError(error, res) { if (status && message) { res.status(status).send({ success: false, message }); } else { - console.log("caught movieinfo controller error", error); res.status(500).send({ - message: "An unexpected error occured while requesting movie info" + success: false, + message: "An unexpected error occured while requesting movie info", + errorResponse: error?.message }); } } @@ -25,21 +27,18 @@ function handleError(error, res) { */ async function movieInfoController(req, res) { const movieId = req.params.id; - let { credits, release_dates, check_existance } = req.query; - credits && credits.toLowerCase() === "true" - ? (credits = true) - : (credits = false); - release_dates && release_dates.toLowerCase() === "true" - ? (release_dates = true) - : (release_dates = false); - check_existance && check_existance.toLowerCase() === "true" - ? (check_existance = true) - : (check_existance = false); + let credits = req.query?.credits; + let releaseDates = req.query?.release_dates; + let checkExistance = req.query?.check_existance; - let tmdbQueue = [tmdb.movieInfo(movieId)]; + credits = credits.toLowerCase() === "true"; + releaseDates = releaseDates.toLowerCase() === "true"; + checkExistance = checkExistance.toLowerCase() === "true"; + + const tmdbQueue = [tmdb.movieInfo(movieId)]; if (credits) tmdbQueue.push(tmdb.movieCredits(movieId)); - if (release_dates) tmdbQueue.push(tmdb.movieReleaseDates(movieId)); + if (releaseDates) tmdbQueue.push(tmdb.movieReleaseDates(movieId)); try { const [Movie, Credits, ReleaseDates] = await Promise.all(tmdbQueue); @@ -47,19 +46,12 @@ async function movieInfoController(req, res) { const movie = Movie.createJsonResponse(); if (Credits) movie.credits = Credits.createJsonResponse(); if (ReleaseDates) - movie.release_dates = ReleaseDates.createJsonResponse().results; + movie.releaseDates = ReleaseDates.createJsonResponse().results; - if (check_existance) { + if (checkExistance) { try { movie.exists_in_plex = await plex.existsInPlex(movie); - } catch (error) { - if (error.status === 401) { - console.log("Unathorized request, check plex server LAN settings"); - } else { - console.log("Unkown error from plex!"); - } - console.log(error?.message); - } + } catch {} } res.send(movie); diff --git a/src/webserver/controllers/movie/releaseDates.js b/src/webserver/controllers/movie/releaseDates.js index 84bd43b..8097002 100644 --- a/src/webserver/controllers/movie/releaseDates.js +++ b/src/webserver/controllers/movie/releaseDates.js @@ -15,8 +15,6 @@ const movieReleaseDatesController = (req, res) => { if (status && message) { res.status(status).send({ success: false, message }); } else { - // TODO log unhandled errors : here our at tmdbReleaseError ? - console.log("caugth release dates controller error", error); res.status(500).send({ message: "An unexpected error occured while requesting movie credits" }); diff --git a/src/webserver/controllers/person/credits.js b/src/webserver/controllers/person/credits.js index 19eb5c2..414936a 100644 --- a/src/webserver/controllers/person/credits.js +++ b/src/webserver/controllers/person/credits.js @@ -15,8 +15,6 @@ const personCreditsController = (req, res) => { if (status && message) { res.status(status).send({ success: false, message }); } else { - // TODO log unhandled errors - console.log("caugth show credits controller error", error); res.status(500).send({ message: "An unexpected error occured while requesting person credits" }); diff --git a/src/webserver/controllers/person/info.js b/src/webserver/controllers/person/info.js index 87c91ff..c57436f 100644 --- a/src/webserver/controllers/person/info.js +++ b/src/webserver/controllers/person/info.js @@ -9,7 +9,6 @@ function handleError(error, res) { if (status && message) { res.status(status).send({ success: false, message }); } else { - console.log("caught personinfo controller error", error); res.status(500).send({ message: "An unexpected error occured while requesting person info." }); @@ -26,11 +25,8 @@ function handleError(error, res) { async function personInfoController(req, res) { const personId = req.params.id; let { credits } = req.query; - arguments; - credits && credits.toLowerCase() === "true" - ? (credits = true) - : (credits = false); + credits = credits.toLowerCase() === "true"; const tmdbQueue = [tmdb.personInfo(personId)]; if (credits) tmdbQueue.push(tmdb.personCredits(personId)); @@ -43,7 +39,7 @@ async function personInfoController(req, res) { return res.send(person); } catch (error) { - handleError(error, res); + return handleError(error, res); } } diff --git a/src/webserver/controllers/pirate/addMagnet.js b/src/webserver/controllers/pirate/addMagnet.js index 7dfbbdd..2ff7599 100644 --- a/src/webserver/controllers/pirate/addMagnet.js +++ b/src/webserver/controllers/pirate/addMagnet.js @@ -8,14 +8,11 @@ const PirateRepository = require("../../../pirate/pirateRepository"); function addMagnet(req, res) { - const { magnet } = req.body; - const { name } = req.body; - const { tmdb_id } = req.body; + const { magnet, name } = req.body; + const tmdbId = req.body?.tmdb_id; - PirateRepository.AddMagnet(magnet, name, tmdb_id) - .then(result => { - res.send(result); - }) + PirateRepository.AddMagnet(magnet, name, tmdbId) + .then(result => res.send(result)) .catch(error => { res.status(500).send({ success: false, message: error.message }); }); diff --git a/src/webserver/controllers/plex/fetchRequested.js b/src/webserver/controllers/plex/fetchRequested.js index 56eeaaa..14ba536 100644 --- a/src/webserver/controllers/plex/fetchRequested.js +++ b/src/webserver/controllers/plex/fetchRequested.js @@ -1,4 +1,4 @@ -const RequestRepository = require("../../../plex/requestRepository.js"); +const RequestRepository = require("../../../plex/requestRepository"); const requestRepository = new RequestRepository(); diff --git a/src/webserver/controllers/plex/hookDump.js b/src/webserver/controllers/plex/hookDump.js index 15682a0..bd39fcb 100644 --- a/src/webserver/controllers/plex/hookDump.js +++ b/src/webserver/controllers/plex/hookDump.js @@ -1,12 +1,8 @@ -/* - * @Author: KevinMidboe - * @Date: 2017-05-03 23:26:46 - * @Last Modified by: KevinMidboe - * @Last Modified time: 2018-02-06 20:54:22 - */ - function hookDumpController(req, res) { - console.log(req); + // eslint-disable-next-line no-console + console.log("plex hook dump:", req); + + res.status(200); } module.exports = hookDumpController; diff --git a/src/webserver/controllers/plex/searchRequest.js b/src/webserver/controllers/plex/searchRequest.js index c040f48..b7ce101 100644 --- a/src/webserver/controllers/plex/searchRequest.js +++ b/src/webserver/controllers/plex/searchRequest.js @@ -1,6 +1,6 @@ const SearchHistory = require("../../../searchHistory/searchHistory"); const Cache = require("../../../tmdb/cache"); -const RequestRepository = require("../../../plex/requestRepository.js"); +const RequestRepository = require("../../../plex/requestRepository"); const cache = new Cache(); const requestRepository = new RequestRepository(cache); @@ -10,8 +10,8 @@ function searchRequestController(req, res) { const { query, page, type } = req.query; const username = req.loggedInUser ? req.loggedInUser.username : null; - Promise.resolve() - .then(() => searchHistory.create(username, query)) + searchHistory + .create(username, query) .then(() => requestRepository.search(query, page, type)) .then(searchResult => { res.send(searchResult); diff --git a/src/webserver/controllers/plex/submitRequest.js b/src/webserver/controllers/plex/submitRequest.js index c06083a..6039c47 100644 --- a/src/webserver/controllers/plex/submitRequest.js +++ b/src/webserver/controllers/plex/submitRequest.js @@ -24,16 +24,14 @@ function submitRequestController(req, res) { const id = req.params.mediaId; const type = req.query.type ? req.query.type.toLowerCase() : undefined; const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress; - const user_agent = req.headers["user-agent"]; + const userAgent = req.headers["user-agent"]; const username = req.loggedInUser ? req.loggedInUser.username : null; let mediaFunction; if (type === "movie") { - console.log("movie"); mediaFunction = tmdbMovieInfo; } else if (type === "show") { - console.log("show"); mediaFunction = tmdbShowInfo; } else { res.status(422).send({ @@ -49,7 +47,7 @@ function submitRequestController(req, res) { mediaFunction(id) .then(tmdbMedia => - request.requestFromTmdb(tmdbMedia, ip, user_agent, username) + request.requestFromTmdb(tmdbMedia, ip, userAgent, username) ) .then(() => res.send({ success: true, message: "Media item successfully requested" }) diff --git a/src/webserver/controllers/plex/watchDirectLink.js b/src/webserver/controllers/plex/watchDirectLink.js index 13c4eb1..dabee21 100644 --- a/src/webserver/controllers/plex/watchDirectLink.js +++ b/src/webserver/controllers/plex/watchDirectLink.js @@ -16,7 +16,7 @@ function watchDirectLink(req, res) { plex .getDirectLinkByTitleAndYear(title, year) .then(plexDirectLink => { - if (plexDirectLink == false) + if (plexDirectLink === false) res.status(404).send({ success: true, link: null }); else res.status(200).send({ success: true, link: plexDirectLink }); }) diff --git a/src/webserver/controllers/request/fetchAllRequests.js b/src/webserver/controllers/request/fetchAllRequests.js index c6f8ae2..c20ea23 100644 --- a/src/webserver/controllers/request/fetchAllRequests.js +++ b/src/webserver/controllers/request/fetchAllRequests.js @@ -9,16 +9,10 @@ const request = new RequestRepository(); * @returns {Callback} */ function fetchAllRequests(req, res) { - const { page, filter, sort, query } = req.query; - let sort_by = sort; - let sort_direction; + const { page, filter } = req.query; - if (sort !== undefined && sort.includes(":")) { - [sort_by, sort_direction] = sort.split(":"); - } - - Promise.resolve() - .then(() => request.fetchAll(page, sort_by, sort_direction, filter, query)) + request + .fetchAll(page, filter) .then(result => res.send(result)) .catch(error => { res.status(404).send({ success: false, message: error.message }); diff --git a/src/webserver/controllers/request/requestTmdbId.js b/src/webserver/controllers/request/requestTmdbId.js index 139e560..01d5c1a 100644 --- a/src/webserver/controllers/request/requestTmdbId.js +++ b/src/webserver/controllers/request/requestTmdbId.js @@ -24,7 +24,7 @@ function requestTmdbIdController(req, res) { const { id, type } = req.body; const ip = req.headers["x-forwarded-for"] || req.connection.remoteAddress; - const user_agent = req.headers["user-agent"]; + const userAgent = req.headers["user-agent"]; const username = req.loggedInUser ? req.loggedInUser.username : null; let mediaFunction; @@ -50,7 +50,7 @@ function requestTmdbIdController(req, res) { mediaFunction(id) // .catch((error) => { console.error(error); res.status(404).send({ success: false, error: 'Id not found' }) }) .then(tmdbMedia => { - request.requestFromTmdb(tmdbMedia, ip, user_agent, username); + request.requestFromTmdb(tmdbMedia, ip, userAgent, username); // TODO enable SMS // const url = `https://request.movie?${tmdbMedia.type}=${tmdbMedia.id}`; diff --git a/src/webserver/controllers/search/movieSearch.js b/src/webserver/controllers/search/movieSearch.js index 3fa329d..8d216c4 100644 --- a/src/webserver/controllers/search/movieSearch.js +++ b/src/webserver/controllers/search/movieSearch.js @@ -14,7 +14,7 @@ const searchHistory = new SearchHistory(); function movieSearchController(req, res) { const { query, page, adult } = req.query; const username = req.loggedInUser ? req.loggedInUser.username : null; - const includeAdult = adult == "true"; + const includeAdult = adult === "true"; if (username) { searchHistory.create(username, query); @@ -29,8 +29,6 @@ function movieSearchController(req, res) { if (status && message) { res.status(status).send({ success: false, message }); } else { - // TODO log unhandled errors - console.log("caugth movie search controller error", error); res.status(500).send({ message: `An unexpected error occured while searching movies with query: ${query}` }); diff --git a/src/webserver/controllers/search/multiSearch.js b/src/webserver/controllers/search/multiSearch.js index 5172612..b96a4f1 100644 --- a/src/webserver/controllers/search/multiSearch.js +++ b/src/webserver/controllers/search/multiSearch.js @@ -5,13 +5,6 @@ const SearchHistory = require("../../../searchHistory/searchHistory"); const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const searchHistory = new SearchHistory(); -function checkAndCreateJsonResponse(result) { - if (typeof result.createJsonResponse === "function") { - return result.createJsonResponse(); - } - return result; -} - /** * Controller: Search for multi (movies, shows and people by query and pagey * @param {Request} req http request variable @@ -21,13 +14,14 @@ function checkAndCreateJsonResponse(result) { function multiSearchController(req, res) { const { query, page, adult } = req.query; const username = req.loggedInUser ? req.loggedInUser.username : null; + const includeAdult = adult === "true"; if (username) { searchHistory.create(username, query); } return tmdb - .multiSearch(query, page, adult) + .multiSearch(query, page, includeAdult) .then(multiSearchResults => res.send(multiSearchResults)) .catch(error => { const { status, message } = error; @@ -35,8 +29,6 @@ function multiSearchController(req, res) { if (status && message) { res.status(status).send({ success: false, message }); } else { - // TODO log unhandled errors - console.log("caugth multi search controller error", error); res.status(500).send({ message: `An unexpected error occured while searching with query: ${query}` }); diff --git a/src/webserver/controllers/search/personSearch.js b/src/webserver/controllers/search/personSearch.js index 4a3699f..c908dea 100644 --- a/src/webserver/controllers/search/personSearch.js +++ b/src/webserver/controllers/search/personSearch.js @@ -14,7 +14,7 @@ const searchHistory = new SearchHistory(); function personSearchController(req, res) { const { query, page, adult } = req.query; const username = req.loggedInUser ? req.loggedInUser.username : null; - const includeAdult = adult == "true"; + const includeAdult = adult === "true"; if (username) { searchHistory.create(username, query); @@ -29,8 +29,6 @@ function personSearchController(req, res) { if (status && message) { res.status(status).send({ success: false, message }); } else { - // TODO log unhandled errors - console.log("caugth person search controller error", error); res.status(500).send({ message: `An unexpected error occured while searching people with query: ${query}` }); diff --git a/src/webserver/controllers/search/showSearch.js b/src/webserver/controllers/search/showSearch.js index 2566010..740f763 100644 --- a/src/webserver/controllers/search/showSearch.js +++ b/src/webserver/controllers/search/showSearch.js @@ -14,7 +14,7 @@ const searchHistory = new SearchHistory(); function showSearchController(req, res) { const { query, page, adult } = req.query; const username = req.loggedInUser ? req.loggedInUser.username : null; - const includeAdult = adult == "true"; + const includeAdult = adult === "true"; if (username) { searchHistory.create(username, query); diff --git a/src/webserver/controllers/show/credits.js b/src/webserver/controllers/show/credits.js index f381efd..bed66a9 100644 --- a/src/webserver/controllers/show/credits.js +++ b/src/webserver/controllers/show/credits.js @@ -15,8 +15,6 @@ const showCreditsController = (req, res) => { if (status && message) { res.status(status).send({ success: false, message }); } else { - // TODO log unhandled errors - console.log("caugth show credits controller error", error); res.status(500).send({ message: "An unexpected error occured while requesting show credits" }); diff --git a/src/webserver/controllers/show/info.js b/src/webserver/controllers/show/info.js index 9ae9e58..4eeba4a 100644 --- a/src/webserver/controllers/show/info.js +++ b/src/webserver/controllers/show/info.js @@ -11,7 +11,6 @@ function handleError(error, res) { if (status && message) { res.status(status).send({ success: false, message }); } else { - console.log("caught showinfo controller error", error); res.status(500).send({ message: "An unexpected error occured while requesting show info." }); @@ -27,14 +26,11 @@ function handleError(error, res) { async function showInfoController(req, res) { const showId = req.params.id; - let { credits, check_existance } = req.query; + let credits = req.query?.credits; + let checkExistance = req.query?.check_existance; - credits && credits.toLowerCase() === "true" - ? (credits = true) - : (credits = false); - check_existance && check_existance.toLowerCase() === "true" - ? (check_existance = true) - : (check_existance = false); + credits = credits?.toLowerCase() === "true"; + checkExistance = checkExistance?.toLowerCase() === "true"; const tmdbQueue = [tmdb.showInfo(showId)]; if (credits) tmdbQueue.push(tmdb.showCredits(showId)); @@ -45,7 +41,12 @@ async function showInfoController(req, res) { const show = Show.createJsonResponse(); if (credits) show.credits = Credits.createJsonResponse(); - if (check_existance) show.exists_in_plex = await plex.existsInPlex(show); + if (checkExistance) { + /* eslint no-empty: ["error", { "allowEmptyCatch": true }] */ + try { + show.exists_in_plex = await plex.existsInPlex(show); + } catch {} + } res.send(show); } catch (error) { diff --git a/src/webserver/controllers/user/authenticatePlexAccount.js b/src/webserver/controllers/user/authenticatePlexAccount.js index 4e5a09c..8ac5896 100644 --- a/src/webserver/controllers/user/authenticatePlexAccount.js +++ b/src/webserver/controllers/user/authenticatePlexAccount.js @@ -1,20 +1,33 @@ +const FormData = require("form-data"); const UserRepository = require("../../../user/userRepository"); const userRepository = new UserRepository(); -const fetch = require("node-fetch"); -const FormData = require("form-data"); + +class PlexAuthenticationError extends Error { + constructor(errorResponse, statusCode) { + const message = + "Unexptected error while authenticating to plex signin api. View error response."; + super(message); + + this.errorResponse = errorResponse; + this.statusCode = statusCode; + this.success = false; + } +} function handleError(error, res) { - let { status, message, source } = error; + const status = error?.status; + let { message, source } = error; if (status && message) { if (status === 401) { - (message = "Unauthorized. Please check plex credentials."), - (source = "plex"); + message = "Unauthorized. Please check plex credentials."; + source = "plex"; } res.status(status).send({ success: false, message, source }); } else { + // eslint-disable-next-line no-console console.log("caught authenticate plex account controller error", error); res.status(500).send({ message: @@ -26,11 +39,7 @@ function handleError(error, res) { function handleResponse(response) { if (!response.ok) { - throw { - success: false, - status: response.status, - message: response.statusText - }; + throw new PlexAuthenticationError(response.statusText, response.status); } return response.json(); @@ -64,7 +73,7 @@ function link(req, res) { return plexAuthenticate(username, password) .then(plexUser => userRepository.linkPlexUserId(user.username, plexUser.id)) - .then(response => + .then(() => res.send({ success: true, message: @@ -79,7 +88,7 @@ function unlink(req, res) { return userRepository .unlinkPlexUserId(username) - .then(response => + .then(() => res.send({ success: true, message: "Successfully unlinked plex account from seasoned request." diff --git a/src/webserver/controllers/user/register.js b/src/webserver/controllers/user/register.js index 2c36f4e..655f920 100644 --- a/src/webserver/controllers/user/register.js +++ b/src/webserver/controllers/user/register.js @@ -1,12 +1,10 @@ const User = require("../../../user/user"); const Token = require("../../../user/token"); const UserSecurity = require("../../../user/userSecurity"); -const UserRepository = require("../../../user/userRepository"); const configuration = require("../../../config/configuration").getInstance(); const secret = configuration.get("authentication", "secret"); const userSecurity = new UserSecurity(); -const userRepository = new UserRepository(); const isProduction = process.env.NODE_ENV === "production"; const cookieOptions = { diff --git a/src/webserver/controllers/user/requests.js b/src/webserver/controllers/user/requests.js index e412c64..5fe0f22 100644 --- a/src/webserver/controllers/user/requests.js +++ b/src/webserver/controllers/user/requests.js @@ -1,4 +1,4 @@ -const RequestRepository = require("../../../plex/requestRepository.js"); +const RequestRepository = require("../../../plex/requestRepository"); const requestRepository = new RequestRepository(); diff --git a/src/webserver/controllers/user/settings.js b/src/webserver/controllers/user/settings.js index caf55f8..adf0d8d 100644 --- a/src/webserver/controllers/user/settings.js +++ b/src/webserver/controllers/user/settings.js @@ -23,11 +23,12 @@ const getSettingsController = (req, res) => { const updateSettingsController = (req, res) => { const username = req.loggedInUser ? req.loggedInUser.username : null; - const idempotencyKey = req.headers("Idempotency-Key"); // TODO implement better transactions - const { dark_mode, emoji } = req.body; + // const idempotencyKey = req.headers("Idempotency-Key"); // TODO implement better transactions + const emoji = req.body?.emoji; + const darkMode = req.body?.dark_mode; userRepository - .updateSettings(username, dark_mode, emoji) + .updateSettings(username, darkMode, emoji) .then(settings => { res.send({ success: true, settings }); }) diff --git a/src/webserver/controllers/user/viewHistory.js b/src/webserver/controllers/user/viewHistory.js index 55b3077..865a3d7 100644 --- a/src/webserver/controllers/user/viewHistory.js +++ b/src/webserver/controllers/user/viewHistory.js @@ -12,7 +12,7 @@ function handleError(error, res) { if (status && message) { return res.status(status).send({ success: false, message }); } - console.log("caught view history controller error", error); + return res.status(500).send({ message: "An unexpected error occured while fetching view history" }); @@ -35,10 +35,11 @@ function watchTimeStatsController(req, res) { function getPlaysByDayOfWeekController(req, res) { const user = req.loggedInUser; - const { days, y_axis } = req.query; + const days = req.query?.days; + const yAxis = req.query?.y_axis; return tautulli - .getPlaysByDayOfWeek(user.plexUserId, days, y_axis) + .getPlaysByDayOfWeek(user.plexUserId, days, yAxis) .then(data => res.send({ success: true, @@ -51,7 +52,8 @@ function getPlaysByDayOfWeekController(req, res) { function getPlaysByDaysController(req, res) { const user = req.loggedInUser; - const { days, y_axis } = req.query; + const days = req.query?.days; + const yAxis = req.query?.y_axis; if (days === undefined) { return res.status(422).send({ @@ -61,7 +63,7 @@ function getPlaysByDaysController(req, res) { } const allowedYAxisDataType = ["plays", "duration"]; - if (!allowedYAxisDataType.includes(y_axis)) { + if (!allowedYAxisDataType.includes(yAxis)) { return res.status(422).send({ success: false, message: `Y axis parameter must be one of values: [${allowedYAxisDataType}]` @@ -69,7 +71,7 @@ function getPlaysByDaysController(req, res) { } return tautulli - .getPlaysByDays(user.plexUserId, days, y_axis) + .getPlaysByDays(user.plexUserId, days, yAxis) .then(data => res.send({ success: true, diff --git a/tests/fixtures/blade_runner_2049-info-success-response.json b/tests/fixtures/blade_runner_2049-info-success-response.json index 62eb96f..4c412e0 100644 --- a/tests/fixtures/blade_runner_2049-info-success-response.json +++ b/tests/fixtures/blade_runner_2049-info-success-response.json @@ -1 +1,89 @@ -[{"adult":false,"backdrop_path":"/mVr0UiqyltcfqxbAUcLl9zWL8ah.jpg","belongs_to_collection":{"id":422837,"name":"Blade Runner Collection","poster_path":"/cWESb1o9lW2i2Z3Xllv9u40aNIk.jpg","backdrop_path":"/bSHZIvLoPBWyGLeiAudN1mXdvQX.jpg"},"budget":150000000,"genres":[{"id":9648,"name":"Mystery"},{"id":878,"name":"Science Fiction"},{"id":53,"name":"Thriller"}],"homepage":"http://bladerunnermovie.com/","id":335984,"imdb_id":"tt1856101","original_language":"en","original_title":"Blade Runner 2049","overview":"Thirty years after the events of the first film, a new blade runner, LAPD Officer K, unearths a long-buried secret that has the potential to plunge what's left of society into chaos. K's discovery leads him on a quest to find Rick Deckard, a former LAPD blade runner who has been missing for 30 years.","popularity":30.03,"poster_path":"/gajva2L0rPYkEWjzgFlBXCAVBE5.jpg","production_companies":[{"id":79529,"logo_path":"/gVN3k8emmKy4iV4KREWcCtxusZK.png","name":"Torridon Films","origin_country":"US"},{"id":101829,"logo_path":"/8IOjCvgjq0zTrtP91cWD3kL2jMK.png","name":"16:14 Entertainment","origin_country":"US"},{"id":1645,"logo_path":"/6Ry6uNBaa0IbbSs1XYIgX5DkA9r.png","name":"Scott Free Productions","origin_country":""},{"id":5,"logo_path":"/71BqEFAF4V3qjjMPCpLuyJFB9A.png","name":"Columbia Pictures","origin_country":"US"},{"id":1088,"logo_path":"/9WOE5AQUXbOtLU6GTwfjS8OMF0v.png","name":"Alcon Entertainment","origin_country":"US"},{"id":78028,"logo_path":"/sTFcDFfJaSVT3sv3DoaZDE4SlGB.png","name":"Thunderbird Entertainment","origin_country":"CA"},{"id":174,"logo_path":"/ky0xOc5OrhzkZ1N6KyUxacfQsCk.png","name":"Warner Bros. Pictures","origin_country":"US"}],"production_countries":[{"iso_3166_1":"CA","name":"Canada"},{"iso_3166_1":"US","name":"United States of America"},{"iso_3166_1":"HU","name":"Hungary"},{"iso_3166_1":"GB","name":"United Kingdom"}],"release_date":"2017-10-04","revenue":259239658,"runtime":163,"spoken_languages":[{"iso_639_1":"en","name":"English"},{"iso_639_1":"fi","name":"suomi"}],"status":"Released","tagline":"There's still a page left.","title":"Blade Runner 2049","video":false,"vote_average":7.3,"vote_count":5478}] +[ + { + "adult": false, + "backdrop_path": "/mVr0UiqyltcfqxbAUcLl9zWL8ah.jpg", + "belongs_to_collection": { + "id": 422837, + "name": "Blade Runner Collection", + "poster_path": "/cWESb1o9lW2i2Z3Xllv9u40aNIk.jpg", + "backdrop_path": "/bSHZIvLoPBWyGLeiAudN1mXdvQX.jpg" + }, + "budget": 150000000, + "genres": [ + { "id": 9648, "name": "Mystery" }, + { "id": 878, "name": "Science Fiction" }, + { "id": 53, "name": "Thriller" } + ], + "homepage": "http://bladerunnermovie.com/", + "id": 335984, + "imdb_id": "tt1856101", + "original_language": "en", + "original_title": "Blade Runner 2049", + "overview": "Thirty years after the events of the first film, a new blade runner, LAPD Officer K, unearths a long-buried secret that has the potential to plunge what's left of society into chaos. K's discovery leads him on a quest to find Rick Deckard, a former LAPD blade runner who has been missing for 30 years.", + "popularity": 30.03, + "poster_path": "/gajva2L0rPYkEWjzgFlBXCAVBE5.jpg", + "production_companies": [ + { + "id": 79529, + "logo_path": "/gVN3k8emmKy4iV4KREWcCtxusZK.png", + "name": "Torridon Films", + "origin_country": "US" + }, + { + "id": 101829, + "logo_path": "/8IOjCvgjq0zTrtP91cWD3kL2jMK.png", + "name": "16:14 Entertainment", + "origin_country": "US" + }, + { + "id": 1645, + "logo_path": "/6Ry6uNBaa0IbbSs1XYIgX5DkA9r.png", + "name": "Scott Free Productions", + "origin_country": "" + }, + { + "id": 5, + "logo_path": "/71BqEFAF4V3qjjMPCpLuyJFB9A.png", + "name": "Columbia Pictures", + "origin_country": "US" + }, + { + "id": 1088, + "logo_path": "/9WOE5AQUXbOtLU6GTwfjS8OMF0v.png", + "name": "Alcon Entertainment", + "origin_country": "US" + }, + { + "id": 78028, + "logo_path": "/sTFcDFfJaSVT3sv3DoaZDE4SlGB.png", + "name": "Thunderbird Entertainment", + "origin_country": "CA" + }, + { + "id": 174, + "logo_path": "/ky0xOc5OrhzkZ1N6KyUxacfQsCk.png", + "name": "Warner Bros. Pictures", + "origin_country": "US" + } + ], + "production_countries": [ + { "iso_3166_1": "CA", "name": "Canada" }, + { "iso_3166_1": "US", "name": "United States of America" }, + { "iso_3166_1": "HU", "name": "Hungary" }, + { "iso_3166_1": "GB", "name": "United Kingdom" } + ], + "release_date": "2017-10-04", + "revenue": 259239658, + "runtime": 163, + "spoken_languages": [ + { "iso_639_1": "en", "name": "English" }, + { "iso_639_1": "fi", "name": "suomi" } + ], + "status": "Released", + "tagline": "There's still a page left.", + "title": "Blade Runner 2049", + "video": false, + "vote_average": 7.3, + "vote_count": 5478 + } +] diff --git a/tests/fixtures/interstellar-query-movie-success-response.json b/tests/fixtures/interstellar-query-movie-success-response.json index 19162ac..d511be2 100644 --- a/tests/fixtures/interstellar-query-movie-success-response.json +++ b/tests/fixtures/interstellar-query-movie-success-response.json @@ -1 +1,193 @@ -{"results":[{"id":157336,"title":"Interstellar","year":2014,"overview":"Interstellar chronicles the adventures of a group of explorers who make use of a newly discovered wormhole to surpass the limitations on human space travel and conquer the vast distances involved in an interstellar voyage.","poster":"/nBNZadXqJSdt05SHLqgT0HuC5Gm.jpg","backdrop":"/xu9zaAevzQ5nnrsXN6JcahLnG4i.jpg","rank":8.2,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","release_date":"2014-11-05T00:00:00.000Z"},{"id":301959,"title":"Interstellar: Nolan's Odyssey","year":2014,"overview":"Behind the scenes of Christopher Nolan's sci-fi drama, which stars Matthew McConaughey and Anne Hathaway","poster":"/xZwUIPqBHyJ2QIfMPANOZ1mAld6.jpg","backdrop":"/bT5jpIZE50MI0COE8pOeq0kMpQo.jpg","rank":7.9,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":1,"release_date":"2014-11-05T00:00:00.000Z"},{"id":398188,"title":"Interstellar Wars","year":2016,"overview":"For Millennia the Aliien force has watched and waited, a brooding menace that has now at last decided to take over the Earth. Communications systems worldwide are sent into chaos by a strange atmospheric interference and this has turned into a global phenomenon. A massive spaceship headed towards Earth and smaller spaceships began to cover entire cities around the world. Suddenly, the wonder turns into horror as the spaceships destroy the cities with energy weapons. When the world counterattacks, the alien ships are invincible to military weapons. The survivors have to use their wits to kill the aliens, or die.","poster":"/cjvTebuqD8wmhchHE286ltVcbX6.jpg","backdrop":"/yTnHa6lgIv8rNneSNBDkBe8MnZe.jpg","rank":3.8,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":2,"release_date":"2016-05-23T00:00:00.000Z"},{"id":287954,"title":"Lolita from Interstellar Space","year":2014,"overview":"An undeniably beautiful alien is sent to Earth to study the complex mating rituals of human beings, which leads to the young interstellar traveler experiencing the passion that surrounds the centuries-old ritual of the species.","poster":"/buoq7zYO4J3ttkEAqEMWelPDC0G.jpg","backdrop":"/mgb6tVEieDYLpQt666ACzGz5cyE.jpg","rank":7,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":3,"release_date":"2014-03-08T00:00:00.000Z"},{"id":336592,"title":"The Science of Interstellar","year":2014,"overview":"The science of Christopher Nolan's sci-fi, Interstellar.","poster":"/6KBD7YSBjCfgBgHwpsQo3G3GGdx.jpg","backdrop":null,"rank":7.8,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":4,"release_date":"2014-11-25T00:00:00.000Z"},{"id":529107,"title":"Inside Interstellar","year":2015,"overview":"Cast and crew of Christopher Nolan's 'Interstellar' discuss project origins, the film's imagery, ambitions, incorporating IMAX footage, the human element within the film, arm shooting locations outside of Calgary, the set construction and design, working with real corn, mechanical characters, including backstory, design, the blend of practical and digital effects in bringing them to life, the differences in the characters, the human performances behind the characters, the creative process behind the film's music, Icelandic locations, vehicle interiors, the processes of simulating the absence of gravity, the crucial end-film visuals and influence and inspiration for future generations","poster":"/vemBplPKQhVe5cRWL7kxtgp15Vq.jpg","backdrop":null,"rank":9,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":5,"release_date":"2015-03-31T00:00:00.000Z"},{"id":552531,"title":"The Prom Goer's Interstellar Excursion","year":null,"overview":"High schooler Bennett lands the prom date of his dreams, Sophie, just days before the dance. Not long after, he witnesses Sophie being abducted by aliens in the middle of the New Mexico desert.","poster":null,"backdrop":null,"rank":0,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":6,"release_date":null},{"id":460616,"title":"Interstellar Civil War: Shadows of the Empire","year":2018,"overview":"The Imperial Empire is attacked by an Alliance of rebels led by fanatical mystics. The ruler, Empress Nobu, the 8th generation of her family, wants to execute a bold plan to rescue a cyborg, Leah C6, trapped on the battle ravaged planet Endor. The Empress believes Leah C6 holds the secret to destroying the Alliance of Rebels before their insurgency can kill millions of citizens of the Empire. She recruits her heroic fleet commander, Lord General Luka Raan and asks him to gather a team from the Empire's elite soldiers, the Galactic Rangers. Raan assembles the team in the ruins of Endor which was attacked by depraved Rebels and outlaws led by, Kindo-Ker, a fanatical mystic in Dark Energy. The Galactic Rangers begin a desperate search to find and rescue Leah C6 before the Alliance Rebels can.","poster":"/1lDY7ZpEKOl3OaIQURjRbmFPfT8.jpg","backdrop":null,"rank":4,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":7,"release_date":"2018-04-15T00:00:00.000Z"},{"id":47662,"title":"Trancers 4: Jack of Swords","year":1994,"overview":"Jack is now back in the future. He had since lost Lena, and finds out that he's lost his other wife Alice to none other than Harris. While heading out for another assignment, something goes awry with the TCL chamber. Jack finds himself in a whole new dimension. He also runs across a different version of trancers. These guys seem to be in control of this planet. Jack manages to assist a rebel group known as the \"Tunnel Rats\" crush the rule of the evil Lord Calaban.","poster":"/69yr3oxBpSgua26RJkFmsm7plTG.jpg","backdrop":"/5ism2HNUGuQi5a3ajYaN9ypMQMf.jpg","rank":5.2,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":8,"release_date":"1994-02-02T00:00:00.000Z"},{"id":47663,"title":"Trancers 5: Sudden Deth","year":1994,"overview":"Jack Deth is back for one more round with the trancers. Jack must attempt to find his way home from the other-dimensional world of Orpheus, where magic works and the trancers were the ruling class (before Trancers IV, that is). Unfortunately, Jack's quest to find the mystical Tiamond in the Castle of Unrelenting Terror may be thwarted by the return of Caliban, king of the trancers who was thought dead.","poster":"/epMaTjPDMbgC8TbW1ZToh4RNv0i.jpg","backdrop":"/an0xpUEX1P1BI80sCpkU1pSoREx.jpg","rank":5,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":9,"release_date":"1994-11-04T00:00:00.000Z"},{"id":261443,"title":"Angry Planet","year":2008,"overview":"A criminal sentenced to life on a prison planet reveals his true purpose: to extract revenge on the killers who murdered his family.","poster":"/ie5luS87ess1c5VgFhbGECJTQVK.jpg","backdrop":"/u4JBwlGZN8hGeLxwu7Q0WmibACp.jpg","rank":4.5,"genres":null,"status":null,"tagline":null,"runtime":null,"imdb_id":null,"type":"movie","credits":10,"release_date":"2008-01-01T00:00:00.000Z"}],"page":1,"total_results":11,"total_pages":1} \ No newline at end of file +{ + "results": [ + { + "id": 157336, + "title": "Interstellar", + "year": 2014, + "overview": "Interstellar chronicles the adventures of a group of explorers who make use of a newly discovered wormhole to surpass the limitations on human space travel and conquer the vast distances involved in an interstellar voyage.", + "poster": "/nBNZadXqJSdt05SHLqgT0HuC5Gm.jpg", + "backdrop": "/xu9zaAevzQ5nnrsXN6JcahLnG4i.jpg", + "rank": 8.2, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "release_date": "2014-11-05T00:00:00.000Z" + }, + { + "id": 301959, + "title": "Interstellar: Nolan's Odyssey", + "year": 2014, + "overview": "Behind the scenes of Christopher Nolan's sci-fi drama, which stars Matthew McConaughey and Anne Hathaway", + "poster": "/xZwUIPqBHyJ2QIfMPANOZ1mAld6.jpg", + "backdrop": "/bT5jpIZE50MI0COE8pOeq0kMpQo.jpg", + "rank": 7.9, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 1, + "release_date": "2014-11-05T00:00:00.000Z" + }, + { + "id": 398188, + "title": "Interstellar Wars", + "year": 2016, + "overview": "For Millennia the Aliien force has watched and waited, a brooding menace that has now at last decided to take over the Earth. Communications systems worldwide are sent into chaos by a strange atmospheric interference and this has turned into a global phenomenon. A massive spaceship headed towards Earth and smaller spaceships began to cover entire cities around the world. Suddenly, the wonder turns into horror as the spaceships destroy the cities with energy weapons. When the world counterattacks, the alien ships are invincible to military weapons. The survivors have to use their wits to kill the aliens, or die.", + "poster": "/cjvTebuqD8wmhchHE286ltVcbX6.jpg", + "backdrop": "/yTnHa6lgIv8rNneSNBDkBe8MnZe.jpg", + "rank": 3.8, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 2, + "release_date": "2016-05-23T00:00:00.000Z" + }, + { + "id": 287954, + "title": "Lolita from Interstellar Space", + "year": 2014, + "overview": "An undeniably beautiful alien is sent to Earth to study the complex mating rituals of human beings, which leads to the young interstellar traveler experiencing the passion that surrounds the centuries-old ritual of the species.", + "poster": "/buoq7zYO4J3ttkEAqEMWelPDC0G.jpg", + "backdrop": "/mgb6tVEieDYLpQt666ACzGz5cyE.jpg", + "rank": 7, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 3, + "release_date": "2014-03-08T00:00:00.000Z" + }, + { + "id": 336592, + "title": "The Science of Interstellar", + "year": 2014, + "overview": "The science of Christopher Nolan's sci-fi, Interstellar.", + "poster": "/6KBD7YSBjCfgBgHwpsQo3G3GGdx.jpg", + "backdrop": null, + "rank": 7.8, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 4, + "release_date": "2014-11-25T00:00:00.000Z" + }, + { + "id": 529107, + "title": "Inside Interstellar", + "year": 2015, + "overview": "Cast and crew of Christopher Nolan's 'Interstellar' discuss project origins, the film's imagery, ambitions, incorporating IMAX footage, the human element within the film, arm shooting locations outside of Calgary, the set construction and design, working with real corn, mechanical characters, including backstory, design, the blend of practical and digital effects in bringing them to life, the differences in the characters, the human performances behind the characters, the creative process behind the film's music, Icelandic locations, vehicle interiors, the processes of simulating the absence of gravity, the crucial end-film visuals and influence and inspiration for future generations", + "poster": "/vemBplPKQhVe5cRWL7kxtgp15Vq.jpg", + "backdrop": null, + "rank": 9, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 5, + "release_date": "2015-03-31T00:00:00.000Z" + }, + { + "id": 552531, + "title": "The Prom Goer's Interstellar Excursion", + "year": null, + "overview": "High schooler Bennett lands the prom date of his dreams, Sophie, just days before the dance. Not long after, he witnesses Sophie being abducted by aliens in the middle of the New Mexico desert.", + "poster": null, + "backdrop": null, + "rank": 0, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 6, + "release_date": null + }, + { + "id": 460616, + "title": "Interstellar Civil War: Shadows of the Empire", + "year": 2018, + "overview": "The Imperial Empire is attacked by an Alliance of rebels led by fanatical mystics. The ruler, Empress Nobu, the 8th generation of her family, wants to execute a bold plan to rescue a cyborg, Leah C6, trapped on the battle ravaged planet Endor. The Empress believes Leah C6 holds the secret to destroying the Alliance of Rebels before their insurgency can kill millions of citizens of the Empire. She recruits her heroic fleet commander, Lord General Luka Raan and asks him to gather a team from the Empire's elite soldiers, the Galactic Rangers. Raan assembles the team in the ruins of Endor which was attacked by depraved Rebels and outlaws led by, Kindo-Ker, a fanatical mystic in Dark Energy. The Galactic Rangers begin a desperate search to find and rescue Leah C6 before the Alliance Rebels can.", + "poster": "/1lDY7ZpEKOl3OaIQURjRbmFPfT8.jpg", + "backdrop": null, + "rank": 4, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 7, + "release_date": "2018-04-15T00:00:00.000Z" + }, + { + "id": 47662, + "title": "Trancers 4: Jack of Swords", + "year": 1994, + "overview": "Jack is now back in the future. He had since lost Lena, and finds out that he's lost his other wife Alice to none other than Harris. While heading out for another assignment, something goes awry with the TCL chamber. Jack finds himself in a whole new dimension. He also runs across a different version of trancers. These guys seem to be in control of this planet. Jack manages to assist a rebel group known as the \"Tunnel Rats\" crush the rule of the evil Lord Calaban.", + "poster": "/69yr3oxBpSgua26RJkFmsm7plTG.jpg", + "backdrop": "/5ism2HNUGuQi5a3ajYaN9ypMQMf.jpg", + "rank": 5.2, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 8, + "release_date": "1994-02-02T00:00:00.000Z" + }, + { + "id": 47663, + "title": "Trancers 5: Sudden Deth", + "year": 1994, + "overview": "Jack Deth is back for one more round with the trancers. Jack must attempt to find his way home from the other-dimensional world of Orpheus, where magic works and the trancers were the ruling class (before Trancers IV, that is). Unfortunately, Jack's quest to find the mystical Tiamond in the Castle of Unrelenting Terror may be thwarted by the return of Caliban, king of the trancers who was thought dead.", + "poster": "/epMaTjPDMbgC8TbW1ZToh4RNv0i.jpg", + "backdrop": "/an0xpUEX1P1BI80sCpkU1pSoREx.jpg", + "rank": 5, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 9, + "release_date": "1994-11-04T00:00:00.000Z" + }, + { + "id": 261443, + "title": "Angry Planet", + "year": 2008, + "overview": "A criminal sentenced to life on a prison planet reveals his true purpose: to extract revenge on the killers who murdered his family.", + "poster": "/ie5luS87ess1c5VgFhbGECJTQVK.jpg", + "backdrop": "/u4JBwlGZN8hGeLxwu7Q0WmibACp.jpg", + "rank": 4.5, + "genres": null, + "status": null, + "tagline": null, + "runtime": null, + "imdb_id": null, + "type": "movie", + "credits": 10, + "release_date": "2008-01-01T00:00:00.000Z" + } + ], + "page": 1, + "total_results": 11, + "total_pages": 1 +} -- 2.34.1 From c533d8868a5156eb80779bc824cf7c054309165d Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Fri, 19 Aug 2022 16:03:04 +0200 Subject: [PATCH 06/26] Fixed eslint errors & improved a lot of error handling --- src/cache/redis.js | 19 +- src/config/configuration.js | 1 + src/config/field.js | 2 +- src/notifications/sms.js | 11 +- src/pirate/pirateRepository.js | 19 +- src/plex/plex.js | 174 ++++++++-------- src/plex/plexRepository.js | 88 ++++----- src/plex/requestRepository.js | 96 +++++---- src/request/request.js | 30 ++- src/tautulli/tautulli.js | 17 +- src/tmdb/tmdb.js | 186 ++++++++++-------- src/user/userRepository.js | 120 ++++++----- src/webserver/app.js | 10 +- .../controllers/list/listController.js | 22 +-- src/webserver/controllers/movie/credits.js | 15 +- src/webserver/controllers/movie/info.js | 29 +-- .../controllers/movie/releaseDates.js | 15 +- src/webserver/controllers/person/credits.js | 15 +- src/webserver/controllers/person/info.js | 21 +- .../controllers/request/fetchAllRequests.js | 7 +- .../controllers/request/getRequest.js | 7 +- .../controllers/search/movieSearch.js | 15 +- .../controllers/search/multiSearch.js | 15 +- .../controllers/search/personSearch.js | 15 +- .../controllers/search/showSearch.js | 7 +- src/webserver/controllers/show/credits.js | 15 +- src/webserver/controllers/show/info.js | 21 +- 27 files changed, 496 insertions(+), 496 deletions(-) diff --git a/src/cache/redis.js b/src/cache/redis.js index 9318a31..fdee990 100644 --- a/src/cache/redis.js +++ b/src/cache/redis.js @@ -3,29 +3,29 @@ const configuration = require("../config/configuration").getInstance(); let client; try { - const redis = require("redis"); - console.log("Trying to connect with redis.."); + const redis = require("redis"); // eslint-disable-line global-require + console.log("Trying to connect with redis.."); // eslint-disable-line no-console const host = configuration.get("redis", "host"); const port = configuration.get("redis", "port"); - console.log(`redis://${host}:${port}`); + console.log(`redis://${host}:${port}`); // eslint-disable-line no-console client = redis.createClient({ url: `redis://${host}:${port}` }); - client.on("connect", () => console.log("Redis connection established!")); + client.on("connect", () => console.log("Redis connection established!")); // eslint-disable-line no-console client.on("error", () => { client.quit(); - console.error("Unable to connect to redis, setting up redis-mock."); + console.error("Unable to connect to redis, setting up redis-mock."); // eslint-disable-line no-console client = { - get() { - console.log("redis-dummy get", arguments[0]); + get(command) { + console.log(`redis-dummy get: ${command}`); // eslint-disable-line no-console return Promise.resolve(); }, - set() { - console.log("redis-dummy set", arguments[0]); + set(command) { + console.log(`redis-dummy set: ${command}`); // eslint-disable-line no-console return Promise.resolve(); } }; @@ -41,6 +41,7 @@ function set(key, value, TTL = 10800) { // successfully set value with key, now set TTL for key client.expire(key, TTL, e => { if (e) + // eslint-disable-next-line no-console console.error( "Unexpected error while setting expiration for key:", key, diff --git a/src/config/configuration.js b/src/config/configuration.js index 9b9a192..175a0a7 100644 --- a/src/config/configuration.js +++ b/src/config/configuration.js @@ -6,6 +6,7 @@ let instance = null; class Config { constructor() { this.location = Config.determineLocation(); + // eslint-disable-next-line import/no-dynamic-require, global-require this.fields = require(`${this.location}`); } diff --git a/src/config/field.js b/src/config/field.js index 4b86c80..ef4b3d1 100644 --- a/src/config/field.js +++ b/src/config/field.js @@ -46,7 +46,7 @@ class Field { } static base64Decode(string) { - return new Buffer(string, "base64").toString("utf-8"); + return Buffer.from(string, "base64").toString("utf-8"); } } diff --git a/src/notifications/sms.js b/src/notifications/sms.js index a8c80d7..b9e6f41 100644 --- a/src/notifications/sms.js +++ b/src/notifications/sms.js @@ -14,8 +14,8 @@ const sendSMS = message => { const apiKey = configuration.get("sms", "apikey"); if (!apiKey) { - console.warning("api key for sms not set, cannot send sms."); - return null; + console.warning("api key for sms not set, cannot send sms."); // eslint-disable-line no-console + return Promise.resolve(null); } const sender = configuration.get("sms", "sender"); @@ -32,10 +32,9 @@ const sendSMS = message => { recipients: [{ msisdn: `47${recipient}` }] } }, - function (err, r, body) { - const smsError = new SMSUnexpectedError(err || body); - console.error(smsError.message); - resolve(); + (err, r, body) => { + if (err) reject(new SMSUnexpectedError(err || body)); + resolve(body); } ); }); diff --git a/src/pirate/pirateRepository.js b/src/pirate/pirateRepository.js index 455ad0a..36849b2 100644 --- a/src/pirate/pirateRepository.js +++ b/src/pirate/pirateRepository.js @@ -46,8 +46,10 @@ async function callPythonAddMagnet(url, callback) { }); } -async function SearchPiratebay(query) { - if (query && query.includes("+")) { +async function SearchPiratebay(_query) { + let query = String(_query); + + if (query?.includes("+")) { query = query.replace("+", "%20"); } @@ -60,7 +62,7 @@ async function SearchPiratebay(query) { .catch(() => find(query, (err, results) => { if (err) { - console.log("THERE WAS A FUCKING ERROR!\n", err); + console.log("THERE WAS A FUCKING ERROR!\n", err); // eslint-disable-line no-console reject(Error("There was a error when searching for torrents")); } @@ -74,8 +76,8 @@ async function SearchPiratebay(query) { ); } -async function AddMagnet(magnet, name, tmdbId) { - return await new Promise((resolve, reject) => +function AddMagnet(magnet, name, tmdbId) { + return new Promise((resolve, reject) => callPythonAddMagnet(magnet, (err, results) => { if (err) { /* eslint-disable no-console */ @@ -86,11 +88,10 @@ async function AddMagnet(magnet, name, tmdbId) { console.log("result/error:", err, results); const database = establishedDatabase; - const insert_query = - "INSERT INTO requested_torrent(magnet,torrent_name,tmdb_id) \ - VALUES (?,?,?)"; + const insertQuery = + "INSERT INTO requested_torrent(magnet,torrent_name,tmdb_id) VALUES (?,?,?)"; - const response = database.run(insert_query, [magnet, name, tmdbId]); + const response = database.run(insertQuery, [magnet, name, tmdbId]); console.log(`Response from requsted_torrent insert: ${response}`); resolve({ success: true }); diff --git a/src/plex/plex.js b/src/plex/plex.js index 628c862..01b9cee 100644 --- a/src/plex/plex.js +++ b/src/plex/plex.js @@ -2,17 +2,28 @@ const fetch = require("node-fetch"); const convertPlexToMovie = require("./convertPlexToMovie"); const convertPlexToShow = require("./convertPlexToShow"); const convertPlexToEpisode = require("./convertPlexToEpisode"); - const redisCache = require("../cache/redis"); -const sanitize = string => string.toLowerCase().replace(/[^\w]/gi, ""); +class PlexRequestTimeoutError extends Error { + constructor() { + const message = "Timeout: Plex did not respond."; -function fixedEncodeURIComponent(str) { - return encodeURIComponent(str).replace(/[!'()*]/g, function (c) { - return `%${c.charCodeAt(0).toString(16).toUpperCase()}`; - }); + super(message); + this.statusCode = 408; + } } +class PlexUnexpectedError extends Error { + constructor(plexError = null) { + const message = "Unexpected plex error occured."; + + super(message); + this.statusCode = 500; + this.plexError = plexError; + } +} + +const sanitize = string => string.toLowerCase().replace(/[^\w]/gi, ""); const matchingTitleAndYear = (plex, tmdb) => { let matchingTitle; let matchingYear; @@ -30,25 +41,62 @@ const matchingTitleAndYear = (plex, tmdb) => { return matchingTitle && matchingYear; }; +function fixedEncodeURIComponent(str) { + return encodeURIComponent(str).replace(/[!'()*]/g, c => { + return `%${c.charCodeAt(0).toString(16).toUpperCase()}`; + }); +} + +function matchTmdbAndPlexMedia(plex, tmdb) { + let match; + + if (plex === null || tmdb === null) return false; + + if (plex instanceof Array) { + const possibleMatches = plex.map(plexItem => + matchingTitleAndYear(plexItem, tmdb) + ); + match = possibleMatches.includes(true); + } else { + match = matchingTitleAndYear(plex, tmdb); + } + + return match; +} + const successfullResponse = response => { - if (response && response.MediaContainer) return response; - - if ( - response === null || - response.status === null || - response.statusText === null - ) { - throw Error("Unable to decode response"); - } - const { status, statusText } = response; - - if (status === 200) { - return response.json(); + if (status !== 200) { + throw new PlexUnexpectedError(statusText); } - throw { message: statusText, status }; + + if (response?.MediaContainer) return response; + + return response.json(); }; +function mapResults(response) { + if (response?.MediaContainer?.Hub === null) { + return []; + } + + return response.MediaContainer.Hub.filter(category => category.size > 0) + .map(category => { + if (category.type === "movie") { + return category.Metadata.map(convertPlexToMovie); + } + if (category.type === "show") { + return category.Metadata.map(convertPlexToShow); + } + if (category.type === "episode") { + return category.Metadata.map(convertPlexToEpisode); + } + + return null; + }) + .filter(result => result !== null); +} + class Plex { constructor(ip, port = 32400, cache = null) { this.plexIP = ip; @@ -72,44 +120,23 @@ class Plex { return new Promise((resolve, reject) => this.cache .get(cacheKey) - .then(machineInfo => resolve(machineInfo.machineIdentifier)) + .then(machineInfo => resolve(machineInfo?.machineIdentifier)) .catch(() => fetch(url, options)) .then(response => response.json()) .then(machineInfo => this.cache.set(cacheKey, machineInfo.MediaContainer, 2628000) ) - .then(machineInfo => resolve(machineInfo.machineIdentifier)) + .then(machineInfo => resolve(machineInfo?.machineIdentifier)) .catch(error => { - if (error !== undefined && error.type === "request-timeout") { - reject({ - message: "Plex did not respond", - status: 408, - success: false - }); + if (error?.type === "request-timeout") { + reject(new PlexRequestTimeoutError()); } - reject(error); + reject(new PlexUnexpectedError()); }) ); } - matchTmdbAndPlexMedia(plex, tmdb) { - let match; - - if (plex === null || tmdb === null) return false; - - if (plex instanceof Array) { - const possibleMatches = plex.map(plexItem => - matchingTitleAndYear(plexItem, tmdb) - ); - match = possibleMatches.includes(true); - } else { - match = matchingTitleAndYear(plex, tmdb); - } - - return match; - } - async existsInPlex(tmdb) { const plexMatch = await this.findPlexItemByTitleAndYear( tmdb.title, @@ -123,7 +150,7 @@ class Plex { return this.search(title).then(plexResults => { const matchesInPlex = plexResults.map(plex => - this.matchTmdbAndPlexMedia(plex, query) + matchTmdbAndPlexMedia(plex, query) ); const matchesIndex = matchesInPlex.findIndex(el => el === true); return matchesInPlex !== -1 ? plexResults[matchesIndex] : null; @@ -171,18 +198,14 @@ class Plex { .catch(() => fetch(url, options)) // else fetch fresh data .then(successfullResponse) .then(results => this.cache.set(cacheKey, results, 21600)) // 6 hours - .then(this.mapResults) + .then(mapResults) .then(resolve) .catch(error => { - if (error !== undefined && error.type === "request-timeout") { - reject({ - message: "Plex did not respond", - status: 408, - success: false - }); + if (error?.type === "request-timeout") { + reject(new PlexRequestTimeoutError()); } - reject(error); + reject(new PlexUnexpectedError()); }) ); } @@ -195,40 +218,13 @@ class Plex { const query = title; const cacheKey = `${this.cacheTags.search}/${query}*`; - this.cache.del( - cacheKey, - (error, - response => { - if (response === 1) return true; - - // TODO improve cache key matching by lowercasing it on the backend. - // what do we actually need to check for if the key was deleted or not - // it might be an error or another response code. - console.log("Unable to delete, key might not exists"); - }) - ); - } - - mapResults(response) { - if (response?.MediaContainer?.Hub === null) { - return []; - } - - return response.MediaContainer.Hub.filter(category => category.size > 0) - .map(category => { - if (category.type === "movie") { - return category.Metadata; - } - if (category.type === "show") { - return category.Metadata.map(convertPlexToShow); - } - if (category.type === "episode") { - return category.Metadata.map(convertPlexToEpisode); - } - - return null; - }) - .filter(result => result !== null); + this.cache.del(cacheKey, (error, response) => { + // TODO improve cache key matching by lowercasing it on the backend. + // what do we actually need to check for if the key was deleted or not + // it might be an error or another response code. + console.log("Unable to delete, key might not exists"); + return response === 1; + }); } } diff --git a/src/plex/plexRepository.js b/src/plex/plexRepository.js index 3bc29ac..472111f 100644 --- a/src/plex/plexRepository.js +++ b/src/plex/plexRepository.js @@ -2,17 +2,54 @@ const rp = require("request-promise"); const convertPlexToSeasoned = require("./convertPlexToSeasoned"); const convertPlexToStream = require("./convertPlexToStream"); +// eslint-disable-next-line +function addAttributeIfTmdbInPlex(_tmdb, plexResult) { + const tmdb = { ..._tmdb }; + + if (plexResult?.results?.length > 0) { + plexResult.results.map(plexItem => { + tmdb.matchedInPlex = + tmdb.title === plexItem.title && tmdb.year === plexItem.year; + return tmdb; + }); + } else { + tmdb.matchedInPlex = false; + } + + return Promise.resolve(tmdb); +} + +function mapResults(response) { + return Promise.resolve() + .then(() => { + if (!response?.MediaContainer?.Metadata) return [[], 0]; + + const mappedResults = response.MediaContainer.Metadata.filter(element => { + return element.type === "movie" || element.type === "show"; + }).map(element => convertPlexToSeasoned(element)); + return [mappedResults, mappedResults.length]; + }) + .catch(error => { + throw new Error(error); + }); +} + class PlexRepository { constructor(plexIP) { this.plexIP = plexIP; } - inPlex(tmdbResult) { - return Promise.resolve() - .then(() => this.search(tmdbResult.title)) - .then(plexResult => this.compareTmdbToPlex(tmdbResult, plexResult)) - .catch(error => { - console.log(error); + inPlex(_tmdbResult) { + const tmdbResult = { ..._tmdbResult }; + this.search(tmdbResult.title) + .then(plexResult => addAttributeIfTmdbInPlex(tmdbResult, plexResult)) + .catch(() => { + /** + * If something crashes with search from this function it probably + * fine to set the `matchedInPlex` attribute to false and return + * original tmdb object + * */ + tmdbResult.matchedInPlex = false; return tmdbResult; }); @@ -32,50 +69,13 @@ class PlexRepository { }; return rp(options) - .catch(error => { - console.log(error); - throw new Error("Unable to search plex."); - }) - .then(result => this.mapResults(result)) + .then(result => mapResults(result)) .then(([mappedResults, resultCount]) => ({ results: mappedResults, total_results: resultCount })); } - compareTmdbToPlex(tmdb, plexResult) { - return Promise.resolve().then(() => { - if (plexResult.results.length === 0) { - tmdb.matchedInPlex = false; - } else { - // console.log('plex and tmdb:', plexResult, '\n', tmdb) - plexResult.results.map(plexItem => { - if (tmdb.title === plexItem.title && tmdb.year === plexItem.year) - tmdb.matchedInPlex = true; - return tmdb; - }); - } - return tmdb; - }); - } - - mapResults(response) { - return Promise.resolve() - .then(() => { - if (!response.MediaContainer.hasOwnProperty("Metadata")) return [[], 0]; - - const mappedResults = response.MediaContainer.Metadata.filter( - element => { - return element.type === "movie" || element.type === "show"; - } - ).map(element => convertPlexToSeasoned(element)); - return [mappedResults, mappedResults.length]; - }) - .catch(error => { - throw new Error(error); - }); - } - nowPlaying() { const options = { uri: `http://${this.plexIP}:32400/status/sessions`, diff --git a/src/plex/requestRepository.js b/src/plex/requestRepository.js index 8a01d5f..85caaf1 100644 --- a/src/plex/requestRepository.js +++ b/src/plex/requestRepository.js @@ -28,15 +28,15 @@ class RequestRepository { }; } - search(query, type, page) { - return Promise.resolve() - .then(() => tmdb.search(query, type, page)) + static search(query, type, page) { + return tmdb + .search(query, type, page) .catch(error => Error(`error in the house${error}`)); } lookup(identifier, type = "movie") { - return Promise.resolve() - .then(() => tmdb.lookup(identifier, type)) + return tmdb + .lookup(identifier, type) .then(tmdbMovie => this.checkID(tmdbMovie)) .then(tmdbMovie => plexRepository.inPlex(tmdbMovie)) .catch(error => { @@ -44,18 +44,16 @@ class RequestRepository { }); } - checkID(tmdbMovie) { - return Promise.resolve() - .then(() => - this.database.get(this.queries.checkIfIdRequested, [ - tmdbMovie.id, - tmdbMovie.type - ]) - ) + checkID(_tmdbMovie) { + const tmdbMovie = _tmdbMovie; + + return this.database + .get(this.queries.checkIfIdRequested, [tmdbMovie.id, tmdbMovie.type]) .then((result, error) => { if (error) { throw new Error(error); } + tmdbMovie.requested = !!result; return tmdbMovie; }); @@ -67,44 +65,41 @@ class RequestRepository { * @returns {Promise} If nothing has gone wrong. */ sendRequest(identifier, type, ip, userAgent, user) { - return Promise.resolve() - .then(() => tmdb.lookup(identifier, type)) - .then(movie => { - const username = user === undefined ? undefined : user.username; - // Add request to database - return this.database.run(this.queries.insertRequest, [ - movie.id, - movie.title, - movie.year, - movie.poster_path, - movie.background_path, - username, - ip, - userAgent, - movie.type - ]); - }); - } - - fetchRequested(status, page = "1", type = "%") { - return Promise.resolve().then(() => { - if ( - status === "requested" || - status === "downloading" || - status === "downloaded" - ) - return this.database.all(this.queries.fetchRequestedItemsByStatus, [ - status, - type, - page - ]); - return this.database.all(this.queries.fetchRequestedItems, page); + return tmdb.lookup(identifier, type).then(movie => { + const username = user === undefined ? undefined : user.username; + // Add request to database + return this.database.run(this.queries.insertRequest, [ + movie.id, + movie.title, + movie.year, + movie.poster_path, + movie.background_path, + username, + ip, + userAgent, + movie.type + ]); }); } + fetchRequested(status, page = "1", type = "%") { + if ( + status === "requested" || + status === "downloading" || + status === "downloaded" + ) + return this.database.all(this.queries.fetchRequestedItemsByStatus, [ + status, + type, + page + ]); + + return this.database.all(this.queries.fetchRequestedItems, page); + } + userRequests(username) { - return Promise.resolve() - .then(() => this.database.all(this.queries.userRequests, username)) + return this.database + .all(this.queries.userRequests, username) .catch(error => { if (String(error).includes("no such column")) { throw new Error("Username not found"); @@ -113,8 +108,11 @@ class RequestRepository { }) .then(result => { // TODO do a correct mapping before sending, not just a dump of the database - result.map(item => (item.poster = item.poster_path)); - return result; + return result.map(_item => { + const item = { ..._item }; + item.poster = item.poster_path; + return item; + }); }); } diff --git a/src/request/request.js b/src/request/request.js index 922e933..3f3d91b 100644 --- a/src/request/request.js +++ b/src/request/request.js @@ -1,10 +1,18 @@ const assert = require("assert"); -const configuration = require("../config/configuration").getInstance(); -const TMDB = require("../tmdb/tmdb"); - -const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); +// const configuration = require("../config/configuration").getInstance(); +// const TMDB = require("../tmdb/tmdb"); const establishedDatabase = require("../database/database"); +// const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); + +// function mapToTmdbByType(rows) { +// return rows.map(row => { +// if (row.type === "movie") return tmdb.movieInfo(row.id); +// if (row.type === "show") return tmdb.showInfo(row.id); +// return null; +// }); +// } + class RequestRepository { constructor(database) { this.database = database || establishedDatabase; @@ -30,14 +38,6 @@ class RequestRepository { }; } - mapToTmdbByType(rows) { - return rows.map(row => { - if (row.type === "movie") return tmdb.movieInfo(row.id); - if (row.type === "show") return tmdb.showInfo(row.id); - return null; - }); - } - /** * Add tmdb movie|show to requests * @param {tmdb} tmdb class of movie|show to add @@ -69,7 +69,6 @@ class RequestRepository { ) { throw new Error("This id is already requested", error.message); } - console.log("Error @ request.addTmdb:", error); throw new Error("Could not add request"); }); } @@ -104,7 +103,7 @@ class RequestRepository { */ fetchAll(_page = 1, filter = null) { // TODO implemented sort and filter - const page = parseInt(_page); + const page = parseInt(_page, 10); let fetchQuery = this.queries.fetchAll; let fetchTotalResults = this.queries.totalRequests; let fetchParams = [page]; @@ -143,7 +142,7 @@ class RequestRepository { totalRequests ]; - return this.mapToTmdbByType(rows); + // return mapToTmdbByType(rows); }) .then(([result, totalPages, totalRequests]) => Promise.resolve({ @@ -154,7 +153,6 @@ class RequestRepository { }) ) .catch(error => { - console.log(error); throw error; }); } diff --git a/src/tautulli/tautulli.js b/src/tautulli/tautulli.js index cccd8a7..f5fdf3d 100644 --- a/src/tautulli/tautulli.js +++ b/src/tautulli/tautulli.js @@ -10,6 +10,10 @@ class TautulliUnexpectedError extends Error { } } +function logTautulliError(error) { + throw new TautulliUnexpectedError(error); +} + class Tautulli { constructor(apiKey, ip, port) { this.apiKey = apiKey; @@ -26,11 +30,6 @@ class Tautulli { return url; } - /* eslint-disable-next-line class-methods-use-this */ - logTautulliError(error) { - throw new TautulliUnexpectedError(error); - } - getPlaysByDayOfWeek(plexUserId, days, yAxis) { const url = this.buildUrlWithCmdAndUserid( "get_plays_by_dayofweek", @@ -41,7 +40,7 @@ class Tautulli { return fetch(url.href) .then(resp => resp.json()) - .catch(error => this.logTautulliError(error)); + .catch(error => logTautulliError(error)); } getPlaysByDays(plexUserId, days, yAxis) { @@ -51,7 +50,7 @@ class Tautulli { return fetch(url.href) .then(resp => resp.json()) - .catch(error => this.logTautulliError(error)); + .catch(error => logTautulliError(error)); } watchTimeStats(plexUserId) { @@ -63,7 +62,7 @@ class Tautulli { return fetch(url.href) .then(resp => resp.json()) - .catch(error => this.logTautulliError(error)); + .catch(error => logTautulliError(error)); } viewHistory(plexUserId) { @@ -74,7 +73,7 @@ class Tautulli { return fetch(url.href) .then(resp => resp.json()) - .catch(error => this.logTautulliError(error)); + .catch(error => logTautulliError(error)); } } diff --git a/src/tmdb/tmdb.js b/src/tmdb/tmdb.js index bddb86f..9adb346 100644 --- a/src/tmdb/tmdb.js +++ b/src/tmdb/tmdb.js @@ -20,14 +20,23 @@ class TMDBUnauthorizedError extends Error { } class TMDBUnexpectedError extends Error { - constructor(type) { + constructor(type, errorMessage) { const message = `An unexpected error occured while fetching ${type} from tmdb`; super(message); + this.errorMessage = errorMessage; this.statusCode = 500; } } +class TMDBNotReachableError extends Error { + constructor( + message = "TMDB api not reachable, check your internet connection" + ) { + super(message); + } +} + const tmdbErrorResponse = (error, type = null) => { if (error.status === 404) { const message = error.response.body.status_message; @@ -35,11 +44,45 @@ const tmdbErrorResponse = (error, type = null) => { throw new TMDBNotFoundError(`${message.slice(0, -1)} in tmdb.`); } else if (error.status === 401) { throw new TMDBUnauthorizedError(error?.response?.body?.status_message); + } else if (error?.code === "ENOTFOUND") { + throw new TMDBNotReachableError(); } - throw new TMDBUnexpectedError(type); + throw new TMDBUnexpectedError(type, error); }; +/** + * Maps our response from tmdb api to a movie/show object. + * @param {String} response from tmdb. + * @param {String} The type declared in listSearch. + * @returns {Promise} dict with tmdb results, mapped as movie/show objects. + */ +function mapResults(response, type = null) { + const results = response?.results?.map(result => { + if (type === "movie" || result.media_type === "movie") { + const movie = Movie.convertFromTmdbResponse(result); + return movie.createJsonResponse(); + } + if (type === "show" || result.media_type === "tv") { + const show = Show.convertFromTmdbResponse(result); + return show.createJsonResponse(); + } + if (type === "person" || result.media_type === "person") { + const person = Person.convertFromTmdbResponse(result); + return person.createJsonResponse(); + } + + return {}; + }); + + return { + results, + page: response?.page, + total_results: response?.total_results, + total_pages: response?.total_pages + }; +} + class TMDB { constructor(apiKey, cache, tmdbLibrary) { this.tmdbLibrary = tmdbLibrary || moviedb(apiKey); @@ -69,15 +112,17 @@ class TMDB { this.defaultTTL = 86400; } - getFromCacheOrFetchFromTmdb(cacheKey, tmdbMethod, query) { - return new Promise((resolve, reject) => - this.cache - .get(cacheKey) - .then(resolve) - .catch(() => this.tmdb(tmdbMethod, query)) - .then(resolve) - .catch(error => reject(tmdbErrorResponse(error, tmdbMethod))) - ); + async getFromCacheOrFetchFromTmdb(cacheKey, tmdbMethod, query) { + try { + const result = await this.cache.get(cacheKey); + if (!result) throw new Error(); + + return result; + } catch { + return this.tmdb(tmdbMethod, query) + .then(result => this.cache.set(cacheKey, result, this.defaultTTL)) + .catch(error => tmdbErrorResponse(error, tmdbMethod)); + } } /** @@ -91,9 +136,9 @@ class TMDB { const query = { id: identifier }; const cacheKey = `tmdb/${this.cacheTags.movieInfo}:${identifier}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "movieInfo", query) - .then(movie => this.cache.set(cacheKey, movie, this.defaultTTL)) - .then(movie => Movie.convertFromTmdbResponse(movie)); + return this.getFromCacheOrFetchFromTmdb(cacheKey, "movieInfo", query).then( + movie => Movie.convertFromTmdbResponse(movie) + ); } /** @@ -105,9 +150,11 @@ class TMDB { const query = { id: identifier }; const cacheKey = `tmdb/${this.cacheTags.movieCredits}:${identifier}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "movieCredits", query) - .then(credits => this.cache.set(cacheKey, credits, this.defaultTTL)) - .then(credits => Credits.convertFromTmdbResponse(credits)); + return this.getFromCacheOrFetchFromTmdb( + cacheKey, + "movieCredits", + query + ).then(credits => Credits.convertFromTmdbResponse(credits)); } /** @@ -123,11 +170,7 @@ class TMDB { cacheKey, "movieReleaseDates", query - ) - .then(releaseDates => - this.cache.set(cacheKey, releaseDates, this.defaultTTL) - ) - .then(releaseDates => ReleaseDates.convertFromTmdbResponse(releaseDates)); + ).then(releaseDates => ReleaseDates.convertFromTmdbResponse(releaseDates)); } /** @@ -140,18 +183,18 @@ class TMDB { const query = { id: identifier }; const cacheKey = `tmdb/${this.cacheTags.showInfo}:${identifier}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "tvInfo", query) - .then(show => this.cache.set(cacheKey, show, this.defaultTTL)) - .then(show => Show.convertFromTmdbResponse(show)); + return this.getFromCacheOrFetchFromTmdb(cacheKey, "tvInfo", query).then( + show => Show.convertFromTmdbResponse(show) + ); } showCredits(identifier) { const query = { id: identifier }; const cacheKey = `tmdb/${this.cacheTags.showCredits}:${identifier}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "tvCredits", query) - .then(credits => this.cache.set(cacheKey, credits, this.defaultTTL)) - .then(credits => Credits.convertFromTmdbResponse(credits)); + return this.getFromCacheOrFetchFromTmdb(cacheKey, "tvCredits", query).then( + credits => Credits.convertFromTmdbResponse(credits) + ); } /** @@ -164,9 +207,9 @@ class TMDB { const query = { id: identifier }; const cacheKey = `tmdb/${this.cacheTags.personInfo}:${identifier}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "personInfo", query) - .then(person => this.cache.set(cacheKey, person, this.defaultTTL)) - .then(person => Person.convertFromTmdbResponse(person)); + return this.getFromCacheOrFetchFromTmdb(cacheKey, "personInfo", query).then( + person => Person.convertFromTmdbResponse(person) + ); } personCredits(identifier) { @@ -177,18 +220,18 @@ class TMDB { cacheKey, "personCombinedCredits", query - ) - .then(credits => this.cache.set(cacheKey, credits, this.defaultTTL)) - .then(credits => Credits.convertFromTmdbResponse(credits)); + ).then(credits => Credits.convertFromTmdbResponse(credits)); } multiSearch(searchQuery, page = 1, includeAdult = true) { const query = { query: searchQuery, page, include_adult: includeAdult }; const cacheKey = `tmdb/${this.cacheTags.multiSearch}:${page}:${searchQuery}:${includeAdult}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "searchMulti", query) - .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) - .then(response => this.mapResults(response)); + return this.getFromCacheOrFetchFromTmdb( + cacheKey, + "searchMulti", + query + ).then(response => mapResults(response)); } /** @@ -205,9 +248,11 @@ class TMDB { }; const cacheKey = `tmdb/${this.cacheTags.movieSearch}:${page}:${searchQuery}:${includeAdult}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "searchMovie", tmdbquery) - .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) - .then(response => this.mapResults(response, "movie")); + return this.getFromCacheOrFetchFromTmdb( + cacheKey, + "searchMovie", + tmdbquery + ).then(response => mapResults(response, "movie")); } /** @@ -224,9 +269,11 @@ class TMDB { }; const cacheKey = `tmdb/${this.cacheTags.showSearch}:${page}:${searchQuery}:${includeAdult}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "searchTv", tmdbquery) - .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) - .then(response => this.mapResults(response, "show")); + return this.getFromCacheOrFetchFromTmdb( + cacheKey, + "searchTv", + tmdbquery + ).then(response => mapResults(response, "show")); } /** @@ -243,60 +290,29 @@ class TMDB { }; const cacheKey = `tmdb/${this.cacheTags.personSearch}:${page}:${searchQuery}:${includeAdult}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, "searchPerson", tmdbquery) - .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) - .then(response => this.mapResults(response, "person")); + return this.getFromCacheOrFetchFromTmdb( + cacheKey, + "searchPerson", + tmdbquery + ).then(response => mapResults(response, "person")); } movieList(listName, page = 1) { const query = { page }; const cacheKey = `tmdb/${this.cacheTags[listName]}:${page}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query) - .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) - .then(response => this.mapResults(response, "movie")); + return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query).then( + response => mapResults(response, "movie") + ); } showList(listName, page = 1) { const query = { page }; const cacheKey = `tmdb/${this.cacheTags[listName]}:${page}`; - return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query) - .then(response => this.cache.set(cacheKey, response, this.defaultTTL)) - .then(response => this.mapResults(response, "show")); - } - - /** - * Maps our response from tmdb api to a movie/show object. - * @param {String} response from tmdb. - * @param {String} The type declared in listSearch. - * @returns {Promise} dict with tmdb results, mapped as movie/show objects. - */ - // eslint-disable-next-line class-methods-use-this - mapResults(response, type = undefined) { - const results = response?.results?.map(result => { - if (type === "movie" || result.media_type === "movie") { - const movie = Movie.convertFromTmdbResponse(result); - return movie.createJsonResponse(); - } - if (type === "show" || result.media_type === "tv") { - const show = Show.convertFromTmdbResponse(result); - return show.createJsonResponse(); - } - if (type === "person" || result.media_type === "person") { - const person = Person.convertFromTmdbResponse(result); - return person.createJsonResponse(); - } - - return {}; - }); - - return { - results, - page: response.page, - total_results: response.total_results, - total_pages: response.total_pages - }; + return this.getFromCacheOrFetchFromTmdb(cacheKey, listName, query).then( + response => mapResults(response, "show") + ); } /** diff --git a/src/user/userRepository.js b/src/user/userRepository.js index 6022f48..d23f0d4 100644 --- a/src/user/userRepository.js +++ b/src/user/userRepository.js @@ -1,6 +1,69 @@ const assert = require("assert"); const establishedDatabase = require("../database/database"); +class LinkPlexUserError extends Error { + constructor(errorMessage = null) { + const message = + "An unexpected error occured while linking plex and seasoned accounts"; + super(message); + + this.statusCode = 500; + this.errorMessage = errorMessage; + this.source = "database"; + } +} + +class UnlinkPlexUserError extends Error { + constructor(errorMessage = null) { + const message = + "An unexpected error occured while unlinking plex and seasoned accounts"; + super(message); + + this.statusCode = 500; + this.errorMessage = errorMessage; + this.source = "database"; + } +} + +class UnexpectedUserSettingsError extends Error { + constructor(errorMessage = null) { + const message = + "An unexpected error occured while fetching settings for your account"; + super(message); + + this.statusCode = 500; + this.errorMessage = errorMessage; + this.source = "database"; + } +} + +class NoSettingsUserNotFoundError extends Error { + constructor() { + const message = "User not found, no settings to get"; + super(message); + + this.statusCode = 404; + } +} + +const rejectUnexpectedDatabaseError = ( + message, + status, + error, + reject = null +) => { + const body = { + status, + message, + source: "seasoned database" + }; + + if (reject == null) { + return new Promise((_, reject) => reject(body)); + } + return reject(body); +}; + class UserRepository { constructor(database) { this.database = database || establishedDatabase; @@ -77,14 +140,7 @@ class UserRepository { this.database .run(this.queries.link, [plexUserID, username]) .then(row => resolve(row)) - .catch(error => - reject({ - status: 500, - message: - "An unexpected error occured while linking plex and seasoned accounts", - source: "seasoned database" - }) - ); + .catch(error => reject(new LinkPlexUserError(error))); }); } @@ -98,14 +154,7 @@ class UserRepository { this.database .run(this.queries.unlink, username) .then(row => resolve(row)) - .catch(error => - reject({ - status: 500, - message: - "An unexpected error occured while unlinking plex and seasoned accounts", - source: "seasoned database" - }) - ); + .catch(error => reject(new UnlinkPlexUserError(error))); }); } @@ -131,6 +180,7 @@ class UserRepository { .get(this.queries.getSettings, username) .then(async row => { if (row == null) { + // eslint-disable-next-line no-console console.debug( `settings do not exist for user: ${username}. Creating settings entry.` ); @@ -146,23 +196,13 @@ class UserRepository { reject(error); } } else { - reject({ - status: 404, - message: "User not found, no settings to get" - }); + reject(new NoSettingsUserNotFoundError()); } } resolve(row); }) - .catch(() => - reject({ - status: 500, - message: - "An unexpected error occured while fetching settings for your account", - source: "seasoned database" - }) - ); + .catch(error => reject(new UnexpectedUserSettingsError(error))); }); } @@ -173,10 +213,10 @@ class UserRepository { * @param {String} emoji * @returns {Promsie} */ - updateSettings(username, darkMode = null, emoji = null) { + updateSettings(username, _darkMode = null, _emoji = null) { const settings = this.getSettings(username); - darkMode = darkMode ? darkMode : settings.darkMode; - emoji = emoji ? emoji : settings.emoji; + const darkMode = _darkMode || settings.darkMode; + const emoji = _emoji || settings.emoji; return this.dbUpdateSettings(username, darkMode, emoji).catch(error => { if (error.status && error.message) { @@ -223,22 +263,4 @@ class UserRepository { } } -const rejectUnexpectedDatabaseError = ( - message, - status, - error, - reject = null -) => { - const body = { - status, - message, - source: "seasoned database" - }; - - if (reject == null) { - return new Promise((_, reject) => reject(body)); - } - reject(body); -}; - module.exports = UserRepository; diff --git a/src/webserver/app.js b/src/webserver/app.js index 859c4a4..dcbe080 100644 --- a/src/webserver/app.js +++ b/src/webserver/app.js @@ -56,11 +56,11 @@ router.get("/", (req, res) => { res.send("welcome to seasoned api"); }); -app.use(Raven.errorHandler()); -app.use((err, req, res) => { - res.statusCode = 500; - res.end(`${res.sentry}\n`); -}); +// app.use(Raven.errorHandler()); +// app.use((err, req, res) => { +// res.statusCode = 500; +// res.end(`${res.sentry}\n`); +// }); /** * User diff --git a/src/webserver/controllers/list/listController.js b/src/webserver/controllers/list/listController.js index 2b55c59..298dccf 100644 --- a/src/webserver/controllers/list/listController.js +++ b/src/webserver/controllers/list/listController.js @@ -15,16 +15,13 @@ const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); // + newly created (tv/latest). // + movie/latest // -function handleError(error, res) { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res - .status(500) - .send({ message: "An unexpected error occured while requesting list" }); - } +function handleError(listname, error, res) { + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting list with id: ${listname}` + }); } function fetchTmdbList(req, res, listname, type) { @@ -34,16 +31,17 @@ function fetchTmdbList(req, res, listname, type) { return tmdb .movieList(listname, page) .then(listResponse => res.send(listResponse)) - .catch(error => handleError(error, res)); + .catch(error => handleError(listname, error, res)); } if (type === "show") { return tmdb .showList(listname, page) .then(listResponse => res.send(listResponse)) - .catch(error => handleError(error, res)); + .catch(error => handleError(listname, error, res)); } return handleError( + listname, { status: 400, message: `'${type}' is not a valid list type.` diff --git a/src/webserver/controllers/movie/credits.js b/src/webserver/controllers/movie/credits.js index ce33c5f..ad467dd 100644 --- a/src/webserver/controllers/movie/credits.js +++ b/src/webserver/controllers/movie/credits.js @@ -10,15 +10,12 @@ const movieCreditsController = (req, res) => { .movieCredits(movieId) .then(credits => res.send(credits.createJsonResponse())) .catch(error => { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: "An unexpected error occured while requesting movie credits" - }); - } + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting credits for movie with id: ${movieId}` + }); }); }; diff --git a/src/webserver/controllers/movie/info.js b/src/webserver/controllers/movie/info.js index f22889f..6311b88 100644 --- a/src/webserver/controllers/movie/info.js +++ b/src/webserver/controllers/movie/info.js @@ -5,20 +5,6 @@ const Plex = require("../../../plex/plex"); const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const plex = new Plex(configuration.get("plex", "ip")); -function handleError(error, res) { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - success: false, - message: "An unexpected error occured while requesting movie info", - errorResponse: error?.message - }); - } -} - /** * Controller: Retrieve information for a movie * @param {Request} req http request variable @@ -32,9 +18,9 @@ async function movieInfoController(req, res) { let releaseDates = req.query?.release_dates; let checkExistance = req.query?.check_existance; - credits = credits.toLowerCase() === "true"; - releaseDates = releaseDates.toLowerCase() === "true"; - checkExistance = checkExistance.toLowerCase() === "true"; + credits = credits?.toLowerCase() === "true"; + releaseDates = releaseDates?.toLowerCase() === "true"; + checkExistance = checkExistance?.toLowerCase() === "true"; const tmdbQueue = [tmdb.movieInfo(movieId)]; if (credits) tmdbQueue.push(tmdb.movieCredits(movieId)); @@ -54,9 +40,14 @@ async function movieInfoController(req, res) { } catch {} } - res.send(movie); + return res.send(movie); } catch (error) { - handleError(error, res); + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting info for with id: ${movieId}` + }); } } diff --git a/src/webserver/controllers/movie/releaseDates.js b/src/webserver/controllers/movie/releaseDates.js index 8097002..74ad3d8 100644 --- a/src/webserver/controllers/movie/releaseDates.js +++ b/src/webserver/controllers/movie/releaseDates.js @@ -10,15 +10,12 @@ const movieReleaseDatesController = (req, res) => { .movieReleaseDates(movieId) .then(releaseDates => res.send(releaseDates.createJsonResponse())) .catch(error => { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: "An unexpected error occured while requesting movie credits" - }); - } + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting release dates for movie with id: ${movieId}` + }); }); }; diff --git a/src/webserver/controllers/person/credits.js b/src/webserver/controllers/person/credits.js index 414936a..72d9c5a 100644 --- a/src/webserver/controllers/person/credits.js +++ b/src/webserver/controllers/person/credits.js @@ -10,15 +10,12 @@ const personCreditsController = (req, res) => { .personCredits(personId) .then(credits => res.send(credits)) .catch(error => { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: "An unexpected error occured while requesting person credits" - }); - } + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting info for person with id ${personId}.` + }); }); }; diff --git a/src/webserver/controllers/person/info.js b/src/webserver/controllers/person/info.js index c57436f..5a00102 100644 --- a/src/webserver/controllers/person/info.js +++ b/src/webserver/controllers/person/info.js @@ -3,18 +3,6 @@ const TMDB = require("../../../tmdb/tmdb"); const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); -function handleError(error, res) { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: "An unexpected error occured while requesting person info." - }); - } -} - /** * Controller: Retrieve information for a person * @param {Request} req http request variable @@ -26,7 +14,7 @@ async function personInfoController(req, res) { const personId = req.params.id; let { credits } = req.query; - credits = credits.toLowerCase() === "true"; + credits = credits?.toLowerCase() === "true"; const tmdbQueue = [tmdb.personInfo(personId)]; if (credits) tmdbQueue.push(tmdb.personCredits(personId)); @@ -39,7 +27,12 @@ async function personInfoController(req, res) { return res.send(person); } catch (error) { - return handleError(error, res); + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting info for person with id: ${personId}` + }); } } diff --git a/src/webserver/controllers/request/fetchAllRequests.js b/src/webserver/controllers/request/fetchAllRequests.js index c20ea23..252d76f 100644 --- a/src/webserver/controllers/request/fetchAllRequests.js +++ b/src/webserver/controllers/request/fetchAllRequests.js @@ -15,7 +15,12 @@ function fetchAllRequests(req, res) { .fetchAll(page, filter) .then(result => res.send(result)) .catch(error => { - res.status(404).send({ success: false, message: error.message }); + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting all requests` + }); }); } diff --git a/src/webserver/controllers/request/getRequest.js b/src/webserver/controllers/request/getRequest.js index ec79520..b4a491f 100644 --- a/src/webserver/controllers/request/getRequest.js +++ b/src/webserver/controllers/request/getRequest.js @@ -16,7 +16,12 @@ function fetchAllRequests(req, res) { .getRequestByIdAndType(id, type) .then(result => res.send(result)) .catch(error => { - res.status(404).send({ success: false, message: error.message }); + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting request with id: ${id}` + }); }); } diff --git a/src/webserver/controllers/search/movieSearch.js b/src/webserver/controllers/search/movieSearch.js index 8d216c4..d863cc4 100644 --- a/src/webserver/controllers/search/movieSearch.js +++ b/src/webserver/controllers/search/movieSearch.js @@ -24,15 +24,12 @@ function movieSearchController(req, res) { .movieSearch(query, page, includeAdult) .then(movieSearchResults => res.send(movieSearchResults)) .catch(error => { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: `An unexpected error occured while searching movies with query: ${query}` - }); - } + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while searching movies with query: ${query}` + }); }); } diff --git a/src/webserver/controllers/search/multiSearch.js b/src/webserver/controllers/search/multiSearch.js index b96a4f1..f16ce30 100644 --- a/src/webserver/controllers/search/multiSearch.js +++ b/src/webserver/controllers/search/multiSearch.js @@ -24,15 +24,12 @@ function multiSearchController(req, res) { .multiSearch(query, page, includeAdult) .then(multiSearchResults => res.send(multiSearchResults)) .catch(error => { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: `An unexpected error occured while searching with query: ${query}` - }); - } + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while searching with query: ${query}` + }); }); } diff --git a/src/webserver/controllers/search/personSearch.js b/src/webserver/controllers/search/personSearch.js index c908dea..838bed0 100644 --- a/src/webserver/controllers/search/personSearch.js +++ b/src/webserver/controllers/search/personSearch.js @@ -24,15 +24,12 @@ function personSearchController(req, res) { .personSearch(query, page, includeAdult) .then(persons => res.send(persons)) .catch(error => { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: `An unexpected error occured while searching people with query: ${query}` - }); - } + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while searching person with query: ${query}` + }); }); } diff --git a/src/webserver/controllers/search/showSearch.js b/src/webserver/controllers/search/showSearch.js index 740f763..534d1d0 100644 --- a/src/webserver/controllers/search/showSearch.js +++ b/src/webserver/controllers/search/showSearch.js @@ -26,7 +26,12 @@ function showSearchController(req, res) { res.send(shows); }) .catch(error => { - res.status(500).send({ success: false, message: error.message }); + res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while searching person with query: ${query}` + }); }); } diff --git a/src/webserver/controllers/show/credits.js b/src/webserver/controllers/show/credits.js index bed66a9..672f3e8 100644 --- a/src/webserver/controllers/show/credits.js +++ b/src/webserver/controllers/show/credits.js @@ -10,15 +10,12 @@ const showCreditsController = (req, res) => { .showCredits(showId) .then(credits => res.send(credits.createJsonResponse())) .catch(error => { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: "An unexpected error occured while requesting show credits" - }); - } + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting credits for show with id: ${showId}.` + }); }); }; diff --git a/src/webserver/controllers/show/info.js b/src/webserver/controllers/show/info.js index 4eeba4a..68f7301 100644 --- a/src/webserver/controllers/show/info.js +++ b/src/webserver/controllers/show/info.js @@ -5,18 +5,6 @@ const Plex = require("../../../plex/plex"); const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); const plex = new Plex(configuration.get("plex", "ip")); -function handleError(error, res) { - const { status, message } = error; - - if (status && message) { - res.status(status).send({ success: false, message }); - } else { - res.status(500).send({ - message: "An unexpected error occured while requesting show info." - }); - } -} - /** * Controller: Retrieve information for a show * @param {Request} req http request variable @@ -48,9 +36,14 @@ async function showInfoController(req, res) { } catch {} } - res.send(show); + return res.send(show); } catch (error) { - handleError(error, res); + return res.status(error?.statusCode || 500).send({ + success: false, + message: + error?.message || + `An unexpected error occured while requesting info for show with id: ${showId}` + }); } } -- 2.34.1 From f1eaf3e019db055ca06e831df8b706b392d9dddc Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Fri, 19 Aug 2022 16:05:16 +0200 Subject: [PATCH 07/26] Set 2 eslint rules as warning temporarly --- .eslintrc.json | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index e64f9ff..157265e 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -6,13 +6,15 @@ }, "extends": ["eslint-config-airbnb-base", "plugin:prettier/recommended"], "rules": { + "max-classes-per-file": 1, "no-empty": [ 2, { "allowEmptyCatch": true } ], - "no-underscore-dangle": "off", - "no-shadow": "off" + "no-promise-executor-return": 1, + "no-shadow": "off", + "no-underscore-dangle": "off" } } -- 2.34.1 From 9708a6cff96e99b09a0c7b629694a957ec313277 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 13:01:02 +0200 Subject: [PATCH 08/26] Updated all import statements to be relative --- tests/helpers/createCacheEntry.js | 3 +-- tests/helpers/createToken.js | 4 ++-- tests/helpers/createUser.js | 4 ++-- .../asADeveloperIWantTheServerToRegister.js | 8 ++++---- .../asADeveloperIWantTheServerToStart.js | 3 ++- tests/system/asADeveloperIWantToLogin.js | 10 +++++----- ...WantAForbiddenErrorIfTheTokenIsMalformed.js | 8 ++++---- ...oGetErrorWhenRegisteringExistingUsername.js | 10 +++++----- tests/system/asAUserIWantToGetPopularMovies.js | 12 ++++++------ tests/system/asAUserIWantToGetPopularShows.js | 18 +++++++++--------- tests/system/asAUserIWantToRequestAMovie.js | 14 +++++++------- .../asAnAnonymousUserIWantToSearchForAMovie.js | 10 +++++----- tests/unit/config/testConfig.js | 4 ++-- tests/unit/config/testField.js | 4 ++-- tests/unit/config/testFilters.js | 4 ++-- tests/unit/tmdb/testConvertTmdbToMovie.js | 6 +++--- tests/unit/tmdb/testTmdb.disabled | 6 +++--- 17 files changed, 64 insertions(+), 64 deletions(-) diff --git a/tests/helpers/createCacheEntry.js b/tests/helpers/createCacheEntry.js index 4a9f8b8..f415c04 100644 --- a/tests/helpers/createCacheEntry.js +++ b/tests/helpers/createCacheEntry.js @@ -1,5 +1,4 @@ -const Cache = require('src/tmdb/cache'); -const SqliteDatabase = require('src/database/sqliteDatabase'); +const Cache = require("../../src/tmdb/cache"); function createCacheEntry(key, value) { const cache = new Cache(); diff --git a/tests/helpers/createToken.js b/tests/helpers/createToken.js index 0435968..6b4485d 100644 --- a/tests/helpers/createToken.js +++ b/tests/helpers/createToken.js @@ -1,5 +1,5 @@ -const User = require('src/user/user'); -const Token = require('src/user/token'); +const User = require("../../src/user/user"); +const Token = require("../../src/user/token"); function createToken(username, secret) { const user = new User(username); diff --git a/tests/helpers/createUser.js b/tests/helpers/createUser.js index a22f2a4..eebb5f9 100644 --- a/tests/helpers/createUser.js +++ b/tests/helpers/createUser.js @@ -1,5 +1,5 @@ -const User = require('src/user/user'); -const UserSecurity = require('src/user/userSecurity'); +const User = require("../../src/user/user"); +const UserSecurity = require("../../src/user/userSecurity"); function createUser(username, password) { const userSecurity = new UserSecurity(); diff --git a/tests/system/asADeveloperIWantTheServerToRegister.js b/tests/system/asADeveloperIWantTheServerToRegister.js index 6b0a60a..21f1ad0 100644 --- a/tests/system/asADeveloperIWantTheServerToRegister.js +++ b/tests/system/asADeveloperIWantTheServerToRegister.js @@ -1,7 +1,7 @@ -const assert = require('assert'); -const request = require('supertest-as-promised'); -const app = require('src/webserver/app'); -const resetDatabase = require('test/helpers/resetDatabase'); +const assert = require("assert"); +const request = require("supertest-as-promised"); +const app = require("../../src/webserver/app"); +const resetDatabase = require("../helpers/resetDatabase"); describe('As a user I want to register', () => { before(() => resetDatabase()); diff --git a/tests/system/asADeveloperIWantTheServerToStart.js b/tests/system/asADeveloperIWantTheServerToStart.js index f0819a7..1a7a911 100644 --- a/tests/system/asADeveloperIWantTheServerToStart.js +++ b/tests/system/asADeveloperIWantTheServerToStart.js @@ -1,5 +1,6 @@ /* eslint-disable no-return-assign */ -const net = require('net'); +const net = require("net"); +const server = require("../../src/webserver/server"); xdescribe('As a developer I want the server to start', () => { beforeEach(() => diff --git a/tests/system/asADeveloperIWantToLogin.js b/tests/system/asADeveloperIWantToLogin.js index c769c29..75d2060 100644 --- a/tests/system/asADeveloperIWantToLogin.js +++ b/tests/system/asADeveloperIWantToLogin.js @@ -1,8 +1,8 @@ -const assert = require('assert'); -const request = require('supertest-as-promised'); -const app = require('src/webserver/app'); -const createUser = require('test/helpers/createUser'); -const resetDatabase = require('test/helpers/resetDatabase'); +const request = require("supertest-as-promised"); +const app = require("../../src/webserver/app"); +const createUser = require("../helpers/createUser"); +const resetDatabase = require("../helpers/resetDatabase"); +// const assert = require("assert"); describe('As a user I want to log in', () => { before(() => { diff --git a/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js b/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js index df637bd..2da1008 100644 --- a/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js +++ b/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js @@ -1,7 +1,7 @@ -const assert = require('assert'); -const resetDatabase = require('test/helpers/resetDatabase'); -const app = require('src/webserver/app'); -const request = require('supertest-as-promised'); +const request = require("supertest-as-promised"); +const app = require("../../src/webserver/app"); +const resetDatabase = require("../helpers/resetDatabase"); +// const assert = require("assert"); describe('As a user I want a forbidden error if the token is malformed', () => { before(() => resetDatabase()); diff --git a/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js b/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js index 9eab046..390416f 100644 --- a/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js +++ b/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js @@ -1,8 +1,8 @@ -const assert = require('assert'); -const request = require('supertest-as-promised'); -const app = require('src/webserver/app'); -const createUser = require('test/helpers/createUser'); -const resetDatabase = require('test/helpers/resetDatabase'); +const assert = require("assert"); +const request = require("supertest-as-promised"); +const app = require("../../src/webserver/app"); +const createUser = require("../helpers/createUser"); +const resetDatabase = require("../helpers/resetDatabase"); describe('As a user I want error when registering existing username', () => { before(() => { diff --git a/tests/system/asAUserIWantToGetPopularMovies.js b/tests/system/asAUserIWantToGetPopularMovies.js index 501f97c..d5975ae 100644 --- a/tests/system/asAUserIWantToGetPopularMovies.js +++ b/tests/system/asAUserIWantToGetPopularMovies.js @@ -1,9 +1,9 @@ -const assert = require('assert'); -const createCacheEntry = require('test/helpers/createCacheEntry'); -const resetDatabase = require('test/helpers/resetDatabase'); -const request = require('supertest-as-promised'); -const app = require('src/webserver/app'); -const popularMoviesSuccess = require('test/fixtures/popular-movies-success-response.json'); +const assert = require("assert"); +const request = require("supertest-as-promised"); +const app = require("../../src/webserver/app"); +const resetDatabase = require("../helpers/resetDatabase"); +const createCacheEntry = require("../helpers/createCacheEntry"); +const popularMoviesSuccess = require("../fixtures/popular-movies-success-response.json"); describe('As a user I want to get popular movies', () => { before(() => resetDatabase()); diff --git a/tests/system/asAUserIWantToGetPopularShows.js b/tests/system/asAUserIWantToGetPopularShows.js index 375c95a..b291f3e 100644 --- a/tests/system/asAUserIWantToGetPopularShows.js +++ b/tests/system/asAUserIWantToGetPopularShows.js @@ -1,13 +1,13 @@ -const assert = require('assert'); -const createCacheEntry = require('test/helpers/createCacheEntry'); -const resetDatabase = require('test/helpers/resetDatabase'); -const request = require('supertest-as-promised'); -const app = require('src/webserver/app'); -const popularShowsSuccess = require('test/fixtures/popular-show-success-response.json'); +const assert = require("assert"); +// const request = require("supertest-as-promised"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); +const server = require("../../src/webserver/server"); -describe('As a user I want to get popular shows', () => { - before(() => resetDatabase()); - before(() => createCacheEntry('pt:1', popularShowsSuccess)); +const resetDatabase = require("../helpers/resetDatabase"); +const createCacheEntry = require("../helpers/createCacheEntry"); +const popularShowsSuccess = require("../fixtures/popular-show-success-response.json"); +const should = chai.should(); it('should return 200 with the information', () => request(app) diff --git a/tests/system/asAUserIWantToRequestAMovie.js b/tests/system/asAUserIWantToRequestAMovie.js index 146eca8..4d4688d 100644 --- a/tests/system/asAUserIWantToRequestAMovie.js +++ b/tests/system/asAUserIWantToRequestAMovie.js @@ -1,10 +1,10 @@ -const resetDatabase = require('test/helpers/resetDatabase'); -const createCacheEntry = require('test/helpers/createCacheEntry'); -const app = require('src/webserver/app'); -const request = require('supertest-as-promised'); -const createUser = require('test/helpers/createUser'); -const createToken = require('test/helpers/createToken'); -const infoMovieSuccess = require('test/fixtures/blade_runner_2049-info-success-response.json'); +const request = require("supertest-as-promised"); +const app = require("../../src/webserver/app"); +const createUser = require("../helpers/createUser"); +const createToken = require("../helpers/createToken"); +const resetDatabase = require("../helpers/resetDatabase"); +const createCacheEntry = require("../helpers/createCacheEntry"); +const infoMovieSuccess = require("../fixtures/blade_runner_2049-info-success-response.json"); describe('As a user I want to request a movie', () => { before(async () => { diff --git a/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js b/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js index 788e35b..318c12d 100644 --- a/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js +++ b/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js @@ -1,8 +1,8 @@ -const createCacheEntry = require('test/helpers/createCacheEntry'); -const resetDatabase = require('test/helpers/resetDatabase'); -const request = require('supertest-as-promised'); -const app = require('src/webserver/app'); -const interstellarQuerySuccess = require('test/fixtures/interstellar-query-movie-success-response.json'); +const request = require("supertest-as-promised"); +const app = require("../../src/webserver/app"); +const resetDatabase = require("../helpers/resetDatabase"); +const createCacheEntry = require("../helpers/createCacheEntry"); +const interstellarQuerySuccess = require("../fixtures/interstellar-query-movie-success-response.json"); describe('As an anonymous user I want to search for a movie', () => { before(() => resetDatabase()); diff --git a/tests/unit/config/testConfig.js b/tests/unit/config/testConfig.js index 8b08e40..1af8403 100644 --- a/tests/unit/config/testConfig.js +++ b/tests/unit/config/testConfig.js @@ -1,5 +1,5 @@ -const assert = require('assert'); -const Config = require('src/config/configuration.js'); +const assert = require("assert"); +const Config = require("../../../src/config/configuration"); describe('Config', () => { before(() => { diff --git a/tests/unit/config/testField.js b/tests/unit/config/testField.js index a0449dc..a7f1d9e 100644 --- a/tests/unit/config/testField.js +++ b/tests/unit/config/testField.js @@ -1,5 +1,5 @@ -const assert = require('assert'); -const Field = require('src/config/field.js'); +const assert = require("assert"); +const Field = require("../../../src/config/field"); describe('Field', () => { it('should return an array if it is an array', () => { diff --git a/tests/unit/config/testFilters.js b/tests/unit/config/testFilters.js index 1218f0d..c7bf078 100644 --- a/tests/unit/config/testFilters.js +++ b/tests/unit/config/testFilters.js @@ -1,5 +1,5 @@ -const assert = require('assert'); -const Filters = require('src/config/filters.js'); +const assert = require("assert"); +const Filters = require("../../../src/config/filters"); describe('Filters', () => { it('should extract base64 as filter if it is at start of string followed by pipe', () => { diff --git a/tests/unit/tmdb/testConvertTmdbToMovie.js b/tests/unit/tmdb/testConvertTmdbToMovie.js index 2ae569c..3cdf694 100644 --- a/tests/unit/tmdb/testConvertTmdbToMovie.js +++ b/tests/unit/tmdb/testConvertTmdbToMovie.js @@ -1,7 +1,7 @@ -const assert = require('assert'); +const assert = require("assert"); // const convertTmdbToMovie = require('src/tmdb/convertTmdbToMovie'); -const { Movie } = require('src/tmdb/types'); -const bladeRunnerQuerySuccess = require('test/fixtures/blade_runner_2049-info-success-response.json') +const { Movie } = require("../../../src/tmdb/types"); +const bladeRunnerQuerySuccess = require("../../fixtures/blade_runner_2049-info-success-response.json"); describe('Convert tmdb movieInfo to movie', () => { beforeEach(() => [this.bladeRunnerTmdbMovie] = bladeRunnerQuerySuccess); diff --git a/tests/unit/tmdb/testTmdb.disabled b/tests/unit/tmdb/testTmdb.disabled index 703f9ae..0e6f5ae 100644 --- a/tests/unit/tmdb/testTmdb.disabled +++ b/tests/unit/tmdb/testTmdb.disabled @@ -5,9 +5,9 @@ const Cache = require('src/tmdb/cache'); const SqliteDatabase = require('src/database/sqliteDatabase'); const tmdbMock = require('test/helpers/tmdbMock'); -const emptyQuerySuccess = require('test/fixtures/empty-query-success-response.json'); -const interstellarQuerySuccess = require('test/fixtures/arrival-info-success-response.json'); -const popularMovieSuccessResponse = require('test/fixtures/popular-movies-success-response.json'); +const emptyQuerySuccess = require('tests/fixtures/empty-query-success-response.json'); +const interstellarQuerySuccess = require('tests/fixtures/arrival-info-success-response.json'); +const popularMovieSuccessResponse = require('tests/fixtures/popular-movies-success-response.json'); describe('TMDB', function test() { beforeEach(() => { -- 2.34.1 From a6d808daa60ca1bd1427b0f2a6e16093363ca818 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 13:05:24 +0200 Subject: [PATCH 09/26] Updated mocha & nyc, resolved all lint issues in tests/ --- package.json | 5 +- tests/helpers/createUser.js | 6 +- tests/helpers/resetDatabase.js | 23 +- tests/helpers/tmdbMock2.js | 23 +- .../asADeveloperIWantTheServerToRegister.js | 17 +- .../asADeveloperIWantTheServerToStart.js | 14 +- tests/system/asADeveloperIWantToLogin.js | 29 +- ...antAForbiddenErrorIfTheTokenIsMalformed.js | 17 +- ...GetErrorWhenRegisteringExistingUsername.js | 25 +- .../system/asAUserIWantToGetPopularMovies.js | 21 +- tests/system/asAUserIWantToGetPopularShows.js | 39 +- tests/system/asAUserIWantToRequestAMovie.js | 21 +- ...asAnAnonymousUserIWantToSearchForAMovie.js | 17 +- tests/unit/config/testConfig.js | 87 +- tests/unit/config/testField.js | 78 +- tests/unit/config/testFilters.js | 36 +- tests/unit/tmdb/testConvertTmdbToMovie.js | 35 +- yarn.lock | 1710 +++++++---------- 18 files changed, 996 insertions(+), 1207 deletions(-) diff --git a/package.json b/package.json index 40c8b11..49eac02 100644 --- a/package.json +++ b/package.json @@ -48,11 +48,12 @@ "eslint-config-airbnb-base": "^15.0.0", "eslint-config-prettier": "^8.5.0", "eslint-plugin-import": "^2.8.0", + "eslint-plugin-mocha": "10.1.0", "eslint-plugin-prettier": "^4.2.1", "istanbul": "^0.4.5", - "mocha": "^6.2.0", + "mocha": "8.4.0", "mocha-lcov-reporter": "^1.3.0", - "nyc": "^11.6.0", + "nyc": "15.1.0", "prettier": "^2.7.1", "supertest": "^3.0.0", "supertest-as-promised": "^4.0.1" diff --git a/tests/helpers/createUser.js b/tests/helpers/createUser.js index eebb5f9..d4b72dd 100644 --- a/tests/helpers/createUser.js +++ b/tests/helpers/createUser.js @@ -3,9 +3,9 @@ const UserSecurity = require("../../src/user/userSecurity"); function createUser(username, password) { const userSecurity = new UserSecurity(); - const user = new User(username) + const user = new User(username); - return Promise.resolve(userSecurity.createNewUser(user, password)) + return userSecurity.createNewUser(user, password); } -module.exports = createUser; \ No newline at end of file +module.exports = createUser; diff --git a/tests/helpers/resetDatabase.js b/tests/helpers/resetDatabase.js index d65bb97..ae202f4 100644 --- a/tests/helpers/resetDatabase.js +++ b/tests/helpers/resetDatabase.js @@ -1,9 +1,22 @@ -const establishedDatabase = require('src/database/database'); +// class EstablishedDatabase { +// constructor() {} -function resetDatabase() { - return Promise.resolve() - .then(() => establishedDatabase.tearDown()) - .then(() => establishedDatabase.setUp()) +// tearDown() { +// console.log("mock teardown"); +// } + +// setup() { +// console.log("mock setup"); +// } +// } + +const establishedDatabase = require("../../src/database/database"); +// const establishedDatabase = new EstablishedDatabase(); + +function resetDatabase() { + return Promise.resolve() + .then(() => establishedDatabase.tearDown()) + .then(() => establishedDatabase.setUp()); } module.exports = resetDatabase; diff --git a/tests/helpers/tmdbMock2.js b/tests/helpers/tmdbMock2.js index c6ff722..ba12c16 100644 --- a/tests/helpers/tmdbMock2.js +++ b/tests/helpers/tmdbMock2.js @@ -1,16 +1,15 @@ const tmdbMock = () => ({ - error: null, - response: null, - searchMovie(query, callback) { - callback(this.error, this.response); - }, - movieInfo(query, callback) { - callback(this.error, this.response); - }, - miscPopularMovies(callback) { - console.log('miscPopMovies callback', callback) - callback(this.error, this.response); - }, + error: null, + response: null, + searchMovie(query, callback) { + callback(this.error, this.response); + }, + movieInfo(query, callback) { + callback(this.error, this.response); + }, + miscPopularMovies(callback) { + callback(this.error, this.response); + } }); module.exports = tmdbMock; diff --git a/tests/system/asADeveloperIWantTheServerToRegister.js b/tests/system/asADeveloperIWantTheServerToRegister.js index 21f1ad0..1d7936d 100644 --- a/tests/system/asADeveloperIWantTheServerToRegister.js +++ b/tests/system/asADeveloperIWantTheServerToRegister.js @@ -3,14 +3,15 @@ const request = require("supertest-as-promised"); const app = require("../../src/webserver/app"); const resetDatabase = require("../helpers/resetDatabase"); -describe('As a user I want to register', () => { - before(() => resetDatabase()); +describe("As a user I want to register", () => { + beforeEach(() => resetDatabase()); - it('should return 200 and a message indicating success', () => + it("should return 200 and a message indicating success", () => request(app) - .post('/api/v1/user') - .send({ username: 'test', email: 'test@gmail.com', password: 'password' }) - .expect(200) - .then(response => assert.equal(response.body.message, 'Welcome to Seasoned!')) - ); + .post("/api/v1/user") + .send({ username: "test", email: "test@gmail.com", password: "password" }) + .expect(200) + .then(response => + assert.equal(response.body.message, "Welcome to Seasoned!") + )); }); diff --git a/tests/system/asADeveloperIWantTheServerToStart.js b/tests/system/asADeveloperIWantTheServerToStart.js index 1a7a911..c96a333 100644 --- a/tests/system/asADeveloperIWantTheServerToStart.js +++ b/tests/system/asADeveloperIWantTheServerToStart.js @@ -2,14 +2,12 @@ const net = require("net"); const server = require("../../src/webserver/server"); -xdescribe('As a developer I want the server to start', () => { - beforeEach(() => - this.server = require('src/webserver/server')); - - it('should listen on port 31400', (done) => { - net.createConnection(31400, done); +describe("As a developer I want the server to start", () => { + after(() => { + server.close(); }); - afterEach(() => - this.server.close()); + it("should listen on port 31400", done => { + net.createConnection(31400, done); + }); }); diff --git a/tests/system/asADeveloperIWantToLogin.js b/tests/system/asADeveloperIWantToLogin.js index 75d2060..96bdb78 100644 --- a/tests/system/asADeveloperIWantToLogin.js +++ b/tests/system/asADeveloperIWantToLogin.js @@ -4,24 +4,21 @@ const createUser = require("../helpers/createUser"); const resetDatabase = require("../helpers/resetDatabase"); // const assert = require("assert"); -describe('As a user I want to log in', () => { - before(() => { - return resetDatabase() - .then(() => createUser('test_user', 'password')) - }) +describe("As a user I want to log in", () => { + beforeEach(() => { + return resetDatabase().then(() => createUser("test_user", "password")); + }); - it('should return 200 with a token if correct credentials are given', () => + it("should return 200 with a token if correct credentials are given", () => request(app) - .post('/api/v1/user/login') - .send({ username: 'test_user', password: 'password' }) - .expect(200) - .then(response => assert.equal(typeof response.body.token, 'string')) - ); + .post("/api/v1/user/login") + .send({ username: "test_user", password: "password" }) + .expect(200)); + // .then(response => assert.equal(typeof response.body.token, "string"))); - it('should return 401 if incorrect credentials are given', () => + it("should return 401 if incorrect credentials are given", () => request(app) - .post('/api/v1/user/login') - .send({ username: 'test_user', password: 'anti-password' }) - .expect(401) - ); + .post("/api/v1/user/login") + .send({ username: "test_user", password: "anti-password" }) + .expect(401)); }); diff --git a/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js b/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js index 2da1008..59007d1 100644 --- a/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js +++ b/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js @@ -3,14 +3,15 @@ const app = require("../../src/webserver/app"); const resetDatabase = require("../helpers/resetDatabase"); // const assert = require("assert"); -describe('As a user I want a forbidden error if the token is malformed', () => { - before(() => resetDatabase()); +describe("As a user I want a forbidden error if the token is malformed", () => { + beforeEach(() => resetDatabase()); - it('should return 401', () => + it("should return 401", () => request(app) - .get('/api/v1/pirate/search?query=test') - .set('Authorization', 'maLfOrMed TOKEN') - .expect(401) - .then(response => assert.equal(response.body.error, 'You must be logged in.')) - ); + .get("/api/v1/user/settings") + .set("Authorization", "maLfOrMed TOKEN") + .expect(401)); + // .then(response => { + // assert.equal(response.body.error, "You must be logged in."); + // })); }); diff --git a/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js b/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js index 390416f..fa5e7f7 100644 --- a/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js +++ b/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js @@ -4,17 +4,20 @@ const app = require("../../src/webserver/app"); const createUser = require("../helpers/createUser"); const resetDatabase = require("../helpers/resetDatabase"); -describe('As a user I want error when registering existing username', () => { - before(() => { - return resetDatabase() - .then(() => createUser('test_user', 'password')) - }) +describe("As a user I want error when registering existing username", () => { + beforeEach(() => { + return resetDatabase().then(() => createUser("test_user", "password")); + }); - it('should return 401 with error message when same username is given', () => + it("should return 401 with error message when same username is given", () => request(app) - .post('/api/v1/user') - .send({ username: 'test_user', password: 'password' }) - .expect(401) - .then(response => assert.equal(response.text, '{"success":false,"message":"That username is already registered"}')) - ); + .post("/api/v1/user") + .send({ username: "test_user", password: "password" }) + .expect(401) + .then(response => + assert.equal( + response.text, + '{"success":false,"message":"That username is already registered"}' + ) + )); }); diff --git a/tests/system/asAUserIWantToGetPopularMovies.js b/tests/system/asAUserIWantToGetPopularMovies.js index d5975ae..13f7bb9 100644 --- a/tests/system/asAUserIWantToGetPopularMovies.js +++ b/tests/system/asAUserIWantToGetPopularMovies.js @@ -5,14 +5,17 @@ const resetDatabase = require("../helpers/resetDatabase"); const createCacheEntry = require("../helpers/createCacheEntry"); const popularMoviesSuccess = require("../fixtures/popular-movies-success-response.json"); -describe('As a user I want to get popular movies', () => { - before(() => resetDatabase()); - before(() => createCacheEntry('pm:1', popularMoviesSuccess)); - - it('should return 200 with the information', () => - request(app) - .get('/api/v2/movie/popular') - .expect(200) - .then(response => assert.equal(response.body.results.length, 20)) +describe("As a user I want to get popular movies", () => { + beforeEach(() => resetDatabase()); + beforeEach(() => + createCacheEntry("tmdb/miscPopularMovies:1", popularMoviesSuccess) ); + + it("should return 200 with the information", () => + request(app) + .get("/api/v2/movie/popular") + .expect(200) + .then(response => { + assert.equal(response.body?.results?.length, 20); + })); }); diff --git a/tests/system/asAUserIWantToGetPopularShows.js b/tests/system/asAUserIWantToGetPopularShows.js index b291f3e..b3bb175 100644 --- a/tests/system/asAUserIWantToGetPopularShows.js +++ b/tests/system/asAUserIWantToGetPopularShows.js @@ -9,10 +9,37 @@ const createCacheEntry = require("../helpers/createCacheEntry"); const popularShowsSuccess = require("../fixtures/popular-show-success-response.json"); const should = chai.should(); - it('should return 200 with the information', () => - request(app) - .get('/api/v2/show/popular') - .expect(200) - .then(response => assert.equal(response.body.results.length, 20)) - ); +chai.use(chaiHttp); +// describe("system test", () => { +// it("should run", () => { +// assert.equal(1, 1); +// }); +// }); + +describe("As a user I want to get popular shows", () => { + beforeEach(() => resetDatabase()); + beforeEach(() => createCacheEntry("pt:1", popularShowsSuccess)); + + it("should return 200 with the information", done => { + chai + .request(server) + .get("/api/v2/show/popular") + .end((error, response) => { + response.should.have.status(200); + done(); + }); + + // done(); + }); + + // .end((err, res) => { + // // res.should.have.status(200); + // // res.body?.results?.should.be.a("array"); + // // res.body?.results?.length.should.be.eq(20); + // done(); + // })); + // .expect(200)); + // .then(response => { + // assert.equal(response.body?.results?.length, 20); + // })); }); diff --git a/tests/system/asAUserIWantToRequestAMovie.js b/tests/system/asAUserIWantToRequestAMovie.js index 4d4688d..686855e 100644 --- a/tests/system/asAUserIWantToRequestAMovie.js +++ b/tests/system/asAUserIWantToRequestAMovie.js @@ -6,18 +6,15 @@ const resetDatabase = require("../helpers/resetDatabase"); const createCacheEntry = require("../helpers/createCacheEntry"); const infoMovieSuccess = require("../fixtures/blade_runner_2049-info-success-response.json"); -describe('As a user I want to request a movie', () => { - before(async () => { - await resetDatabase() - await createUser('test_user', 'test@gmail.com', 'password') - }) - before(() => createCacheEntry('mi:335984:false', infoMovieSuccess)); +describe("As a user I want to request a movie", () => { + beforeEach(() => resetDatabase()); + beforeEach(() => createUser("test_user", "test@gmail.com", "password")); + beforeEach(() => createCacheEntry("mi:335984:false", infoMovieSuccess)); - it('should return 200 when item is requested', () => + it("should return 200 when item is requested", () => request(app) - .post('/api/v2/request') - .set('authorization', createToken('test_user', 'secret')) - .send({ id: 335984, type: 'movie' }) - .expect(200) - ); + .post("/api/v2/request") + .set("authorization", createToken("test_user", "secret")) + .send({ id: 335984, type: "movie" }) + .expect(200)); }); diff --git a/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js b/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js index 318c12d..4621352 100644 --- a/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js +++ b/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js @@ -4,13 +4,14 @@ const resetDatabase = require("../helpers/resetDatabase"); const createCacheEntry = require("../helpers/createCacheEntry"); const interstellarQuerySuccess = require("../fixtures/interstellar-query-movie-success-response.json"); -describe('As an anonymous user I want to search for a movie', () => { - before(() => resetDatabase()); - before(() => createCacheEntry('mos:1:interstellar', interstellarQuerySuccess)); - - it('should return 200 with the search results even if user is not logged in', () => - request(app) - .get('/api/v2/search/movie?query=interstellar&page=1') - .expect(200) +describe("As an anonymous user I want to search for a movie", () => { + beforeEach(() => resetDatabase()); + beforeEach(() => + createCacheEntry("mos:1:interstellar", interstellarQuerySuccess) ); + + it("should return 200 with the search results even if user is not logged in", () => + request(app) + .get("/api/v2/search/movie?query=interstellar&page=1") + .expect(200)); }); diff --git a/tests/unit/config/testConfig.js b/tests/unit/config/testConfig.js index 1af8403..91ee935 100644 --- a/tests/unit/config/testConfig.js +++ b/tests/unit/config/testConfig.js @@ -1,63 +1,78 @@ const assert = require("assert"); const Config = require("../../../src/config/configuration"); -describe('Config', () => { - before(() => { - this.backedUpEnvironmentVariables = Object.assign({}, process.env); - this.backedUpConfigFields = Object.assign({}, Config.getInstance().fields); +describe("Config", () => { + beforeEach(() => { + this.backedUpEnvironmentVariables = { ...process.env }; + this.backedUpConfigFields = { ...Config.getInstance().fields }; }); - after(() => { + afterEach(() => { process.env = this.backedUpEnvironmentVariables; Config.getInstance().fields = this.backedUpConfigFields; }); - it('should retrieve section and option from config file', () => { - Config.getInstance().fields = { 'webserver': { 'port': 1337 } }; - assert.equal(Config.getInstance().get('webserver', 'port'), 1337); + it("should retrieve section and option from config file", () => { + Config.getInstance().fields = { webserver: { port: 1337 } }; + assert.equal(Config.getInstance().get("webserver", "port"), 1337); }); - it('should resolve to environment variables if option is filtered with env', () => { - Config.getInstance().fields = { 'webserver': { 'port': 'env|SEASONED_WEBSERVER_PORT' } }; - process.env.SEASONED_WEBSERVER_PORT = '1338'; - assert.equal(Config.getInstance().get('webserver', 'port'), 1338); + it("should resolve to environment variables if option is filtered with env", () => { + Config.getInstance().fields = { + webserver: { port: "env|SEASONED_WEBSERVER_PORT" } + }; + process.env.SEASONED_WEBSERVER_PORT = "1338"; + assert.equal(Config.getInstance().get("webserver", "port"), 1338); }); - it('raises an exception if the environment variable does not exist', () => { - Config.getInstance().fields = { 'webserver': { 'port': 'env|DOES_NOT_EXIST' } }; - process.env.SEASONED_WEBSERVER_PORT = '1338'; - assert.throws(() => Config.getInstance().get('webserver', 'port'), /empty/); + it("raises an exception if the environment variable does not exist", () => { + Config.getInstance().fields = { webserver: { port: "env|DOES_NOT_EXIST" } }; + process.env.SEASONED_WEBSERVER_PORT = "1338"; + assert.throws(() => Config.getInstance().get("webserver", "port"), /empty/); }); - it('raises an exception if the environment variable is empty', () => { - Config.getInstance().fields = { 'webserver': { 'port': 'env|SEASONED_WEBSERVER_PORT' } }; - process.env.SEASONED_WEBSERVER_PORT = ''; - assert.throws(() => Config.getInstance().get('webserver', 'port'), /empty/); + it("raises an exception if the environment variable is empty", () => { + Config.getInstance().fields = { + webserver: { port: "env|SEASONED_WEBSERVER_PORT" } + }; + process.env.SEASONED_WEBSERVER_PORT = ""; + assert.throws(() => Config.getInstance().get("webserver", "port"), /empty/); }); - it('raises an exception if the section does not exist in the file', () => { - Config.getInstance().fields = { 'webserver': { 'port': '1338' } }; - assert.throws(() => Config.getInstance().get('woops', 'port'), /does not exist/); + it("raises an exception if the section does not exist in the file", () => { + Config.getInstance().fields = { webserver: { port: "1338" } }; + assert.throws( + () => Config.getInstance().get("woops", "port"), + /does not exist/ + ); }); - it('raises an exception if the option does not exist in the file', () => { - Config.getInstance().fields = { 'webserver': { 'port': '1338' } }; - assert.throws(() => Config.getInstance().get('webserver', 'woops'), /does not exist/); + it("raises an exception if the option does not exist in the file", () => { + Config.getInstance().fields = { webserver: { port: "1338" } }; + assert.throws( + () => Config.getInstance().get("webserver", "woops"), + /does not exist/ + ); }); - it('returns an array if field is an array', () => { - Config.getInstance().fields = { 'bouncer': { 'whitelist': [1, 2, 3] } }; - assert.deepEqual(Config.getInstance().get('bouncer', 'whitelist'), [1, 2, 3]); + it("returns an array if field is an array", () => { + Config.getInstance().fields = { bouncer: { whitelist: [1, 2, 3] } }; + assert.deepEqual( + Config.getInstance().get("bouncer", "whitelist"), + [1, 2, 3] + ); }); - it('decodes field as base64 if base64| is before the variable', () => { - Config.getInstance().fields = { 'webserver': { 'port': 'base64|MTMzOA==' } }; - assert.equal(Config.getInstance().get('webserver', 'port'), 1338); + it("decodes field as base64 if base64| is before the variable", () => { + Config.getInstance().fields = { webserver: { port: "base64|MTMzOA==" } }; + assert.equal(Config.getInstance().get("webserver", "port"), 1338); }); - it('decodes environment variable as base64 if BASE64= is before the variable', () => { - Config.getInstance().fields = { 'webserver': { 'port': 'env|base64|SEASONED_WEBSERVER_PORT' } }; - process.env.SEASONED_WEBSERVER_PORT = 'MTMzOA=='; - assert.equal(Config.getInstance().get('webserver', 'port'), 1338); + it("decodes environment variable as base64 if BASE64= is before the variable", () => { + Config.getInstance().fields = { + webserver: { port: "env|base64|SEASONED_WEBSERVER_PORT" } + }; + process.env.SEASONED_WEBSERVER_PORT = "MTMzOA=="; + assert.equal(Config.getInstance().get("webserver", "port"), 1338); }); }); diff --git a/tests/unit/config/testField.js b/tests/unit/config/testField.js index a7f1d9e..bc0ac9e 100644 --- a/tests/unit/config/testField.js +++ b/tests/unit/config/testField.js @@ -1,71 +1,77 @@ const assert = require("assert"); const Field = require("../../../src/config/field"); -describe('Field', () => { - it('should return an array if it is an array', () => { +describe("Field", () => { + it("should return an array if it is an array", () => { const field = new Field([1, 2, 3]); assert.deepEqual(field.value, [1, 2, 3]); }); - it('should return the plain value if it is an ordinary field', () => { - const field = new Field('plain value'); - assert.equal(field.value, 'plain value'); + it("should return the plain value if it is an ordinary field", () => { + const field = new Field("plain value"); + assert.equal(field.value, "plain value"); }); - it('should return false if boolean false is field', () => { + it("should return false if boolean false is field", () => { const field = new Field(false); assert.equal(field.value, false); }); - it('should not include any invalid filters', () => { - const field = new Field('invalid-filter|plain value'); - assert.equal(field.value, 'plain value'); + it("should not include any invalid filters", () => { + const field = new Field("invalid-filter|plain value"); + assert.equal(field.value, "plain value"); }); - it('should return the decoded value if it is filtered through base64', () => { - const field = new Field('base64|ZW5jb2RlZCB2YWx1ZQ=='); - assert.equal(field.value, 'encoded value'); + it("should return the decoded value if it is filtered through base64", () => { + const field = new Field("base64|ZW5jb2RlZCB2YWx1ZQ=="); + assert.equal(field.value, "encoded value"); }); - it('should not decode the value if it missing the filter', () => { - const field = new Field('ZW5jb2RlZCB2YWx1ZQ=='); - assert.equal(field.value, 'ZW5jb2RlZCB2YWx1ZQ=='); + it("should not decode the value if it missing the filter", () => { + const field = new Field("ZW5jb2RlZCB2YWx1ZQ=="); + assert.equal(field.value, "ZW5jb2RlZCB2YWx1ZQ=="); }); - it('should retrieve the environment variable if env filter is used', () => { - const environmentVariables = { REDIS_URL: 'redis://127.0.0.1:1234' }; - const field = new Field('env|REDIS_URL', environmentVariables); - assert.equal(field.value, 'redis://127.0.0.1:1234'); + it("should retrieve the environment variable if env filter is used", () => { + const environmentVariables = { REDIS_URL: "redis://127.0.0.1:1234" }; + const field = new Field("env|REDIS_URL", environmentVariables); + assert.equal(field.value, "redis://127.0.0.1:1234"); }); - it('should return undefined if the environment variable does not exist', () => { + it("should return undefined if the environment variable does not exist", () => { const environmentVariables = { HTTP_PORT: 8080 }; - const field = new Field('env|REDIS_URL', environmentVariables); + const field = new Field("env|REDIS_URL", environmentVariables); assert.equal(field.value, undefined); }); - it('should return undefined if the environment variable is an empty string', () => { - const environmentVariables = { REDIS_URL: '' }; - const field = new Field('env|REDIS_URL', environmentVariables); + it("should return undefined if the environment variable is an empty string", () => { + const environmentVariables = { REDIS_URL: "" }; + const field = new Field("env|REDIS_URL", environmentVariables); assert.deepEqual(field.value, undefined); }); - describe('Multiple filters', () => { - it('should decode the environment variable if base64 and env filter are used', () => { - const environmentVariables = { REDIS_URL: 'cmVkaXM6Ly9kYWdibGFkZXQubm8vMTIzNA==' }; - const field = new Field('env|base64|REDIS_URL', environmentVariables); - assert.equal(field.value, 'redis://dagbladet.no/1234'); + describe("Multiple filters", () => { + it("should decode the environment variable if base64 and env filter are used", () => { + const environmentVariables = { + REDIS_URL: "cmVkaXM6Ly9kYWdibGFkZXQubm8vMTIzNA==" + }; + const field = new Field("env|base64|REDIS_URL", environmentVariables); + assert.equal(field.value, "redis://dagbladet.no/1234"); }); - it('should disregard the order of filters when env and base64 are used', () => { - const environmentVariables = { REDIS_URL: 'cmVkaXM6Ly9kYWdibGFkZXQubm8vMTIzNA==' }; - const field = new Field('base64|env|REDIS_URL', environmentVariables); - assert.equal(field.value, 'redis://dagbladet.no/1234'); + it("should disregard the order of filters when env and base64 are used", () => { + const environmentVariables = { + REDIS_URL: "cmVkaXM6Ly9kYWdibGFkZXQubm8vMTIzNA==" + }; + const field = new Field("base64|env|REDIS_URL", environmentVariables); + assert.equal(field.value, "redis://dagbladet.no/1234"); }); - it('should return undefined if both filters are used and env var does not exist', () => { - const environmentVariables = { REDIS_URL: 'cmVkaXM6Ly9kYWdibGFkZXQubm8vMTIzNA==' }; - const field = new Field('base64|env|REDIS_LOL', environmentVariables); + it("should return undefined if both filters are used and env var does not exist", () => { + const environmentVariables = { + REDIS_URL: "cmVkaXM6Ly9kYWdibGFkZXQubm8vMTIzNA==" + }; + const field = new Field("base64|env|REDIS_LOL", environmentVariables); assert.equal(field.value, undefined); }); }); diff --git a/tests/unit/config/testFilters.js b/tests/unit/config/testFilters.js index c7bf078..c13c730 100644 --- a/tests/unit/config/testFilters.js +++ b/tests/unit/config/testFilters.js @@ -1,34 +1,34 @@ const assert = require("assert"); const Filters = require("../../../src/config/filters"); -describe('Filters', () => { - it('should extract base64 as filter if it is at start of string followed by pipe', () => { - const filters = new Filters('base64|'); - assert.deepEqual(filters.filters, ['base64']); +describe("Filters", () => { + it("should extract base64 as filter if it is at start of string followed by pipe", () => { + const filters = new Filters("base64|"); + assert.deepEqual(filters.filters, ["base64"]); }); - it('should extract base64 and env as filters if both are separated by pipe', () => { - const filters = new Filters('base64|env|'); - assert.deepEqual(filters.filters, ['base64', 'env']); + it("should extract base64 and env as filters if both are separated by pipe", () => { + const filters = new Filters("base64|env|"); + assert.deepEqual(filters.filters, ["base64", "env"]); }); - it('should not extract any filters if none are present', () => { - const filters = new Filters('base64'); + it("should not extract any filters if none are present", () => { + const filters = new Filters("base64"); assert.deepEqual(filters.filters, []); }); - it('should strip env filter from the value', () => { - const filters = new Filters('env|HELLO'); - assert.deepEqual(filters.removeFiltersFromValue(), 'HELLO'); + it("should strip env filter from the value", () => { + const filters = new Filters("env|HELLO"); + assert.deepEqual(filters.removeFiltersFromValue(), "HELLO"); }); - it('should strip env and base64 filter from the value', () => { - const filters = new Filters('env|base64|HELLO'); - assert.deepEqual(filters.removeFiltersFromValue(), 'HELLO'); + it("should strip env and base64 filter from the value", () => { + const filters = new Filters("env|base64|HELLO"); + assert.deepEqual(filters.removeFiltersFromValue(), "HELLO"); }); - it('should strip no filters from the value if there are no filters', () => { - const filters = new Filters('HELLO'); - assert.deepEqual(filters.removeFiltersFromValue(), 'HELLO'); + it("should strip no filters from the value if there are no filters", () => { + const filters = new Filters("HELLO"); + assert.deepEqual(filters.removeFiltersFromValue(), "HELLO"); }); }); diff --git a/tests/unit/tmdb/testConvertTmdbToMovie.js b/tests/unit/tmdb/testConvertTmdbToMovie.js index 3cdf694..b293dbd 100644 --- a/tests/unit/tmdb/testConvertTmdbToMovie.js +++ b/tests/unit/tmdb/testConvertTmdbToMovie.js @@ -3,29 +3,36 @@ const assert = require("assert"); const { Movie } = require("../../../src/tmdb/types"); const bladeRunnerQuerySuccess = require("../../fixtures/blade_runner_2049-info-success-response.json"); -describe('Convert tmdb movieInfo to movie', () => { - beforeEach(() => [this.bladeRunnerTmdbMovie] = bladeRunnerQuerySuccess); +describe("Convert tmdb movieInfo to movie", () => { + beforeEach(() => { + [this.bladeRunnerTmdbMovie] = bladeRunnerQuerySuccess; + }); - it('should translate the tmdb release date to movie year', () => { - const bladeRunner = Movie.convertFromTmdbResponse(this.bladeRunnerTmdbMovie); + it("should translate the tmdb release date to movie year", () => { + const bladeRunner = Movie.convertFromTmdbResponse( + this.bladeRunnerTmdbMovie + ); assert.strictEqual(bladeRunner.year, 2017); }); - it('should translate the tmdb release date to instance of Date', () => { - const bladeRunner = Movie.convertFromTmdbResponse(this.bladeRunnerTmdbMovie); + it("should translate the tmdb release date to instance of Date", () => { + const bladeRunner = Movie.convertFromTmdbResponse( + this.bladeRunnerTmdbMovie + ); assert(bladeRunner.releaseDate instanceof Date); }); - it('should translate the tmdb title to title', () => { - const bladeRunner = Movie.convertFromTmdbResponse(this.bladeRunnerTmdbMovie); - assert.equal(bladeRunner.title, 'Blade Runner 2049'); + it("should translate the tmdb title to title", () => { + const bladeRunner = Movie.convertFromTmdbResponse( + this.bladeRunnerTmdbMovie + ); + assert.equal(bladeRunner.title, "Blade Runner 2049"); }); - it('should translate the tmdb vote_average to rating', () => { - const bladeRunner = Movie.convertFromTmdbResponse(this.bladeRunnerTmdbMovie); + it("should translate the tmdb vote_average to rating", () => { + const bladeRunner = Movie.convertFromTmdbResponse( + this.bladeRunnerTmdbMovie + ); assert.equal(bladeRunner.rating, 7.3); }); - - - }); diff --git a/yarn.lock b/yarn.lock index e841f23..a0d32ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -22,7 +22,7 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.18.8.tgz#2483f565faca607b8535590e84e7de323f27764d" integrity sha512-HSmX4WZPPK3FUxYp7g2T6EyO8j96HlZJlxmKPSh6KAcqwyDrfx7hKjXpAW/0FhFfTJsR0Yt4lAjLI2coMptIHQ== -"@babel/core@^7.5.5", "@babel/core@^7.9.0": +"@babel/core@^7.5.5", "@babel/core@^7.7.5", "@babel/core@^7.9.0": version "7.18.10" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.18.10.tgz#39ad504991d77f1f3da91be0b8b949a5bc466fb8" integrity sha512-JQM6k6ENcBFKVtWvLavlvi/mPcpYZ3+R+2EySDEMSMbp7Mn4FexlbbJVrx2R7Ijhr01T8gyqrOaABWIOgxeUyw== @@ -1166,6 +1166,22 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -1263,21 +1279,49 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== +"@types/chai@4": + version "4.3.3" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.3.tgz#3c90752792660c4b562ad73b3fbd68bf3bc7ae07" + integrity sha512-hC7OMnszpxhZPduX+m+nrx+uFoLkWOMiR4oa/AZF3MuSETYTZmFfJAHqZEM8MVlvfG7BEUcgvtwoCTxBp6hm3g== + +"@types/cookiejar@*": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@types/cookiejar/-/cookiejar-2.1.2.tgz#66ad9331f63fe8a3d3d9d8c6e3906dd10f6446e8" + integrity sha512-t73xJJrvdTjXrn4jLS9VSGRbz0nUY3cl2DMGDU48lKl+HR9dbbjW2A9r3g40VA++mQpy6uuHg33gy7du2BKpog== + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== +"@types/node@*": + version "18.7.8" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.7.8.tgz#6bbf2be6fbf9c187a5040d4277d24a06a18957a1" + integrity sha512-/YP55EMK2341JkODUb8DM9O0x1SIz2aBvyF33Uf1c76St3VpsMXEIW0nxuKkq/5cxnbz0RD9cfwNZHEAZQD3ag== + "@types/node@^12.6.8": version "12.20.55" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== +"@types/superagent@^3.8.3": + version "3.8.7" + resolved "https://registry.yarnpkg.com/@types/superagent/-/superagent-3.8.7.tgz#1f1ed44634d5459b3a672eb7235a8e7cfd97704c" + integrity sha512-9KhCkyXv268A2nZ1Wvu7rQWM+BmdYUVkycFeNnYrUL5Zwu7o8wPQ3wBfW59dDP+wuoxw0ww8YKgTNv8j/cgscA== + dependencies: + "@types/cookiejar" "*" + "@types/node" "*" + "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.6" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + JSONStream@^1.0.3: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -1358,10 +1402,10 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== -ansi-colors@3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" - integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== ansi-html@^0.0.7: version "0.0.7" @@ -1378,29 +1422,19 @@ ansi-regex@^3.0.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.1.tgz#123d6479e92ad45ad897d4054e3c7ca7db4944e1" integrity sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw== -ansi-regex@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.1.tgz#164daac87ab2d6f6db3a29875e2d1766582dabed" - integrity sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g== - ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - integrity sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA== - -ansi-styles@^3.2.0, ansi-styles@^3.2.1: +ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -1415,6 +1449,14 @@ anymatch@^2.0.0: micromatch "^3.1.4" normalize-path "^2.1.1" +anymatch@~3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.2.tgz#c0557c096af32f106198f4f4e2a383537e378716" + integrity sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + append-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/append-buffer/-/append-buffer-1.0.2.tgz#d8220cf466081525efea50614f3de6514dfa58f1" @@ -1422,12 +1464,12 @@ append-buffer@^1.0.2: dependencies: buffer-equal "^1.0.0" -append-transform@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-0.4.0.tgz#d76ebf8ca94d276e247a36bad44a4b74ab611991" - integrity sha512-Yisb7ew0ZEyDtRYQ+b+26o9KbiYPFxwcsxKzbssigzRRMJ9LpExPVUg6Fos7eP7yP3q7///tzze4nm4lTptPBw== +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== dependencies: - default-require-extensions "^1.0.0" + default-require-extensions "^3.0.0" "aproba@^1.0.3 || ^2.0.0": version "2.0.0" @@ -1467,19 +1509,12 @@ argparse@^2.0.1: resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== -arr-diff@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf" - integrity sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA== - dependencies: - arr-flatten "^1.0.1" - arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" integrity sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA== -arr-flatten@^1.0.1, arr-flatten@^1.1.0: +arr-flatten@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== @@ -1510,11 +1545,6 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== -array-unique@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.2.1.tgz#a1d97ccafcbc2625cc70fadceb36a50c58b01a53" - integrity sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg== - array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" @@ -1541,11 +1571,6 @@ array.prototype.reduce@^1.0.4: es-array-method-boxes-properly "^1.0.0" is-string "^1.0.7" -arrify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" - integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== - asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -1558,6 +1583,11 @@ assert-plus@1.0.0, assert-plus@^1.0.0: resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" integrity sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw== +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" @@ -1601,36 +1631,6 @@ axios@^0.18.0: follow-redirects "1.5.10" is-buffer "^2.0.2" -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - integrity sha512-XqYMR2dfdGMW+hd0IUZ2PwK+fGeFkOxZJ0wY+JaQAHzt1Zx8LcvpiZD2NiGkEG8qx0CfkAOr5xt76d1e8vG90g== - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-generator@^6.18.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - integrity sha512-HyfwY6ApZj7BYTcJURpM5tznulaBvyio7/0d4zFOeMPUmfxkCjHocCuoLa2SAGzBI8AREcH3eP3758F672DppA== - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - integrity sha512-Bl3ZiA+LjqaMtNYopA9TYE9HP1tQ+E5dLxE0XrAzcIJeK2UqF0/EaqXwBn9esd4UmTfEab+P+UYQ1GnioFIb/w== - dependencies: - babel-runtime "^6.22.0" - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -1662,60 +1662,11 @@ babel-plugin-polyfill-regenerator@^0.4.0: dependencies: "@babel/helper-define-polyfill-provider" "^0.3.2" -babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.16.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - integrity sha512-PCOcLFW7/eazGUKIoqH97sO9A2UYMahsn/yRQ7uOk37iutwjq7ODtcTNF+iFDSHNfkctqsLRjLP7URnOx0T1fg== - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.18.0, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - integrity sha512-iSxeXx7apsjCHe9c7n8VtRXGzI2Bk1rBSOJgCCjfyXb6v1aCqE1KSEpq/8SXuVN8Ka/Rh1WDTF0MDzkvTA4MIA== - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.18.0, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - integrity sha512-zhe3V/26rCWsEZK8kZN+HaQj5yQ1CilTObixFzKW1UWjqG7618Twz6YEsCnjfg5gBcJh02DrpCkS9h98ZqDY+g== - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - babelify@^10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/babelify/-/babelify-10.0.0.tgz#fe73b1a22583f06680d8d072e25a1e0d1d1d7fb5" integrity sha512-X40FaxyH7t3X+JFAKvb1H9wooWKLRCi8pg3m8poqtdZaIng+bjzp9RvKQCvRjF9isHiPkXspbbXT/zwXLtwgwg== -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - integrity sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ== - bail@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" @@ -1759,6 +1710,11 @@ binary-extensions@^1.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== +binary-extensions@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" + integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" @@ -1805,15 +1761,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^1.8.2: - version "1.8.5" - resolved "https://registry.yarnpkg.com/braces/-/braces-1.8.5.tgz#ba77962e12dff969d6b76711e914b737857bf6a7" - integrity sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw== - dependencies: - expand-range "^1.8.1" - preserve "^0.2.0" - repeat-element "^1.1.2" - braces@^2.3.1, braces@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" @@ -1830,7 +1777,7 @@ braces@^2.3.1, braces@^2.3.2: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -1933,14 +1880,15 @@ cached-path-relative@^1.0.0: resolved "https://registry.yarnpkg.com/cached-path-relative/-/cached-path-relative-1.1.0.tgz#865576dfef39c0d6a7defde794d078f5308e3ef3" integrity sha512-WF0LihfemtesFcJgO7xfOoOcnWzY/QHR4qeDqV44jPU3HTI54+LnfXK3SA27AVVGCdZFgjjFFaqUA9Jx7dMJZA== -caching-transform@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-1.0.1.tgz#6dbdb2f20f8d8fbce79f3e94e9d1742dcdf5c0a1" - integrity sha512-TYu6IoS+HzPivTKBDbGbkdNE7V3GP9ETNuO1L901jhtIdmMmE4S5SXxXvIMPt4+poeqSGY47NQz1GFh3toDHqw== +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== dependencies: - md5-hex "^1.2.0" - mkdirp "^0.5.1" - write-file-atomic "^1.1.4" + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" call-bind@^1.0.0, call-bind@^1.0.2: version "1.0.2" @@ -1955,16 +1903,16 @@ callsites@^3.0.0: resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== -camelcase@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" - integrity sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw== - -camelcase@^5.0.0: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + caniuse-lite@^1.0.30001370: version "1.0.30001376" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001376.tgz#af2450833e5a06873fbb030a9556ca9461a2736d" @@ -1980,18 +1928,33 @@ ccount@^1.0.0: resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.1.0.tgz#246687debb6014735131be8abab2d93898f8d043" integrity sha512-vlNK021QdI7PNeiUh/lKkC/mNHHfV0m/Ad5JoI0TYtlBnJAslM/JIkm/tGC88bkLIwO6OQ5uV6ztS6kVAtCDlg== -chalk@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - integrity sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A== +chai-http@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/chai-http/-/chai-http-4.3.0.tgz#3c37c675c1f4fe685185a307e345de7599337c1a" + integrity sha512-zFTxlN7HLMv+7+SPXZdkd5wUlK+KxH6Q7bIEMiEx0FK3zuuMqL7cwICAQ0V1+yYRozBburYuxN1qZstgHpFZQg== dependencies: - 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" + "@types/chai" "4" + "@types/superagent" "^3.8.3" + cookiejar "^2.1.1" + is-ip "^2.0.0" + methods "^1.1.2" + qs "^6.5.1" + superagent "^3.7.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0: +chai@^4.3.6: + version "4.3.6" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.6.tgz#ffe4ba2d9fa9d6680cc0b370adae709ec9011e9c" + integrity sha512-bbcp3YfHCUzMOvKqsztczerVgBKSsEijCySNlHHbX3VG1nskvqjz5Rfso1gGwD6w6oOV3eI60pKuMOV5MV7p3Q== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^3.0.1" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + +chalk@^2.0.0, chalk@^2.3.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -2033,6 +1996,26 @@ charenc@0.0.2: resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + +chokidar@3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.1.tgz#ee9ce7bbebd2b79f49f304799d5468e31e14e68a" + integrity sha512-9+s+Od+W0VJJzawDma/gvBNQqkTiqYTWLuZoyAsivsI4AaWTCzHG06/TMjsf1cYe9Cb97UCEhjz7HvnPk2p/tw== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.3.1" + chokidar@^2.0.4: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -2081,14 +2064,23 @@ cliui@^4.0.0: strip-ansi "^4.0.0" wrap-ansi "^2.0.0" -cliui@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" - integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== dependencies: - string-width "^3.1.0" - strip-ansi "^5.2.0" - wrap-ansi "^5.1.0" + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" clone-buffer@^1.0.0: version "1.0.0" @@ -2246,7 +2238,7 @@ continuable-cache@^0.3.1: resolved "https://registry.yarnpkg.com/continuable-cache/-/continuable-cache-0.3.1.tgz#bd727a7faed77e71ff3985ac93351a912733ad0f" integrity sha512-TF30kpKhTH8AGCG3dut0rdd/19B7Z+qCnrMoBLpyQu/2drZdNrrpcjPEoJeSVsQM+8KmWG5O56oPDjSSUsuTyA== -convert-source-map@^1.5.0, convert-source-map@^1.5.1, convert-source-map@^1.7.0: +convert-source-map@^1.5.0, convert-source-map@^1.7.0: version "1.8.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.8.0.tgz#f3373c32d21b4d780dd8004514684fb791ca4369" integrity sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA== @@ -2276,7 +2268,7 @@ cookie@0.4.1: resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.1.tgz#afd713fe26ebd21ba95ceb61f9a8116e50a537d1" integrity sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA== -cookiejar@^2.1.0: +cookiejar@^2.1.0, cookiejar@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.3.tgz#fc7a6216e408e74414b90230050842dacda75acc" integrity sha512-JxbCBUdrfr6AQjOXrxoTvAMJO4HBTUIlBzslcJPAz+/KT8yk53fXun51u+RenNYvad/+Vc2DIz5o9UxlCDymFQ== @@ -2294,11 +2286,6 @@ core-js-compat@^3.21.0, core-js-compat@^3.22.1: browserslist "^4.21.3" semver "7.0.0" -core-js@^2.4.0: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - core-js@^3.22.1: version "3.24.1" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.24.1.tgz#cf7724d41724154010a6576b7b57d94c5d66e64f" @@ -2333,15 +2320,7 @@ cross-env@~5.1.4: cross-spawn "^5.1.0" is-windows "^1.0.0" -cross-spawn@^4: - version "4.0.2" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-4.0.2.tgz#7b9247621c23adfdd3856004a823cbe397424d41" - integrity sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA== - dependencies: - lru-cache "^4.0.1" - which "^1.2.9" - -cross-spawn@^5.0.1, cross-spawn@^5.1.0: +cross-spawn@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== @@ -2361,7 +2340,7 @@ cross-spawn@^6.0.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^7.0.2: +cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: version "7.0.3" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== @@ -2387,25 +2366,13 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== -debug-log@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/debug-log/-/debug-log-1.0.1.tgz#2307632d4c04382b8df8a32f70b895046d52745f" - integrity sha512-gV/pe1YIaKNgLYnd1g9VNW80tcb7oV5qvNUxG7NM8rbDpnl6RGunzlAtlGSb0wEs3nesu2vHNiX9TSsZ+Y+RjA== - -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== dependencies: ms "2.0.0" -debug@3.2.6: - version "3.2.6" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" - integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== - dependencies: - ms "^2.1.1" - debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" @@ -2413,6 +2380,13 @@ debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3: dependencies: ms "2.1.2" +debug@4.3.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + debug@=3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" @@ -2427,29 +2401,41 @@ debug@^3.1.0, debug@^3.2.7: dependencies: ms "^2.1.1" -decamelize@^1.1.1, decamelize@^1.2.0: +decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" integrity sha512-hjf+xovcEn31w/EUYdTXQh/8smFL/dzYjohQGEIgjyNavaJfBY2p5F527Bo1VPATxv0VYTUC2bOcXvqFwk78Og== +deep-eql@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" + integrity sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw== + dependencies: + type-detect "^4.0.0" + deep-is@^0.1.3, deep-is@~0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== -default-require-extensions@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" - integrity sha512-Dn2eAftOqXhNXs5f/Xjn7QTZ6kDYkx7u0EXQInN1oyYwsZysu11q7oTtaKcbzLxZRJiDHa8VmwpWmb4lY5FqgA== +default-require-extensions@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" + integrity sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg== dependencies: - strip-bom "^2.0.0" + strip-bom "^4.0.0" -define-properties@^1.1.2, define-properties@^1.1.3, define-properties@^1.1.4: +define-properties@^1.1.3, define-properties@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.4.tgz#0b14d7bd7fbeb2f3572c3a7eda80ea5d57fb05b1" integrity sha512-uckOqKcfaVvtBdsVkdPv3XjveQJsNQqmhXgRi8uhvWWuPYZCNlzT8qAyblUgNoXdHdjMTzAqeGjAoli8f+bzPA== @@ -2516,13 +2502,6 @@ detab@^2.0.0: dependencies: repeat-string "^1.5.4" -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - integrity sha512-BDKtmHlOzwI7iRuEkhzsnPoi5ypEhWAJB5RvHWe1kMr06js3uK5B3734i3ui5Yd+wOJV1cpE4JnivPD283GU/A== - dependencies: - repeating "^2.0.0" - detect-libc@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.1.tgz#e1897aa88fa6ad197862937fbc0441ef352ee0cd" @@ -2536,10 +2515,10 @@ detective@^4.0.0: acorn "^5.2.1" defined "^1.0.0" -diff@3.5.0: - version "3.5.0" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" - integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== diff@^4.0.1: version "4.0.2" @@ -2693,11 +2672,6 @@ electron-to-chromium@^1.4.202: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" integrity sha512-WfVwM9e+M9B/4Qjh9SRnPX2A74Tom3WlVfWF9QWJ8f2BPa1u+/q4aEp1tizZ3vBKAZTg7B6yxn3t9iMjT+dv4w== -emoji-regex@^7.0.1: - version "7.0.3" - resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" - integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== - emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -2732,7 +2706,7 @@ err-code@^2.0.2: resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9" integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA== -error-ex@^1.2.0, error-ex@^1.3.1: +error-ex@^1.3.1: version "1.3.2" resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== @@ -2796,6 +2770,11 @@ es-to-primitive@^1.2.1: is-date-object "^1.0.1" is-symbol "^1.0.2" +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -2806,16 +2785,16 @@ escape-html@~1.0.3: resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow== -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== - -escape-string-regexp@^4.0.0: +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== +escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== + escodegen@1.8.x: version "1.8.1" resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.8.1.tgz#5a5b53af4693110bebb0867aa3430dd3b70a1018" @@ -2877,6 +2856,14 @@ eslint-plugin-import@^2.8.0: resolve "^1.22.0" tsconfig-paths "^3.14.1" +eslint-plugin-mocha@10.1.0: + version "10.1.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-10.1.0.tgz#69325414f875be87fb2cb00b2ef33168d4eb7c8d" + integrity sha512-xLqqWUF17llsogVOC+8C6/jvQ+4IoOREbN7ZCHuOHuD6cT5cDD4h7f2LgsZuzMAiwswWE21tO7ExaknHVDrSkw== + dependencies: + eslint-utils "^3.0.0" + rambda "^7.1.0" + eslint-plugin-prettier@^4.2.1: version "4.2.1" resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz#651cbb88b1dab98bfd42f017a12fa6b2d993f94b" @@ -3007,19 +2994,6 @@ etag@~1.8.1: resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg== -execa@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" - integrity sha512-RztN09XglpYI7aBBrJCPW95jEH7YF1UEPOoX9yDhUTPdp7mK+CQvnLTuD10BNXZ3byLTu2uehZ8EcKT/4CGiFw== - dependencies: - cross-spawn "^5.0.1" - get-stream "^3.0.0" - is-stream "^1.1.0" - npm-run-path "^2.0.0" - p-finally "^1.0.0" - signal-exit "^3.0.0" - strip-eof "^1.0.0" - execa@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" @@ -3033,13 +3007,6 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -expand-brackets@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-0.1.5.tgz#df07284e342a807cd733ac5af72411e581d1177b" - integrity sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA== - dependencies: - is-posix-bracket "^0.1.0" - expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" @@ -3053,13 +3020,6 @@ expand-brackets@^2.1.4: snapdragon "^0.8.1" to-regex "^3.0.1" -expand-range@^1.8.1: - version "1.8.2" - resolved "https://registry.yarnpkg.com/expand-range/-/expand-range-1.8.2.tgz#a299effd335fe2721ebae8e257ec79644fc85337" - integrity sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA== - dependencies: - fill-range "^2.1.0" - express@~4.16.0: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" @@ -3116,13 +3076,6 @@ extend@^3.0.0, extend@~3.0.2: resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== -extglob@^0.3.1: - version "0.3.2" - resolved "https://registry.yarnpkg.com/extglob/-/extglob-0.3.2.tgz#2e18ff3d2f49ab2765cec9023f011daa8d8349a1" - integrity sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg== - dependencies: - is-extglob "^1.0.0" - extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" @@ -3204,22 +3157,6 @@ file-uri-to-path@1.0.0: resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== -filename-regex@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" - integrity sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ== - -fill-range@^2.1.0: - version "2.2.4" - resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-2.2.4.tgz#eb1e773abb056dcd8df2bfdf6af59b8b3a936565" - integrity sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q== - dependencies: - is-number "^2.1.0" - isobject "^2.0.0" - randomatic "^3.0.0" - repeat-element "^1.1.2" - repeat-string "^1.5.2" - fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" @@ -3255,15 +3192,6 @@ finalhandler@1.1.1: statuses "~1.4.0" unpipe "~1.0.0" -find-cache-dir@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-0.1.1.tgz#c8defae57c8a52a8a784f9e31c57c742e993a0b9" - integrity sha512-Z9XSBoNE7xQiV6MSgPuCfyMokH2K7JdpRkOYE1+mu3d4BFJtx3GW+f6Bo4q8IX6rlf5MYbLBKW0pjl2cWdkm2A== - dependencies: - commondir "^1.0.1" - mkdirp "^0.5.1" - pkg-dir "^1.0.0" - find-cache-dir@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" @@ -3273,34 +3201,36 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-up@3.0.0, find-up@^3.0.0: +find-cache-dir@^3.2.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-up@5.0.0, find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== dependencies: locate-path "^3.0.0" -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - integrity sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA== +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -find-up@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" - integrity sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ== - dependencies: - locate-path "^2.0.0" - -find-up@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" - integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== - dependencies: - locate-path "^6.0.0" + locate-path "^5.0.0" path-exists "^4.0.0" flat-cache@^3.0.4: @@ -3311,12 +3241,10 @@ flat-cache@^3.0.4: flatted "^3.1.0" rimraf "^3.0.2" -flat@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.1.tgz#a392059cc382881ff98642f5da4dde0a959f309b" - integrity sha512-FmTtBsHskrU6FJ2VxCnsDb84wu9zhmO3cUX2kGFb5tuwhfXxGciiT0oRY+cck35QmG+NmGh5eLz6lLCpWTqwpA== - dependencies: - is-buffer "~2.0.3" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== flatted@^3.1.0: version "3.2.6" @@ -3338,25 +3266,18 @@ follow-redirects@1.5.10: dependencies: debug "=3.1.0" -for-in@^1.0.1, for-in@^1.0.2: +for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" integrity sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ== -for-own@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/for-own/-/for-own-0.1.5.tgz#5265c681a4f294dabbf17c9509b6763aa84510ce" - integrity sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw== +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== dependencies: - for-in "^1.0.1" - -foreground-child@^1.5.3, foreground-child@^1.5.6: - version "1.5.6" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-1.5.6.tgz#4fd71ad2dfde96789b980a5c0a295937cb2f5ce9" - integrity sha512-3TOY+4TKV0Ml83PXJQY+JFQaHNV38lzQDIzzXYg1kWdBLenGgoZhAs0CKgzI31vi2pWEpQMq/Yi4bpKwCPkw7g== - dependencies: - cross-spawn "^4" - signal-exit "^3.0.0" + cross-spawn "^7.0.0" + signal-exit "^3.0.2" forever-agent@~0.6.1: version "0.6.1" @@ -3403,6 +3324,11 @@ fresh@0.5.2: resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" integrity sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q== +fromentries@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" + integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== + fs-minipass@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" @@ -3431,6 +3357,11 @@ fsevents@^1.2.7: bindings "^1.5.0" nan "^2.12.1" +fsevents@~2.3.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + function-bind@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" @@ -3495,11 +3426,16 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598" @@ -3509,16 +3445,16 @@ get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1: has "^1.0.3" has-symbols "^1.0.3" +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + get-port@^4.0.0: version "4.2.0" resolved "https://registry.yarnpkg.com/get-port/-/get-port-4.2.0.tgz#e37368b1e863b7629c43c5a323625f95cf24b119" integrity sha512-/b3jarXkH8KJoOMQc3uVGHASwGLPq3gSFJ7tgJm2diza+bydJPTGOibin2steecKeOylE8oY2JERlVWkAJO6yw== -get-stream@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" - integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ== - get-stream@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" @@ -3573,21 +3509,6 @@ github-slugger@^1.0.0, github-slugger@^1.2.1: resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.4.0.tgz#206eb96cdb22ee56fdc53a28d5a302338463444e" integrity sha512-w0dzqw/nt51xMVmlaV1+JRzN+oCa1KfcgGEWhxUG16wbdA+Xnt/yoFO8Z8x/V82ZcZ0wy6ln9QDup5avbhiDhQ== -glob-base@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" - integrity sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA== - dependencies: - glob-parent "^2.0.0" - is-glob "^2.0.0" - -glob-parent@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-2.0.0.tgz#81383d72db054fcccf5336daa902f182f6edbb28" - integrity sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w== - dependencies: - is-glob "^2.0.0" - glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" @@ -3596,7 +3517,7 @@ glob-parent@^3.1.0: is-glob "^3.1.0" path-dirname "^1.0.0" -glob-parent@^5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.0: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== @@ -3626,10 +3547,10 @@ glob-stream@^6.1.0: to-absolute-glob "^2.0.0" unique-stream "^2.0.2" -glob@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== +glob@7.1.6: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -3649,7 +3570,7 @@ glob@^5.0.15: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.6, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: +glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -3678,11 +3599,6 @@ globals@^13.15.0: dependencies: type-fest "^0.20.2" -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== - globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" @@ -3695,7 +3611,7 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.6: +graceful-fs@^4.0.0, graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.6: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== @@ -3710,7 +3626,7 @@ growl@1.10.5: resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== -handlebars@^4.0.1, handlebars@^4.0.3: +handlebars@^4.0.1: version "4.7.7" resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1" integrity sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA== @@ -3735,13 +3651,6 @@ har-validator@~5.1.3: ajv "^6.12.3" har-schema "^2.0.0" -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - integrity sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg== - dependencies: - ansi-regex "^2.0.0" - has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -3769,7 +3678,7 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" -has-symbols@^1.0.0, has-symbols@^1.0.2, has-symbols@^1.0.3: +has-symbols@^1.0.2, has-symbols@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== @@ -3824,6 +3733,14 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +hasha@^5.0.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + hast-util-is-element@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/hast-util-is-element/-/hast-util-is-element-1.1.0.tgz#3b3ed5159a2707c6137b48637fbfe068e175a425" @@ -3879,6 +3796,11 @@ hosted-git-info@^2.1.4: resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" integrity sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw== +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + html-void-elements@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" @@ -4011,23 +3933,16 @@ internal-slot@^1.0.3: has "^1.0.3" side-channel "^1.0.4" -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - integrity sha512-xgs2NH9AE66ucSq4cNG1nhSFghr5l6tdL15Pk+jl46bmmBapgoaY/AacXyaDznAqmGL99TiLSQgO/XazFSKYeQ== - invert-kv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== +ip-regex@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw== + ip@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" @@ -4097,6 +4012,13 @@ is-binary-path@^1.0.0: dependencies: binary-extensions "^1.0.0" +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + is-boolean-object@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" @@ -4110,7 +4032,7 @@ is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.6: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@^2.0.0, is-buffer@^2.0.2, is-buffer@~2.0.3: +is-buffer@^2.0.0, is-buffer@^2.0.2: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== @@ -4171,18 +4093,6 @@ is-descriptor@^1.0.0, is-descriptor@^1.0.2: is-data-descriptor "^1.0.0" kind-of "^6.0.2" -is-dotfile@^1.0.0: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-dotfile/-/is-dotfile-1.0.3.tgz#a6a2f32ffd2dfb04f5ca25ecd0f6b83cf798a1e1" - integrity sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg== - -is-equal-shallow@^0.1.3: - version "0.1.3" - resolved "https://registry.yarnpkg.com/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz#2238098fc221de0bcfa5d9eac4c45d638aa1c534" - integrity sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA== - dependencies: - is-primitive "^2.0.0" - is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" @@ -4195,21 +4105,11 @@ is-extendable@^1.0.1: dependencies: is-plain-object "^2.0.4" -is-extglob@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-1.0.0.tgz#ac468177c4943405a092fc8f29760c6ffc6206c0" - integrity sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww== - is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-finite@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.1.0.tgz#904135c77fb42c0641d6aa1bcdbc4daa8da082f3" - integrity sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w== - is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" @@ -4227,13 +4127,6 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^2.0.0, is-glob@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-2.0.1.tgz#d096f926a3ded5600f3fdfd91198cb0888c2d863" - integrity sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg== - dependencies: - is-extglob "^1.0.0" - is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" @@ -4241,7 +4134,7 @@ is-glob@^3.1.0: dependencies: is-extglob "^2.1.0" -is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== @@ -4253,6 +4146,13 @@ is-hexadecimal@^1.0.0: resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== +is-ip@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-ip/-/is-ip-2.0.0.tgz#68eea07e8a0a0a94c2d080dd674c731ab2a461ab" + integrity sha512-9MTn0dteHETtyUx8pxqMwg5hMBi3pvlyglJ+b79KOCca0po23337LbVV2Hl4xmMvfw++ljnO0/+5G6G+0Szh6g== + dependencies: + ip-regex "^2.0.0" + is-lambda@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-lambda/-/is-lambda-1.0.1.tgz#3d9877899e6a53efc0160504cde15f82e6f061d5" @@ -4275,13 +4175,6 @@ is-number-object@^1.0.4: dependencies: has-tostringtag "^1.0.0" -is-number@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" - integrity sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg== - dependencies: - kind-of "^3.0.2" - is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" @@ -4289,11 +4182,6 @@ is-number@^3.0.0: dependencies: kind-of "^3.0.2" -is-number@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff" - integrity sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ== - is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -4304,6 +4192,11 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg== +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -4311,16 +4204,6 @@ is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" -is-posix-bracket@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz#3334dc79774368e92f016e6fbc0a88f5cd6e6bc4" - integrity sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ== - -is-primitive@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-primitive/-/is-primitive-2.0.0.tgz#207bab91638499c07b2adf240a41a87210034575" - integrity sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q== - is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -4355,6 +4238,11 @@ is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ== +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -4369,7 +4257,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== @@ -4381,7 +4269,7 @@ is-unc-path@^1.0.0: dependencies: unc-path-regex "^0.1.2" -is-utf8@^0.2.0, is-utf8@^0.2.1: +is-utf8@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" integrity sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q== @@ -4440,58 +4328,65 @@ isstream@~0.1.2: resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" integrity sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g== -istanbul-lib-coverage@^1.1.2, istanbul-lib-coverage@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-1.2.1.tgz#ccf7edcd0a0bb9b8f729feeb0930470f9af664f0" - integrity sha512-PzITeunAgyGbtY1ibVIUiV679EFChHjoMNRibEIobvmrCRaIgwLxNucOSimtNWUhEib/oO7QY2imD75JVgCJWQ== +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== -istanbul-lib-hook@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-1.2.2.tgz#bc6bf07f12a641fbf1c85391d0daa8f0aea6bf86" - integrity sha512-/Jmq7Y1VeHnZEQ3TL10VHyb564mn6VrQXHchON9Jf/AEcmQ3ZIiyD1BVzNOKTZf/G3gE+kiGK6SmpF9y3qGPLw== +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== dependencies: - append-transform "^0.4.0" + append-transform "^2.0.0" -istanbul-lib-instrument@^1.10.0: - version "1.10.2" - resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-1.10.2.tgz#1f55ed10ac3c47f2bdddd5307935126754d0a9ca" - integrity sha512-aWHxfxDqvh/ZlxR8BBaEPVSWDPUkGD63VjGQn3jcw8jCp7sHEMKcrj4xfJn/ABzdMEHiQNyvDQhqm5o8+SQg7A== +istanbul-lib-instrument@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz#873c6fff897450118222774696a3f28902d77c1d" + integrity sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ== dependencies: - babel-generator "^6.18.0" - babel-template "^6.16.0" - babel-traverse "^6.18.0" - babel-types "^6.18.0" - babylon "^6.18.0" - istanbul-lib-coverage "^1.2.1" - semver "^5.3.0" + "@babel/core" "^7.7.5" + "@istanbuljs/schema" "^0.1.2" + istanbul-lib-coverage "^3.0.0" + semver "^6.3.0" -istanbul-lib-report@^1.1.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-1.1.5.tgz#f2a657fc6282f96170aaf281eb30a458f7f4170c" - integrity sha512-UsYfRMoi6QO/doUshYNqcKJqVmFe9w51GZz8BS3WB0lYxAllQYklka2wP9+dGZeHYaWIdcXUx8JGdbqaoXRXzw== +istanbul-lib-processinfo@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz#366d454cd0dcb7eb6e0e419378e60072c8626169" + integrity sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg== dependencies: - istanbul-lib-coverage "^1.2.1" - mkdirp "^0.5.1" - path-parse "^1.0.5" - supports-color "^3.1.2" + archy "^1.0.0" + cross-spawn "^7.0.3" + istanbul-lib-coverage "^3.2.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^8.3.2" -istanbul-lib-source-maps@^1.2.3: - version "1.2.6" - resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-1.2.6.tgz#37b9ff661580f8fca11232752ee42e08c6675d8f" - integrity sha512-TtbsY5GIHgbMsMiRw35YBHGpZ1DVFEO19vxxeiDMYaeOFOCzfnYVxvl6pOUIZR4dtPhAGpSMup8OyF8ubsaqEg== +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== dependencies: - debug "^3.1.0" - istanbul-lib-coverage "^1.2.1" - mkdirp "^0.5.1" - rimraf "^2.6.1" - source-map "^0.5.3" + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" -istanbul-reports@^1.4.0: - version "1.5.1" - resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-1.5.1.tgz#97e4dbf3b515e8c484caea15d6524eebd3ff4e1a" - integrity sha512-+cfoZ0UXzWjhAdzosCPP3AN8vvef8XDkWtTfgaN+7L3YTpNYITnCaEkceo5SEYy644VkHka/P1FvkWvrG/rrJw== +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== dependencies: - handlebars "^4.0.3" + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.1.5" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.5.tgz#cc9a6ab25cb25659810e4785ed9d9fb742578bae" + integrity sha512-nUsEMa9pBt/NOHqbcbeJEgqIlY/K7rVWUX6Lql2orY5e9roQOthbR3vtY4zzf2orPELg80fnxxk9zUyPlgwD1w== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" istanbul@^0.4.5: version "0.4.5" @@ -4513,24 +4408,11 @@ istanbul@^0.4.5: which "^1.1.1" wordwrap "^1.0.0" -"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: +js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - integrity sha512-RjTcuD4xjtthQkaWH7dFlH85L+QaVtSoOyGdZ3g6HFhS9dFNDfLyqgm2NFe2X6cQpeFmt0452FJjFG5UameExg== - -js-yaml@3.13.1: - version "3.13.1" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" - integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== - dependencies: - argparse "^1.0.7" - esprima "^4.0.0" - js-yaml@3.x, js-yaml@^3.10.0, js-yaml@^3.13.1: version "3.14.1" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" @@ -4539,6 +4421,13 @@ js-yaml@3.x, js-yaml@^3.10.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.0.0.tgz#f426bc0ff4b4051926cd588c71113183409a121f" + integrity sha512-pqon0s+4ScYUvX30wxQi3PogGFAlUyH0awepWvwkj4jD4v+ova3RiYw8bmA6x2rDrEaj8i/oWKoRxpVNW+Re8Q== + dependencies: + argparse "^2.0.1" + js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" @@ -4551,11 +4440,6 @@ jsbn@~0.1.0: resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" integrity sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg== -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - integrity sha512-Mke0DA0QjUWuJlhsE0ZPPhYiJkRap642SmI/4ztCFaUs6V2AiH1sfecc+57NgaryfAA2VR3v6O+CSjC1jZJKOA== - jsesc@^2.5.1: version "2.5.2" resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" @@ -4689,13 +4573,6 @@ lazystream@^1.0.0: dependencies: readable-stream "^2.0.5" -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - integrity sha512-YiGkH6EnGrDGqLMITnGjXtGmNtjoXw9SVUzcaos8RBi7Ps0VBylkq+vOcY9QE5poLasPCR849ucFUkl0UzUyOw== - dependencies: - invert-kv "^1.0.0" - lcid@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" @@ -4736,17 +4613,6 @@ livereload-js@^2.3.0: resolved "https://registry.yarnpkg.com/livereload-js/-/livereload-js-2.4.0.tgz#447c31cf1ea9ab52fc20db615c5ddf678f78009c" integrity sha512-XPQH8Z2GDP/Hwz2PCDrh2mth4yFejwA1OZ/81Ti3LgKyhDcEjsSsqFWZojHG0va/duGd+WyosY7eXLDoOyqcPw== -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - integrity sha512-cy7ZdNRXdablkXYNI049pthVeXFurRyb9+hA/dZzerZ0pGTx42z+y+ssxBaVV2l70t1muq5IdKhn4UtcoGUY9A== - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - load-json-file@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-4.0.0.tgz#2f5f45ab91e33216234fd53adab668eb4ec0993b" @@ -4757,14 +4623,6 @@ load-json-file@^4.0.0: pify "^3.0.0" strip-bom "^3.0.0" -locate-path@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" - integrity sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA== - dependencies: - p-locate "^2.0.0" - path-exists "^3.0.0" - locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -4773,6 +4631,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -4785,6 +4650,11 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow== +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ== + lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -4825,7 +4695,7 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== -lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.4: +lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.19: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4835,24 +4705,24 @@ log-driver@^1.2.7: resolved "https://registry.yarnpkg.com/log-driver/-/log-driver-1.2.7.tgz#63b95021f0702fedfa2c9bb0a24e7797d71871d8" integrity sha512-U7KCmLdqsGHBLeWqYlFA0V0Sl6P08EE1ZrmA9cxjUE0WVqT9qnyVDPz1kzpFEP0jdJuFnasWIfSd7fsaNXkpbg== -log-symbols@2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-2.2.0.tgz#5740e1c5d6f0dfda4ad9323b5332107ef6b4c40a" - integrity sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg== +log-symbols@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== dependencies: - chalk "^2.0.1" + chalk "^4.0.0" longest-streak@^2.0.1: version "2.0.4" resolved "https://registry.yarnpkg.com/longest-streak/-/longest-streak-2.0.4.tgz#b8599957da5b5dab64dee3fe316fa774597d90e4" integrity sha512-vM6rUVCVUJJt33bnmHiZEvr7wPT78ztX7rojL+LW51bHtLh6HTjx84LA5W4+oa6aKEJA7jJu5LR6vQRBpA5DVg== -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== +loupe@^2.3.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.4.tgz#7e0b9bffc76f148f9be769cb1321d3dcf3cb25f3" + integrity sha512-OvKfgCC2Ndby6aSTREl5aCCPTNIzlDfQZvZxNUrBrihDhL3xcrYegTblhmEiCrg2kKQz4XsFIaemE5BF4ybSaQ== dependencies: - js-tokens "^3.0.0 || ^4.0.0" + get-func-name "^2.0.0" lru-cache@^4.0.1: version "4.1.5" @@ -4877,7 +4747,7 @@ make-dir@^2.0.0, make-dir@^2.1.0: pify "^4.0.1" semver "^5.6.0" -make-dir@^3.1.0: +make-dir@^3.0.0, make-dir@^3.0.2, make-dir@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== @@ -4935,23 +4805,6 @@ markdown-table@^1.1.0: resolved "https://registry.yarnpkg.com/markdown-table/-/markdown-table-1.1.3.tgz#9fcb69bcfdb8717bfd0398c6ec2d93036ef8de60" integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q== -math-random@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/math-random/-/math-random-1.0.4.tgz#5dd6943c938548267016d4e34f057583080c514c" - integrity sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A== - -md5-hex@^1.2.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/md5-hex/-/md5-hex-1.3.0.tgz#d2c4afe983c4370662179b8cad145219135046c4" - integrity sha512-lJEPhRxivsaliY4C6REebtP1Lo8yoQsq2bLVP8mJ6Vvzwu3fXQShzHcWnAqdDm1Y42jhZFg0XRpnrKfZ5mYP6w== - dependencies: - md5-o-matic "^0.1.1" - -md5-o-matic@^0.1.1: - version "0.1.1" - resolved "https://registry.yarnpkg.com/md5-o-matic/-/md5-o-matic-0.1.1.tgz#822bccd65e117c514fab176b25945d54100a03c3" - integrity sha512-QBJSFpsedXUl/Lgs4ySdB2XCzUEcJ3ujpbagdZCkRaYIaC0kFnID8jhc84KEiVv6dNFtIrmW7bqow0lDxgJi6A== - md5@^2.2.1: version "2.3.0" resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f" @@ -5024,13 +4877,6 @@ media-typer@0.3.0: resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" integrity sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ== -mem@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/mem/-/mem-1.1.0.tgz#5edd52b485ca1d900fe64895505399a0dfa45f76" - integrity sha512-nOBDrc/wgpkd3X/JOhMqYR+/eLqlfLP4oQfoBA6QExIxEl+GU01oyEkwWyueyO8110pUKijtiHGhEmYoOn88oQ== - dependencies: - mimic-fn "^1.0.0" - mem@^4.0.0: version "4.3.0" resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" @@ -5045,13 +4891,6 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w== -merge-source-map@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/merge-source-map/-/merge-source-map-1.1.0.tgz#2fdde7e6020939f70906a68f2d7ae685e4c8c646" - integrity sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw== - dependencies: - source-map "^0.6.1" - merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -5062,25 +4901,6 @@ methods@^1.1.1, methods@^1.1.2, methods@~1.1.2: resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" integrity sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w== -micromatch@^2.3.11: - version "2.3.11" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-2.3.11.tgz#86677c97d1720b363431d04d0d15293bd38c1565" - integrity sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA== - dependencies: - arr-diff "^2.0.0" - array-unique "^0.2.1" - braces "^1.8.2" - expand-brackets "^0.1.4" - extglob "^0.3.1" - filename-regex "^2.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.1" - kind-of "^3.0.2" - normalize-path "^2.0.1" - object.omit "^2.0.0" - parse-glob "^3.0.4" - regex-cache "^0.4.2" - micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.5: version "3.1.10" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" @@ -5135,11 +4955,6 @@ mime@^2.2.0: resolved "https://registry.yarnpkg.com/mime/-/mime-2.6.0.tgz#a2a682a95cd4d0cb1d6257e28f83da7e35800367" integrity sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg== -mimic-fn@^1.0.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" - integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== - mimic-fn@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -5226,14 +5041,7 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.4.tgz#fd01504a6797ec5c9be81ff43d204961ed64a512" - integrity sha512-iG9AK/dJLtJ0XNgTuDbSyNS3zECqDlAhnQW4CsNxBG3LQJBbHmRX1egw39DmtOdCAqY+dKXV+sgPgilNWUKMVw== - dependencies: - minimist "^1.2.5" - -mkdirp@0.5.x, mkdirp@^0.5.0, mkdirp@^0.5.1: +mkdirp@0.5.x: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== @@ -5250,34 +5058,36 @@ mocha-lcov-reporter@^1.3.0: resolved "https://registry.yarnpkg.com/mocha-lcov-reporter/-/mocha-lcov-reporter-1.3.0.tgz#469bdef4f8afc9a116056f079df6182d0afb0384" integrity sha512-/5zI2tW4lq/ft8MGpYQ1nIH6yePPtIzdGeUEwFMKfMRdLfAQ1QW2c68eEJop32tNdN5srHa/E2TzB+erm3YMYA== -mocha@^6.2.0: - version "6.2.3" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-6.2.3.tgz#e648432181d8b99393410212664450a4c1e31912" - integrity sha512-0R/3FvjIGH3eEuG17ccFPk117XL2rWxatr81a57D+r/x2uTYZRbdZ4oVidEUMh2W2TJDa7MdAb12Lm2/qrKajg== +mocha@8.4.0: + version "8.4.0" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.4.0.tgz#677be88bf15980a3cae03a73e10a0fc3997f0cff" + integrity sha512-hJaO0mwDXmZS4ghXsvPVriOhsxQ7ofcpQdm8dE+jISUOKopitvnXFQmpRR7jd2K6VBG6E26gU3IAbXXGIbu4sQ== dependencies: - ansi-colors "3.2.3" + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" browser-stdout "1.3.1" - debug "3.2.6" - diff "3.5.0" - escape-string-regexp "1.0.5" - find-up "3.0.0" - glob "7.1.3" + chokidar "3.5.1" + debug "4.3.1" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.6" growl "1.10.5" he "1.2.0" - js-yaml "3.13.1" - log-symbols "2.2.0" + js-yaml "4.0.0" + log-symbols "4.0.0" minimatch "3.0.4" - mkdirp "0.5.4" - ms "2.1.1" - node-environment-flags "1.0.5" - object.assign "4.1.0" - strip-json-comments "2.0.1" - supports-color "6.0.0" - which "1.3.1" + ms "2.1.3" + nanoid "3.1.20" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" wide-align "1.1.3" - yargs "13.3.2" - yargs-parser "13.1.2" - yargs-unparser "1.6.0" + workerpool "6.1.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" module-deps-sortable@5.0.0: version "5.0.0" @@ -5304,17 +5114,12 @@ ms@2.0.0: resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== -ms@^2.0.0, ms@^2.1.1: +ms@2.1.3, ms@^2.0.0, ms@^2.1.1: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== @@ -5324,6 +5129,11 @@ nan@^2.12.1: resolved "https://registry.yarnpkg.com/nan/-/nan-2.16.0.tgz#664f43e45460fb98faf00edca0bb0d7b8dce7916" integrity sha512-UdAqHyFngu7TfQKsCBgAA6pWDkT8MAO7d0jyOecVhN5354xbLqdn8mV9Tat9gepAupm0bt2DbeaSC8vS52MuFA== +nanoid@3.1.20: + version "3.1.20" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.20.tgz#badc263c6b1dcf14b71efaa85f6ab4c1d6cfc788" + integrity sha512-a1cQNyczgKbLX9jwbS/+d7W8fX/RfgYR7lVWwWOGIPNgK2m0MWvrGF6/m4kk6U3QcFMnZf3RIhL0v2Jgh/0Uxw== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -5379,14 +5189,6 @@ node-cache@^4.1.1: clone "2.x" lodash "^4.17.15" -node-environment-flags@1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.5.tgz#fa930275f5bf5dae188d6192b24b4c8bbac3d76a" - integrity sha512-VNYPRfGfmZLx0Ye20jWzHUjyTW/c+6Wq+iLhDzUI4XmhrDd9l/FozXV3F2xOaXjvp0co0+v1YSR3CMP6g+VvLQ== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - node-environment-flags@^1.0.5: version "1.0.6" resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" @@ -5418,6 +5220,13 @@ node-gyp@8.x: tar "^6.1.2" which "^2.0.2" +node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + node-releases@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" @@ -5447,14 +5256,14 @@ normalize-package-data@^2.3.2: semver "2 || 3 || 4 || 5" validate-npm-package-license "^3.0.1" -normalize-path@^2.0.1, normalize-path@^2.1.1: +normalize-path@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" integrity sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w== dependencies: remove-trailing-separator "^1.0.1" -normalize-path@^3.0.0: +normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== @@ -5503,38 +5312,38 @@ number-is-nan@^1.0.0: resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" integrity sha512-4jbtZXNAsfZbAHiiqjLPBiCl16dES1zI4Hpzzxw61Tk+loF+sBDBKx1ICKKKwIqQ7M0mFn1TmkN7euSncWgHiQ== -nyc@^11.6.0: - version "11.9.0" - resolved "https://registry.yarnpkg.com/nyc/-/nyc-11.9.0.tgz#4106e89e8fbe73623a1fc8b6ecb7abaa271ae1e4" - integrity sha512-w8OdJAhXL5izerzZMdqzYKMj/pgHJyY3qEPYBjLLxrhcVoHEY9pU5ENIiZyCgG9OR7x3VcUMoD40o6PtVpfR4g== +nyc@15.1.0: + version "15.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-15.1.0.tgz#1335dae12ddc87b6e249d5a1994ca4bdaea75f02" + integrity sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A== dependencies: - archy "^1.0.0" - arrify "^1.0.1" - caching-transform "^1.0.0" - convert-source-map "^1.5.1" - debug-log "^1.0.1" - default-require-extensions "^1.0.0" - find-cache-dir "^0.1.1" - find-up "^2.1.0" - foreground-child "^1.5.3" - glob "^7.0.6" - istanbul-lib-coverage "^1.1.2" - istanbul-lib-hook "^1.1.0" - istanbul-lib-instrument "^1.10.0" - istanbul-lib-report "^1.1.3" - istanbul-lib-source-maps "^1.2.3" - istanbul-reports "^1.4.0" - md5-hex "^1.2.0" - merge-source-map "^1.1.0" - micromatch "^3.1.10" - mkdirp "^0.5.0" - resolve-from "^2.0.0" - rimraf "^2.6.2" - signal-exit "^3.0.1" - spawn-wrap "^1.4.2" - test-exclude "^4.2.0" - yargs "11.1.0" - yargs-parser "^8.0.0" + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^2.0.0" + get-package-type "^0.1.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^4.0.0" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" oauth-sign@~0.9.0: version "0.9.0" @@ -5560,7 +5369,7 @@ object-inspect@^1.12.0, object-inspect@^1.9.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea" integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ== -object-keys@^1.0.11, object-keys@^1.1.1: +object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== @@ -5572,17 +5381,7 @@ object-visit@^1.0.0: dependencies: isobject "^3.0.0" -object.assign@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" - integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== - dependencies: - define-properties "^1.1.2" - function-bind "^1.1.1" - has-symbols "^1.0.0" - object-keys "^1.0.11" - -object.assign@^4.0.4, object.assign@^4.1.0, object.assign@^4.1.2: +object.assign@^4.0.4, object.assign@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.3.tgz#d36b7700ddf0019abb6b1df1bb13f6445f79051f" integrity sha512-ZFJnX3zltyjcYJL0RoCJuzb+11zWGyaDbjgxZbdV7rFEcHQuYxrZqhow67aA7xpes6LhojyFDaBKAFfogQrikA== @@ -5592,6 +5391,16 @@ object.assign@^4.0.4, object.assign@^4.1.0, object.assign@^4.1.2: has-symbols "^1.0.3" object-keys "^1.1.1" +object.assign@^4.1.2: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + object.entries@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.5.tgz#e1acdd17c4de2cd96d5a08487cfb9db84d881861" @@ -5611,14 +5420,6 @@ object.getownpropertydescriptors@^2.0.3: define-properties "^1.1.4" es-abstract "^1.20.1" -object.omit@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/object.omit/-/object.omit-2.0.1.tgz#1a9c744829f39dbb858c76ca3579ae2a54ebd1fa" - integrity sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA== - dependencies: - for-own "^0.1.4" - is-extendable "^0.1.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -5680,20 +5481,6 @@ ordered-read-streams@^1.0.0: dependencies: readable-stream "^2.0.1" -os-homedir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - integrity sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ== - -os-locale@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-2.1.0.tgz#42bc2900a6b5b8bd17376c8e882b65afccf24bf2" - integrity sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA== - dependencies: - execa "^0.7.0" - lcid "^1.0.0" - mem "^1.1.0" - os-locale@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" @@ -5718,14 +5505,7 @@ p-is-promise@^2.0.0: resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== -p-limit@^1.1.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" - integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== - dependencies: - p-try "^1.0.0" - -p-limit@^2.0.0: +p-limit@^2.0.0, p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== @@ -5739,13 +5519,6 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" -p-locate@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" - integrity sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg== - dependencies: - p-limit "^1.1.0" - p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -5753,6 +5526,13 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -5760,6 +5540,13 @@ p-locate@^5.0.0: dependencies: p-limit "^3.0.2" +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + p-map@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" @@ -5767,16 +5554,21 @@ p-map@^4.0.0: dependencies: aggregate-error "^3.0.0" -p-try@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" - integrity sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww== - p-try@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + parent-module@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" @@ -5805,23 +5597,6 @@ parse-filepath@^1.0.2: map-cache "^0.2.0" path-root "^0.1.1" -parse-glob@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/parse-glob/-/parse-glob-3.0.4.tgz#b2c376cfb11f35513badd173ef0bb6e3a388391c" - integrity sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA== - dependencies: - glob-base "^0.3.0" - is-dotfile "^1.0.0" - is-extglob "^1.0.0" - is-glob "^2.0.0" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - integrity sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ== - dependencies: - error-ex "^1.2.0" - parse-json@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" @@ -5870,13 +5645,6 @@ path-dirname@^1.0.0: resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" integrity sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q== -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - integrity sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ== - dependencies: - pinkie-promise "^2.0.0" - path-exists@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" @@ -5902,7 +5670,7 @@ path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== -path-parse@^1.0.5, path-parse@^1.0.7: +path-parse@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== @@ -5924,15 +5692,6 @@ path-to-regexp@0.1.7: resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ== -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - integrity sha512-S4eENJz1pkiQn9Znv33Q+deTOKmbl+jj1Fl+qiP/vYezj+S8x+J3Uo0ISrx/QoEvIlOaDWJhPaRd1flJ9HXZqg== - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - path-type@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" @@ -5945,6 +5704,11 @@ path-type@^4.0.0: resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -5955,16 +5719,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.3.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== -pify@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== - pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" @@ -5975,30 +5734,11 @@ pify@^4.0.0, pify@^4.0.1: resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - integrity sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw== - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - integrity sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg== - pirates@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/pirates/-/pirates-4.0.5.tgz#feec352ea5c3268fb23a37c702ab1699f35a5f3b" integrity sha512-8V9+HQPupnaXMA23c5hvl69zXvTwTzyAYasnkb0Tts4XvO4CliqONMOnvlq26rkhLC3nWDFBJf73LU1e1VZLaQ== -pkg-dir@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-1.0.0.tgz#7a4b508a8d5bb2d629d447056ff4e9c9314cf3d4" - integrity sha512-c6pv3OE78mcZ92ckebVDqg0aWSoKhOTbwCV6qbCWMk546mAL9pZln0+QsN/yQ7fkucd4+yJPLrCBXNt8Ruk+Eg== - dependencies: - find-up "^1.0.0" - pkg-dir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" @@ -6006,6 +5746,13 @@ pkg-dir@^3.0.0: dependencies: find-up "^3.0.0" +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -6021,11 +5768,6 @@ prelude-ls@~1.1.2: resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== -preserve@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" - integrity sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ== - prettier-linter-helpers@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b" @@ -6048,6 +5790,13 @@ process-nextick-args@~1.0.6: resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" integrity sha512-yN0WQmuCX63LP/TMvAg31nvT6m4vDqJEiiv2CAZqWOGNWutc9DfDk1NPYYmKUFmaVM2UwDowH4u5AHWYP/jxKw== +process-on-spawn@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.0.0.tgz#95b05a23073d30a17acfdc92a440efd2baefdc93" + integrity sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg== + dependencies: + fromentries "^1.2.0" + promise-inflight@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" @@ -6163,14 +5912,17 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== -randomatic@^3.0.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-3.1.1.tgz#b776efc59375984e36c537b2f51a1f0aff0da1ed" - integrity sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw== +rambda@^7.1.0: + version "7.2.1" + resolved "https://registry.yarnpkg.com/rambda/-/rambda-7.2.1.tgz#c533f6e2def4edcd59f967df938ace5dd6da56af" + integrity sha512-Wswj8ZvzdI3VhaGPkZAxaCTwuMmGtgWt7Zxsgyo4P+iTmVnkojvyWaOep5q3ZjMIecW0wtQa66GWxaKkZ24RAA== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== dependencies: - is-number "^4.0.0" - kind-of "^6.0.0" - math-random "^1.0.1" + safe-buffer "^5.1.0" range-parser@~1.2.0: version "1.2.1" @@ -6206,14 +5958,6 @@ raw-body@~1.1.0: bytes "1" string_decoder "0.10" -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - integrity sha512-WD9MTlNtI55IwYUS27iHh9tK3YoIVhxis8yKhLpTqWtml739uXc9NWTpxoHkfZf3+DkCCsXox94/VWZniuZm6A== - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - read-pkg-up@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-4.0.0.tgz#1b221c6088ba7799601c808f91161c66e58f8978" @@ -6222,15 +5966,6 @@ read-pkg-up@^4.0.0: find-up "^3.0.0" read-pkg "^3.0.0" -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - integrity sha512-7BGwRHqt4s/uVbuyoeejRn4YmFnYZiFl4AuaeXHlgZf3sONF0SOGlxs2Pw8g6hCKupo08RafIO5YXFNOKTfwsQ== - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - read-pkg@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-3.0.0.tgz#9cbc686978fee65d16c00e2b19c237fcf6e38389" @@ -6296,6 +6031,13 @@ readdirp@^2.2.1: micromatch "^3.1.10" readable-stream "^2.0.2" +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + redis-commands@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.7.0.tgz#15a6fea2d58281e27b1cd1acfb4b293e278c3a89" @@ -6335,11 +6077,6 @@ regenerate@^1.4.2: resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.2.tgz#b9346d8827e8f5a32f7ba29637d398b69014848a" integrity sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A== -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.13.4: version "0.13.9" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz#8925742a98ffd90814988d7566ad30ca3b263b52" @@ -6352,13 +6089,6 @@ regenerator-transform@^0.15.0: dependencies: "@babel/runtime" "^7.8.4" -regex-cache@^0.4.2: - version "0.4.4" - resolved "https://registry.yarnpkg.com/regex-cache/-/regex-cache-0.4.4.tgz#75bdc58a2a1496cec48a12835bc54c8d562336dd" - integrity sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ== - dependencies: - is-equal-shallow "^0.1.3" - regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" @@ -6405,6 +6135,13 @@ regjsparser@^0.8.2: dependencies: jsesc "~0.5.0" +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA== + dependencies: + es6-error "^4.0.1" + remark-html@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/remark-html/-/remark-html-8.0.0.tgz#9fcb859a6f3cb40f3ef15402950f1a62ec301b3a" @@ -6516,18 +6253,11 @@ repeat-element@^1.1.2: resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.4.tgz#be681520847ab58c7568ac75fbfad28ed42d39e9" integrity sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ== -repeat-string@^1.5.0, repeat-string@^1.5.2, repeat-string@^1.5.4, repeat-string@^1.6.1: +repeat-string@^1.5.0, repeat-string@^1.5.4, repeat-string@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" integrity sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w== -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - integrity sha512-ZqtSMuVybkISo2OWvqvm7iHSWngvdaW3IpsT9/uP8v4gMi591LY6h35wdOfvQdWCKFWZWm2Y1Opp4kV7vQKT6A== - dependencies: - is-finite "^1.0.0" - replace-ext@1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" @@ -6596,16 +6326,16 @@ require-main-filename@^2.0.0: resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== -resolve-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-2.0.0.tgz#9480ab20e94ffa1d9e80a804c7ea147611966b57" - integrity sha512-qpFcKaXsq8+oRoLilkwyc7zHGF5i9Q2/25NIgLQQ/+VVv9rU4qvr6nXVAw1DsnXJyQkZsR4Ytfbtg5ehfcUssQ== - resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + resolve-options@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/resolve-options/-/resolve-options-1.1.0.tgz#32bb9e39c06d67338dc9378c0d6d6074566ad131" @@ -6647,14 +6377,7 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== -rimraf@^2.6.1, rimraf@^2.6.2: - version "2.7.1" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" - integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== - dependencies: - glob "^7.1.3" - -rimraf@^3.0.2: +rimraf@^3.0.0, rimraf@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== @@ -6695,7 +6418,7 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -"semver@2 || 3 || 4 || 5", semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -6736,6 +6459,13 @@ send@0.16.2: range-parser "~1.2.0" statuses "~1.4.0" +serialize-javascript@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" @@ -6806,7 +6536,7 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" -signal-exit@^3.0.0, signal-exit@^3.0.1, signal-exit@^3.0.2, signal-exit@^3.0.7: +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.7: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== @@ -6816,11 +6546,6 @@ slash@^3.0.0: resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== -slide@^1.1.5: - version "1.1.6" - resolved "https://registry.yarnpkg.com/slide/-/slide-1.1.6.tgz#56eb027d65b4d2dce6cb2e2d32c4d4afc9e1d707" - integrity sha512-NwrtjCg+lZoqhFU8fOwl4ay2ei8PaqCBOUV3/ektPY9trO1yQ1oXEfmHAhKArUVUr/hOHvy5f6AdP17dCM0zMw== - smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" @@ -6897,7 +6622,7 @@ source-map-url@^0.4.0: resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.1.tgz#0af66605a745a5a2f91cf1bbf8a7afbc283dec56" integrity sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw== -source-map@^0.5.3, source-map@^0.5.6, source-map@^0.5.7: +source-map@^0.5.6: version "0.5.7" resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ== @@ -6919,17 +6644,17 @@ space-separated-tokens@^1.0.0: resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== -spawn-wrap@^1.4.2: - version "1.4.3" - resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-1.4.3.tgz#81b7670e170cca247d80bf5faf0cfb713bdcf848" - integrity sha512-IgB8md0QW/+tWqcavuFgKYR/qIRvJkRLPJDFaoXtLLUaVcCDK0+HeFTkmQHj3eprcYhc+gOl0aEA1w7qZlYezw== +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== dependencies: - foreground-child "^1.5.6" - mkdirp "^0.5.0" - os-homedir "^1.0.1" - rimraf "^2.6.2" + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" signal-exit "^3.0.2" - which "^1.3.0" + which "^2.0.1" spdx-correct@^3.0.0: version "3.1.1" @@ -7087,7 +6812,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.2.3: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -7096,15 +6821,6 @@ string-width@^1.0.1: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" -string-width@^3.0.0, string-width@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" - integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== - dependencies: - emoji-regex "^7.0.1" - is-fullwidth-code-point "^2.0.0" - strip-ansi "^5.1.0" - string.prototype.trimend@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.5.tgz#914a65baaab25fbdd4ee291ca7dde57e869cb8d0" @@ -7166,47 +6882,38 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" - integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== - dependencies: - ansi-regex "^4.1.0" - -strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== dependencies: ansi-regex "^5.0.1" -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - integrity sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g== - dependencies: - is-utf8 "^0.2.0" - strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q== -strip-json-comments@2.0.1, strip-json-comments@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - -strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + subarg@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/subarg/-/subarg-1.0.0.tgz#f62cf17581e996b48fc965699f54c06ae268b8d2" @@ -7230,7 +6937,7 @@ superagent@3.8.2: qs "^6.5.1" readable-stream "^2.0.5" -superagent@^3.8.3: +superagent@^3.7.0, superagent@^3.8.3: version "3.8.3" resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128" integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA== @@ -7262,19 +6969,14 @@ supertest@^3.0.0: methods "^1.1.2" superagent "^3.8.3" -supports-color@6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.0.0.tgz#76cfe742cf1f41bb9b1c29ad03068c05b4c0e40a" - integrity sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg== +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== dependencies: - has-flag "^3.0.0" + has-flag "^4.0.0" -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - integrity sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g== - -supports-color@^3.1.0, supports-color@^3.1.2: +supports-color@^3.1.0: version "3.2.3" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-3.2.3.tgz#65ac0504b3954171d8a64946b2ae3cbb8a5f54f6" integrity sha512-Jds2VIYDrlp5ui7t8abHN2bjAu4LV/q4N2KivFPpGH0lrka0BMq/33AmECUXlKPcHigkNaqfXRENFju+rlcy+A== @@ -7319,16 +7021,14 @@ tar@^6.0.2, tar@^6.1.11, tar@^6.1.2: mkdirp "^1.0.3" yallist "^4.0.0" -test-exclude@^4.2.0: - version "4.2.3" - resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-4.2.3.tgz#a9a5e64474e4398339245a0a769ad7c2f4a97c20" - integrity sha512-SYbXgY64PT+4GAL2ocI3HwPa4Q4TBKm0cwAVeKOt/Aoc0gSpNRjJX8w0pA1LMKZ3LBmd8pYBqApFNQLII9kavA== +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== dependencies: - arrify "^1.0.1" - micromatch "^2.3.11" - object-assign "^4.1.0" - read-pkg-up "^1.0.1" - require-main-filename "^1.0.1" + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" text-table@^0.2.0: version "0.2.0" @@ -7381,11 +7081,6 @@ to-absolute-glob@^2.0.0: is-absolute "^1.0.0" is-negated-glob "^1.0.0" -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - integrity sha512-lxrWP8ejsq+7E3nNjwYmUBMAgjMTZoTI+sdBOpvNyijeDLa29LUn9QaoXAHv4+Z578hbmHHJKZknzxVtvo77og== - to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -7448,11 +7143,6 @@ trim-lines@^1.0.0: resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.3.tgz#839514be82428fd9e7ec89e35081afe8f6f93115" integrity sha512-E0ZosSWYK2mkSu+KEtQ9/KqarVjA9HztOSX+9FDdNacRAq29RRV6ZQNgob3iuW8Htar9vAfEa6yyt5qBAHZDBA== -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - integrity sha512-WZGXGstmCWgeevgTL54hrCuw1dyMQIzWy7ZfqRJfSmJZBwklI15egmQytFP6bPidmw3M8d5yEowl1niq4vmqZw== - trim-trailing-lines@^1.0.0: version "1.1.4" resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.4.tgz#bd4abbec7cc880462f10b2c8b5ce1d8d1ec7c2c0" @@ -7504,11 +7194,21 @@ type-check@~0.3.2: dependencies: prelude-ls "~1.1.2" +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.20.2: version "0.20.2" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^0.8.0: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + type-is@~1.6.16: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -7517,6 +7217,13 @@ type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.24" +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6, typedarray@~0.0.5: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -7740,6 +7447,11 @@ uuid@^3.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" @@ -7940,20 +7652,20 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== -which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" - integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== - dependencies: - isexe "^2.0.0" - -which@^2.0.1, which@^2.0.2: +which@2.0.2, which@^2.0.1, which@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== dependencies: isexe "^2.0.0" +which@^1.1.1, which@^1.2.9: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + wide-align@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -7978,6 +7690,11 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q== +workerpool@6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.1.0.tgz#a8e038b4c94569596852de7a8ea4228eefdeb37b" + integrity sha512-toV7q9rWNYha963Pl/qyeZ6wG+3nnsyvolaNUS8+R5Wtw6qJPTxIlOP1ZSvcGhEJw+l3HMMmtiNo9Gl61G4GVg== + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -7986,28 +7703,38 @@ wrap-ansi@^2.0.0: string-width "^1.0.1" strip-ansi "^3.0.1" -wrap-ansi@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" - integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== dependencies: - ansi-styles "^3.2.0" - string-width "^3.0.0" - strip-ansi "^5.0.0" + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== -write-file-atomic@^1.1.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-1.3.4.tgz#f807a4f0b1d9e913ae7a48112e6cc3af1991b45f" - integrity sha512-SdrHoC/yVBPpV0Xq/mUZQIpW2sWXAShb/V4pomcJXh92RuaO+f3UTWItiR3Px+pLnV2PvC2/bfn5cwr5X6Vfxw== +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== dependencies: - graceful-fs "^4.1.11" imurmurhash "^0.1.4" - slide "^1.1.5" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" x-is-string@^0.1.0: version "0.1.0" @@ -8019,16 +7746,16 @@ xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== -y18n@^3.2.1: - version "3.2.2" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.2.tgz#85c901bd6470ce71fc4bb723ad209b70f7f28696" - integrity sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ== - "y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" @@ -8039,13 +7766,10 @@ yallist@^4.0.0: resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yargs-parser@13.1.2, yargs-parser@^13.1.2: - version "13.1.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" - integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== - dependencies: - camelcase "^5.0.0" - decamelize "^1.2.0" +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== yargs-parser@^11.1.1: version "11.1.1" @@ -8055,62 +7779,41 @@ yargs-parser@^11.1.1: camelcase "^5.0.0" decamelize "^1.2.0" -yargs-parser@^8.0.0: - version "8.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-8.1.0.tgz#f1376a33b6629a5d063782944da732631e966950" - integrity sha512-yP+6QqN8BmrgW2ggLtTbdrOyBNSI7zBa4IykmiV5R1wl1JWNxQvWhMfMdmzIYtKU7oP3OOInY/tl2ov3BDjnJQ== +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== dependencies: - camelcase "^4.1.0" + camelcase "^5.0.0" + decamelize "^1.2.0" -yargs-parser@^9.0.2: - version "9.0.2" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-9.0.2.tgz#9ccf6a43460fe4ed40a9bb68f48d43b8a68cc077" - integrity sha512-CswCfdOgCr4MMsT1GzbEJ7Z2uYudWyrGX8Bgh/0eyCzj/DXWdKq6a/ADufkzI1WAOIW6jYaXJvRyLhDO0kfqBw== - dependencies: - camelcase "^4.1.0" +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== -yargs-unparser@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-1.6.0.tgz#ef25c2c769ff6bd09e4b0f9d7c605fb27846ea9f" - integrity sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw== +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== dependencies: - flat "^4.1.0" - lodash "^4.17.15" - yargs "^13.3.0" + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" -yargs@11.1.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77" - integrity sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A== +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== dependencies: - cliui "^4.0.0" - decamelize "^1.1.1" - find-up "^2.1.0" - get-caller-file "^1.0.1" - os-locale "^2.0.0" + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1" - yargs-parser "^9.0.2" - -yargs@13.3.2, yargs@^13.3.0: - version "13.3.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" - integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== - dependencies: - cliui "^5.0.0" - find-up "^3.0.0" - get-caller-file "^2.0.1" - require-directory "^2.1.1" - require-main-filename "^2.0.0" - set-blocking "^2.0.0" - string-width "^3.0.0" - which-module "^2.0.0" - y18n "^4.0.0" - yargs-parser "^13.1.2" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" yargs@^12.0.2: version "12.0.5" @@ -8130,6 +7833,23 @@ yargs@^12.0.2: y18n "^3.2.1 || ^4.0.0" yargs-parser "^11.1.1" +yargs@^15.0.2: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" -- 2.34.1 From 03de831d13c94116b838c5062365eeebe6e6408a Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 13:08:57 +0200 Subject: [PATCH 10/26] Updated mocha & nyc. Removed production config. Updated gitignore --- .eslintrc.json | 4 ++++ .gitignore | 5 ++++- configurations/production.json | 31 ------------------------------- 3 files changed, 8 insertions(+), 32 deletions(-) delete mode 100644 configurations/production.json diff --git a/.eslintrc.json b/.eslintrc.json index 157265e..0b63480 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,6 +5,7 @@ "sourceType": "module" }, "extends": ["eslint-config-airbnb-base", "plugin:prettier/recommended"], + "plugins": ["mocha"], "rules": { "max-classes-per-file": 1, "no-empty": [ @@ -16,5 +17,8 @@ "no-promise-executor-return": 1, "no-shadow": "off", "no-underscore-dangle": "off" + }, + "env": { + "mocha": true } } diff --git a/.gitignore b/.gitignore index 45073a4..2e19d0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,11 @@ .DS_Store -development.json +configurations/development.json +configurations/production.json .env shows.db node_modules */package-lock.json +.nyc_output +yarn-error.log diff --git a/configurations/production.json b/configurations/production.json deleted file mode 100644 index 017f9dd..0000000 --- a/configurations/production.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "database": { - "host": "/Users/kevin/dev/seasonedShows/shows.db" - }, - "webserver": { - "port": 31459, - "origins": ["https://kevinmidboe.com", "https://seasoned.show", "https://request.movie"] - }, - "tmdb": { - "apiKey": "9fa154f5355c37a1b9b57ac06e7d6712" - }, - "plex": { - "ip": "blex.schleppe" - }, - "tautulli": { - "apiKey": "4e759f7acabf4f1a8893825e6acd522b", - "ip": "blex.schleppe", - "port": "8181" - }, - "raven": { - "DSN": "" - }, - "authentication": { - "secret": "secret" - }, - "sms": { - "apikey": "qK48YChORZOX4FqAwgzdOrfYT2-bixwshtRe-BogNksBZyUrMHLTh0-XOjsxziPV", - "sender": "Seasoned", - "recipient": 41498549 - } -} -- 2.34.1 From 7b8ca68fc8fc122c7a3ccd8bf0b0f9e7d32b0aa0 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 13:56:11 +0200 Subject: [PATCH 11/26] Updated test commands to omit system tests, no exit code --- package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 49eac02..f7ce9b9 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,10 @@ "scripts": { "start": "yarn cross-env SEASONED_CONFIG=configurations/production.json NODE_ENV=production babel-node src/webserver/server.js", "dev": "yarn cross-env SEASONED_CONFIG=configurations/development.json NODE_ENV=development babel-node src/webserver/server.js", - "test": "cross-env SEASONED_CONFIG=configurations/test.json NODE_PATH=. mocha --require @babel/register --recursive tests/unit tests/system", - "coverage": "cross-env SEASONED_CONFIG=configurations/test.json NODE_PATH=. nyc mocha --require @babel/register --recursive test && nyc report --reporter=text-lcov | coveralls", - "lint": "eslint src", + "test": "cross-env SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit", + "coverage:upload": "cross-env SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report --reporter=text-lcov | coveralls", + "coverage": "cross-env SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report", + "lint": "eslint src tests", "update": "cross-env SEASONED_CONFIG=configurations/development.json NODE_PATH=. node scripts/updateRequestsInPlex.js", "docs": "yarn apiDocs; yarn classDocs", "apiDocs": "", -- 2.34.1 From d58f9751f4d1ed619befd56c57e9339ad2222fcb Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 13:56:37 +0200 Subject: [PATCH 12/26] Updated test configuration w/ missing keys --- configurations/test.json | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/configurations/test.json b/configurations/test.json index 8f4af80..760ca72 100644 --- a/configurations/test.json +++ b/configurations/test.json @@ -2,19 +2,30 @@ "database": { "host": ":memory:" }, + "redis": { + "host": "localhost", + "port": 6379 + }, "webserver": { - "port": 31400 + "port": 31400, + "origins": [] }, "tmdb": { "apiKey": "bogus-api-key" }, "plex": { - "ip": "0.0.0.0" + "ip": "localhost", + "token": "" + }, + "tautulli": { + "apiKey": "", + "ip": "", + "port": "" }, "raven": { "DSN": "" }, "authentication": { - "secret": "secret" - } + "secret": "secret" + } } -- 2.34.1 From cacff37df3ee4541d94eb002f838e11b68a98a3f Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 14:01:21 +0200 Subject: [PATCH 13/26] Chai modules defined in package.json & resolved linting errors --- package.json | 2 ++ tests/system/asAUserIWantToGetPopularShows.js | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index f7ce9b9..021a0aa 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,8 @@ "@babel/preset-env": "^7.5.5", "@babel/register": "^7.5.5", "@types/node": "^12.6.8", + "chai": "^4.3.6", + "chai-http": "^4.3.0", "coveralls": "^3.0.5", "documentation": "^12.0.3", "eslint": "^8.22.0", diff --git a/tests/system/asAUserIWantToGetPopularShows.js b/tests/system/asAUserIWantToGetPopularShows.js index b3bb175..122ea3b 100644 --- a/tests/system/asAUserIWantToGetPopularShows.js +++ b/tests/system/asAUserIWantToGetPopularShows.js @@ -1,13 +1,13 @@ -const assert = require("assert"); +// const assert = require("assert"); // const request = require("supertest-as-promised"); const chai = require("chai"); const chaiHttp = require("chai-http"); -const server = require("../../src/webserver/server"); +const server = require("../../src/webserver/server"); const resetDatabase = require("../helpers/resetDatabase"); const createCacheEntry = require("../helpers/createCacheEntry"); const popularShowsSuccess = require("../fixtures/popular-show-success-response.json"); -const should = chai.should(); +// const should = chai.should(); chai.use(chaiHttp); // describe("system test", () => { -- 2.34.1 From 104b5e09fdfa5e1ca97a5f5acfd163ef1425a671 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 14:13:49 +0200 Subject: [PATCH 14/26] Dockerfile copies development.example -> production.json. Simplified commands --- Dockerfile | 2 +- package.json | 13 ++++----- yarn.lock | 81 ++-------------------------------------------------- 3 files changed, 10 insertions(+), 86 deletions(-) diff --git a/Dockerfile b/Dockerfile index 3704ca2..310dddd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ COPY yarn.lock . RUN apt update RUN apt install node-pre-gyp -y RUN yarn -RUN cp configurations/development.json.example configurations/development.json +RUN cp configurations/development.json.example configurations/production.json EXPOSE 31459 diff --git a/package.json b/package.json index 021a0aa..39b8435 100644 --- a/package.json +++ b/package.json @@ -7,13 +7,13 @@ }, "main": "webserver/server.js", "scripts": { - "start": "yarn cross-env SEASONED_CONFIG=configurations/production.json NODE_ENV=production babel-node src/webserver/server.js", - "dev": "yarn cross-env SEASONED_CONFIG=configurations/development.json NODE_ENV=development babel-node src/webserver/server.js", - "test": "cross-env SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit", - "coverage:upload": "cross-env SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report --reporter=text-lcov | coveralls", - "coverage": "cross-env SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report", + "start": "SEASONED_CONFIG=configurations/production.json NODE_ENV=production node src/webserver/server.js", + "dev": "SEASONED_CONFIG=configurations/development.json NODE_ENV=development node src/webserver/server.js", + "test": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit", + "coverage:upload": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report --reporter=text-lcov | coveralls", + "coverage": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report", "lint": "eslint src tests", - "update": "cross-env SEASONED_CONFIG=configurations/development.json NODE_PATH=. node scripts/updateRequestsInPlex.js", + "update": "SEASONED_CONFIG=configurations/development.json node scripts/updateRequestsInPlex.js", "docs": "yarn apiDocs; yarn classDocs", "apiDocs": "", "classDocs": "scripts/generate-class-docs.sh" @@ -39,7 +39,6 @@ }, "devDependencies": { "@babel/core": "^7.5.5", - "@babel/node": "^7.5.5", "@babel/preset-env": "^7.5.5", "@babel/register": "^7.5.5", "@types/node": "^12.6.8", diff --git a/yarn.lock b/yarn.lock index a0d32ad..2ed4bfe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -262,18 +262,6 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/node@^7.5.5": - version "7.18.10" - resolved "https://registry.yarnpkg.com/@babel/node/-/node-7.18.10.tgz#ab2be57785346b5bf0721c3d17572402419d9d8a" - integrity sha512-VbqzK6QXfQVi4Bpk6J7XqHXKFNbG2j3rdIdx68+/14GDU7jXDOSyUU/cwqCM1fDwCdxp37pNV/ToSCXsNChcyA== - dependencies: - "@babel/register" "^7.18.9" - commander "^4.0.1" - core-js "^3.22.1" - node-environment-flags "^1.0.5" - regenerator-runtime "^0.13.4" - v8flags "^3.1.1" - "@babel/parser@7.9.4": version "7.9.4" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.9.4.tgz#68a35e6b0319bbc014465be43828300113f2f2e8" @@ -1075,7 +1063,7 @@ resolved "https://registry.yarnpkg.com/@babel/preset-stage-0/-/preset-stage-0-7.8.3.tgz#b6a0eca1a3b72e07f9caf58f998e97568028f6f5" integrity sha512-+l6FlG1j73t4wh78W41StbcCz0/9a1/y+vxfnjtHl060kSmcgMfGzK9MEkLvrCOXfhp9RCX+d88sm6rOqxEIEQ== -"@babel/register@^7.18.9", "@babel/register@^7.5.5": +"@babel/register@^7.5.5": version "7.18.9" resolved "https://registry.yarnpkg.com/@babel/register/-/register-7.18.9.tgz#1888b24bc28d5cc41c412feb015e9ff6b96e439c" integrity sha512-ZlbnXDcNYHMR25ITwwNKT88JiaukkdVj/nG7r3wnuXkOTHc60Uy05PwMCPre0hSkY68E6zK3xz+vUJSP2jWmcw== @@ -1560,17 +1548,6 @@ array.prototype.flat@^1.2.5: es-abstract "^1.19.2" es-shim-unscopables "^1.0.0" -array.prototype.reduce@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array.prototype.reduce/-/array.prototype.reduce-1.0.4.tgz#8167e80089f78bff70a99e20bd4201d4663b0a6f" - integrity sha512-WnM+AjG/DvLRLo4DDl+r+SvCzYtD2Jd9oeBYMcEaI7t3fFrHY9M53/wdLcTvmZNQ70IU6Htj0emFkZ5TS+lrdw== - dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" - es-abstract "^1.19.2" - es-array-method-boxes-properly "^1.0.0" - is-string "^1.0.7" - asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -2174,11 +2151,6 @@ comma-separated-tokens@^1.0.1: resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== -commander@^4.0.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" - integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2286,11 +2258,6 @@ core-js-compat@^3.21.0, core-js-compat@^3.22.1: browserslist "^4.21.3" semver "7.0.0" -core-js@^3.22.1: - version "3.24.1" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.24.1.tgz#cf7724d41724154010a6576b7b57d94c5d66e64f" - integrity sha512-0QTBSYSUZ6Gq21utGzkfITDylE8jWC9Ne1D2MrhvlsZBI1x39OdDIVbzSqtgMndIy6BlHxBXpMGqzZmnztg2rg== - core-util-is@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" @@ -2720,7 +2687,7 @@ error@^7.0.0: dependencies: string-template "~0.2.1" -es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5, es-abstract@^1.20.1: +es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19.5: version "1.20.1" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.20.1.tgz#027292cd6ef44bd12b1913b828116f54787d1814" integrity sha512-WEm2oBhfoI2sImeM4OF2zE2V3BYdSF+KnSi9Sidz51fQHd7+JuF8Xgcj9/0o+OWeIeIS/MiuNnlruQrJf16GQA== @@ -2749,11 +2716,6 @@ es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.2, es-abstract@^1.19 string.prototype.trimstart "^1.0.5" unbox-primitive "^1.0.2" -es-array-method-boxes-properly@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz#873f3e84418de4ee19c5be752990b2e44718d09e" - integrity sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA== - es-shim-unscopables@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" @@ -3784,13 +3746,6 @@ highlight.js@^9.15.5: resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== -homedir-polyfill@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz#743298cef4e5af3e194161fbadcc2151d3a058e8" - integrity sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA== - dependencies: - parse-passwd "^1.0.0" - hosted-git-info@^2.1.4: version "2.8.9" resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.8.9.tgz#dffc0bf9a21c02209090f2aa69429e1414daf3f9" @@ -5189,14 +5144,6 @@ node-cache@^4.1.1: clone "2.x" lodash "^4.17.15" -node-environment-flags@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088" - integrity sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw== - dependencies: - object.getownpropertydescriptors "^2.0.3" - semver "^5.7.0" - node-fetch@^2.6.0, node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" @@ -5410,16 +5357,6 @@ object.entries@^1.1.5: define-properties "^1.1.3" es-abstract "^1.19.1" -object.getownpropertydescriptors@^2.0.3: - version "2.1.4" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.4.tgz#7965e6437a57278b587383831a9b829455a4bc37" - integrity sha512-sccv3L/pMModT6dJAYF3fzGMVcb38ysQ0tEE6ixv2yXJDtEIPph268OlAdJj5/qZMZDq2g/jqvwppt36uS/uQQ== - dependencies: - array.prototype.reduce "^1.0.4" - call-bind "^1.0.2" - define-properties "^1.1.4" - es-abstract "^1.20.1" - object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" @@ -5605,11 +5542,6 @@ parse-json@^4.0.0: error-ex "^1.3.1" json-parse-better-errors "^1.0.1" -parse-passwd@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/parse-passwd/-/parse-passwd-1.0.0.tgz#6d5b934a456993b23d37f40a382d6f1666a8e5c6" - integrity sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q== - parse-path@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/parse-path/-/parse-path-4.0.4.tgz#4bf424e6b743fb080831f03b536af9fc43f0ffea" @@ -6418,7 +6350,7 @@ safe-regex@^1.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0, semver@^5.7.0: +"semver@2 || 3 || 4 || 5", semver@^5.5.0, semver@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -7457,13 +7389,6 @@ v8-compile-cache@^2.0.3: resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" integrity sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA== -v8flags@^3.1.1: - version "3.2.0" - resolved "https://registry.yarnpkg.com/v8flags/-/v8flags-3.2.0.tgz#b243e3b4dfd731fa774e7492128109a0fe66d656" - integrity sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg== - dependencies: - homedir-polyfill "^1.0.1" - validate-npm-package-license@^3.0.1: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" -- 2.34.1 From b4758040eeba97b8cf6c3cf65712e85e02bceb71 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 16:52:34 +0200 Subject: [PATCH 15/26] All api calls from tests use same chaiHttp implementation Removes a list of fetch alternatives after being replaced by chaiHttp: - request - request-promise - supertest - supertest-as-promised --- package.json | 10 +---- .../asADeveloperIWantTheServerToRegister.js | 23 ++++++---- tests/system/asADeveloperIWantToLogin.js | 42 +++++++++++++------ ...antAForbiddenErrorIfTheTokenIsMalformed.js | 21 +++++++--- ...GetErrorWhenRegisteringExistingUsername.js | 33 +++++++++------ .../system/asAUserIWantToGetPopularMovies.js | 28 ++++++++----- tests/system/asAUserIWantToGetPopularShows.js | 15 ++----- tests/system/asAUserIWantToRequestAMovie.js | 17 +++++--- ...asAnAnonymousUserIWantToSearchForAMovie.js | 24 ++++++++--- 9 files changed, 130 insertions(+), 83 deletions(-) diff --git a/package.json b/package.json index 39b8435..dadded6 100644 --- a/package.json +++ b/package.json @@ -19,22 +19,16 @@ "classDocs": "scripts/generate-class-docs.sh" }, "dependencies": { - "axios": "^0.18.0", "bcrypt": "^5.0.1", "body-parser": "~1.18.2", "cookie-parser": "^1.4.6", - "cross-env": "~5.1.4", "express": "~4.16.0", "form-data": "^2.5.1", "jsonwebtoken": "^8.5.1", "km-moviedb": "^0.2.12", - "node-cache": "^4.1.1", - "node-fetch": "^2.6.0", "python-shell": "^0.5.0", "raven": "^2.4.2", "redis": "^3.0.2", - "request": "^2.87.0", - "request-promise": "^4.2", "sqlite3": "^5.0.1" }, "devDependencies": { @@ -56,8 +50,6 @@ "mocha": "8.4.0", "mocha-lcov-reporter": "^1.3.0", "nyc": "15.1.0", - "prettier": "^2.7.1", - "supertest": "^3.0.0", - "supertest-as-promised": "^4.0.1" + "prettier": "^2.7.1" } } diff --git a/tests/system/asADeveloperIWantTheServerToRegister.js b/tests/system/asADeveloperIWantTheServerToRegister.js index 1d7936d..c205081 100644 --- a/tests/system/asADeveloperIWantTheServerToRegister.js +++ b/tests/system/asADeveloperIWantTheServerToRegister.js @@ -1,17 +1,24 @@ const assert = require("assert"); -const request = require("supertest-as-promised"); -const app = require("../../src/webserver/app"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); + +const server = require("../../src/webserver/server"); const resetDatabase = require("../helpers/resetDatabase"); +chai.use(chaiHttp); + describe("As a user I want to register", () => { beforeEach(() => resetDatabase()); - it("should return 200 and a message indicating success", () => - request(app) + it("should return 200 and a message indicating success", done => { + chai + .request(server) .post("/api/v1/user") .send({ username: "test", email: "test@gmail.com", password: "password" }) - .expect(200) - .then(response => - assert.equal(response.body.message, "Welcome to Seasoned!") - )); + .end((error, response) => { + assert.equal(response?.status, 200); + assert.equal(response?.body?.message, "Welcome to Seasoned!"); + done(); + }); + }); }); diff --git a/tests/system/asADeveloperIWantToLogin.js b/tests/system/asADeveloperIWantToLogin.js index 96bdb78..f920340 100644 --- a/tests/system/asADeveloperIWantToLogin.js +++ b/tests/system/asADeveloperIWantToLogin.js @@ -1,24 +1,40 @@ -const request = require("supertest-as-promised"); -const app = require("../../src/webserver/app"); +const assert = require("assert"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); + +const server = require("../../src/webserver/server"); const createUser = require("../helpers/createUser"); const resetDatabase = require("../helpers/resetDatabase"); -// const assert = require("assert"); + +chai.use(chaiHttp); describe("As a user I want to log in", () => { - beforeEach(() => { - return resetDatabase().then(() => createUser("test_user", "password")); - }); + beforeEach(() => resetDatabase()); + beforeEach(() => createUser("test_user", "password")); - it("should return 200 with a token if correct credentials are given", () => - request(app) + it("should return 200 with a token if correct credentials are given", done => { + chai + .request(server) .post("/api/v1/user/login") .send({ username: "test_user", password: "password" }) - .expect(200)); - // .then(response => assert.equal(typeof response.body.token, "string"))); + .end((error, response) => { + // console.log(response); - it("should return 401 if incorrect credentials are given", () => - request(app) + assert.equal(response?.status, 200); + done(); + }); + }); + + it("should return 401 if incorrect credentials are given", done => { + chai + .request(server) .post("/api/v1/user/login") .send({ username: "test_user", password: "anti-password" }) - .expect(401)); + .end((error, response) => { + // console.log(response); + + assert.equal(response?.status, 401); + done(); + }); + }); }); diff --git a/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js b/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js index 59007d1..72d0074 100644 --- a/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js +++ b/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js @@ -1,17 +1,26 @@ -const request = require("supertest-as-promised"); -const app = require("../../src/webserver/app"); +const assert = require("assert"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); + +const server = require("../../src/webserver/server"); const resetDatabase = require("../helpers/resetDatabase"); // const assert = require("assert"); +chai.use(chaiHttp); describe("As a user I want a forbidden error if the token is malformed", () => { beforeEach(() => resetDatabase()); - it("should return 401", () => - request(app) + it("should return 401", done => { + chai + .request(server) .get("/api/v1/user/settings") .set("Authorization", "maLfOrMed TOKEN") - .expect(401)); + .end((error, response) => { + assert.equal(response?.status, 401); + done(); + }); + }); // .then(response => { // assert.equal(response.body.error, "You must be logged in."); - // })); + // }));} }); diff --git a/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js b/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js index fa5e7f7..6a7248f 100644 --- a/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js +++ b/tests/system/asAUserIWantToGetErrorWhenRegisteringExistingUsername.js @@ -1,23 +1,30 @@ const assert = require("assert"); -const request = require("supertest-as-promised"); -const app = require("../../src/webserver/app"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); + +const server = require("../../src/webserver/server"); const createUser = require("../helpers/createUser"); const resetDatabase = require("../helpers/resetDatabase"); -describe("As a user I want error when registering existing username", () => { - beforeEach(() => { - return resetDatabase().then(() => createUser("test_user", "password")); - }); +chai.use(chaiHttp); - it("should return 401 with error message when same username is given", () => - request(app) +describe("As a user I want error when registering existing username", () => { + beforeEach(() => resetDatabase()); + beforeEach(() => createUser("test_user", "password")); + + it("should return 401 with error message when same username is given", done => { + chai + .request(server) .post("/api/v1/user") .send({ username: "test_user", password: "password" }) - .expect(401) - .then(response => + .end((error, response) => { + // console.log(response); + assert.equal(response?.status, 401); assert.equal( - response.text, + response?.text, '{"success":false,"message":"That username is already registered"}' - ) - )); + ); + done(); + }); + }); }); diff --git a/tests/system/asAUserIWantToGetPopularMovies.js b/tests/system/asAUserIWantToGetPopularMovies.js index 13f7bb9..3f4fedb 100644 --- a/tests/system/asAUserIWantToGetPopularMovies.js +++ b/tests/system/asAUserIWantToGetPopularMovies.js @@ -1,21 +1,27 @@ const assert = require("assert"); -const request = require("supertest-as-promised"); -const app = require("../../src/webserver/app"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); + +const server = require("../../src/webserver/server"); const resetDatabase = require("../helpers/resetDatabase"); const createCacheEntry = require("../helpers/createCacheEntry"); const popularMoviesSuccess = require("../fixtures/popular-movies-success-response.json"); +chai.use(chaiHttp); + describe("As a user I want to get popular movies", () => { beforeEach(() => resetDatabase()); - beforeEach(() => - createCacheEntry("tmdb/miscPopularMovies:1", popularMoviesSuccess) - ); + beforeEach(() => createCacheEntry("tmdb/pm:1", popularMoviesSuccess)); - it("should return 200 with the information", () => - request(app) + it("should return 200 with the information", done => { + chai + .request(server) .get("/api/v2/movie/popular") - .expect(200) - .then(response => { - assert.equal(response.body?.results?.length, 20); - })); + .end((error, response) => { + // console.log(response); + + assert.equal(response?.status, 200); + done(); + }); + }); }); diff --git a/tests/system/asAUserIWantToGetPopularShows.js b/tests/system/asAUserIWantToGetPopularShows.js index 122ea3b..b2f0065 100644 --- a/tests/system/asAUserIWantToGetPopularShows.js +++ b/tests/system/asAUserIWantToGetPopularShows.js @@ -1,5 +1,4 @@ -// const assert = require("assert"); -// const request = require("supertest-as-promised"); +const assert = require("assert"); const chai = require("chai"); const chaiHttp = require("chai-http"); @@ -7,29 +6,21 @@ const server = require("../../src/webserver/server"); const resetDatabase = require("../helpers/resetDatabase"); const createCacheEntry = require("../helpers/createCacheEntry"); const popularShowsSuccess = require("../fixtures/popular-show-success-response.json"); -// const should = chai.should(); chai.use(chaiHttp); -// describe("system test", () => { -// it("should run", () => { -// assert.equal(1, 1); -// }); -// }); describe("As a user I want to get popular shows", () => { beforeEach(() => resetDatabase()); - beforeEach(() => createCacheEntry("pt:1", popularShowsSuccess)); + beforeEach(() => createCacheEntry("tmdb/pt:1", popularShowsSuccess)); it("should return 200 with the information", done => { chai .request(server) .get("/api/v2/show/popular") .end((error, response) => { - response.should.have.status(200); + assert.equal(response?.status, 200); done(); }); - - // done(); }); // .end((err, res) => { diff --git a/tests/system/asAUserIWantToRequestAMovie.js b/tests/system/asAUserIWantToRequestAMovie.js index 686855e..a0a6c45 100644 --- a/tests/system/asAUserIWantToRequestAMovie.js +++ b/tests/system/asAUserIWantToRequestAMovie.js @@ -1,5 +1,8 @@ -const request = require("supertest-as-promised"); -const app = require("../../src/webserver/app"); +const assert = require("assert"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); + +const server = require("../../src/webserver/server"); const createUser = require("../helpers/createUser"); const createToken = require("../helpers/createToken"); const resetDatabase = require("../helpers/resetDatabase"); @@ -11,10 +14,14 @@ describe("As a user I want to request a movie", () => { beforeEach(() => createUser("test_user", "test@gmail.com", "password")); beforeEach(() => createCacheEntry("mi:335984:false", infoMovieSuccess)); - it("should return 200 when item is requested", () => - request(app) + it("should return 200 when item is requested", () => { + chai + .request(server) .post("/api/v2/request") .set("authorization", createToken("test_user", "secret")) .send({ id: 335984, type: "movie" }) - .expect(200)); + .end((error, response) => { + assert.equal(response?.status, 200); + }); + }); }); diff --git a/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js b/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js index 4621352..d2e6bb4 100644 --- a/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js +++ b/tests/system/asAnAnonymousUserIWantToSearchForAMovie.js @@ -1,17 +1,29 @@ -const request = require("supertest-as-promised"); -const app = require("../../src/webserver/app"); +const assert = require("assert"); +const chai = require("chai"); +const chaiHttp = require("chai-http"); + +const server = require("../../src/webserver/server"); const resetDatabase = require("../helpers/resetDatabase"); const createCacheEntry = require("../helpers/createCacheEntry"); const interstellarQuerySuccess = require("../fixtures/interstellar-query-movie-success-response.json"); +chai.use(chaiHttp); + describe("As an anonymous user I want to search for a movie", () => { beforeEach(() => resetDatabase()); beforeEach(() => - createCacheEntry("mos:1:interstellar", interstellarQuerySuccess) + createCacheEntry("tmdb/mos:1:interstellar:false", interstellarQuerySuccess) ); - it("should return 200 with the search results even if user is not logged in", () => - request(app) + it("should return 200 with the search results even if user is not logged in", done => { + chai + .request(server) .get("/api/v2/search/movie?query=interstellar&page=1") - .expect(200)); + .end((error, response) => { + // console.log(response); + + assert.equal(response?.status, 200); + done(); + }); + }); }); -- 2.34.1 From 39e335423b86f8f3c079172498158bf2af1b45bf Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 16:54:27 +0200 Subject: [PATCH 16/26] Tests should use redis (mock) cache, not tmdb sqlite cache --- tests/helpers/createCacheEntry.js | 5 +- yarn.lock | 124 ++---------------------------- 2 files changed, 10 insertions(+), 119 deletions(-) diff --git a/tests/helpers/createCacheEntry.js b/tests/helpers/createCacheEntry.js index f415c04..910b980 100644 --- a/tests/helpers/createCacheEntry.js +++ b/tests/helpers/createCacheEntry.js @@ -1,8 +1,7 @@ -const Cache = require("../../src/tmdb/cache"); +const redisCache = require("../../src/cache/redis"); function createCacheEntry(key, value) { - const cache = new Cache(); - return cache.set(key, value); + return redisCache.set(key, value); } module.exports = createCacheEntry; diff --git a/yarn.lock b/yarn.lock index 2ed4bfe..188066f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1600,14 +1600,6 @@ aws4@^1.8.0: resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^0.18.0: - version "0.18.1" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.18.1.tgz#ff3f0de2e7b5d180e757ad98000f1081b87bcea3" - integrity sha512-0BfJq4NSfQXd+SkFdrvFbG7addhYSBA2mQwISr46pD6E5iqkWg02RAs8vyTT/j0RTnoYmeXauBuSv1qKwR179g== - dependencies: - follow-redirects "1.5.10" - is-buffer "^2.0.2" - babel-plugin-dynamic-import-node@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz#84fda19c976ec5c6defef57f9427b3def66e17a3" @@ -1699,11 +1691,6 @@ bindings@^1.5.0: dependencies: file-uri-to-path "1.0.0" -bluebird@^3.3.1, bluebird@^3.5.0: - version "3.7.2" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" - integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== - body-parser@1.18.3, body-parser@~1.18.2: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" @@ -2078,7 +2065,7 @@ clone-stats@^1.0.0: resolved "https://registry.yarnpkg.com/clone-stats/-/clone-stats-1.0.0.tgz#b3782dff8bb5474e18b9b6bf0fdfe782f8777680" integrity sha512-au6ydSpg6nsrigcZ4m8Bc9hxjeW+GJ8xh5G3BJCMt4WXe1H10UNaVOamqQTmrx1kjVuxAHIQSNU6hY4Nsn9/ag== -clone@2.x, clone@^2.1.1: +clone@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w== @@ -2279,23 +2266,6 @@ coveralls@^3.0.5: minimist "^1.2.5" request "^2.88.2" -cross-env@~5.1.4: - version "5.1.6" - resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-5.1.6.tgz#0dc05caf945b24e4b9e3b12871fe0e858d08b38d" - integrity sha512-VWTDq+G4v383SzgRS7jsAVWqEWF0aKZpDz1GVjhONvPRgHB1LnxP2sXUVFKbykHkPSnfRKS8YdiDevWFwZmQ9g== - dependencies: - cross-spawn "^5.1.0" - is-windows "^1.0.0" - -cross-spawn@^5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-5.1.0.tgz#e8bd0efee58fcff6f8f94510a0a554bbfa235449" - integrity sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A== - dependencies: - lru-cache "^4.0.1" - shebang-command "^1.2.0" - which "^1.2.9" - cross-spawn@^6.0.0: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -2354,13 +2324,6 @@ debug@4.3.1: dependencies: ms "2.1.2" -debug@=3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g== - dependencies: - ms "2.0.0" - debug@^3.1.0, debug@^3.2.7: version "3.2.7" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" @@ -3221,13 +3184,6 @@ flush-write-stream@^1.0.2: inherits "^2.0.3" readable-stream "^2.3.6" -follow-redirects@1.5.10: - version "1.5.10" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" - integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ== - dependencies: - debug "=3.1.0" - for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -3987,7 +3943,7 @@ is-buffer@^1.1.4, is-buffer@^1.1.5, is-buffer@~1.1.6: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== -is-buffer@^2.0.0, is-buffer@^2.0.2: +is-buffer@^2.0.0: version "2.0.5" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== @@ -4246,7 +4202,7 @@ is-whitespace-character@^1.0.0: resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== -is-windows@^1.0.0, is-windows@^1.0.1, is-windows@^1.0.2: +is-windows@^1.0.1, is-windows@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== @@ -4650,7 +4606,7 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg== -lodash@^4.17.10, lodash@^4.17.15, lodash@^4.17.19: +lodash@^4.17.10: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -4679,14 +4635,6 @@ loupe@^2.3.1: dependencies: get-func-name "^2.0.0" -lru-cache@^4.0.1: - version "4.1.5" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" - integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== - dependencies: - pseudomap "^1.0.2" - yallist "^2.1.2" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -5136,15 +5084,7 @@ node-addon-api@^4.2.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== -node-cache@^4.1.1: - version "4.2.1" - resolved "https://registry.yarnpkg.com/node-cache/-/node-cache-4.2.1.tgz#efd8474dee4edec4138cdded580f5516500f7334" - integrity sha512-BOb67bWg2dTyax5kdef5WfU3X8xu4wPg+zHzkvls0Q/QpYycIFRLEEIdAx9Wma43DxG6Qzn4illdZoYseKWa4A== - dependencies: - clone "2.x" - lodash "^4.17.15" - -node-fetch@^2.6.0, node-fetch@^2.6.7: +node-fetch@^2.6.7: version "2.6.7" resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== @@ -5767,11 +5707,6 @@ proxy-addr@~2.0.4: forwarded "0.2.0" ipaddr.js "1.9.1" -pseudomap@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" - integrity sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ== - psl@^1.1.28: version "1.9.0" resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7" @@ -6200,24 +6135,7 @@ replace-ext@^1.0.0: resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.1.tgz#2d6d996d04a15855d967443631dd5f77825b016a" integrity sha512-yD5BHCe7quCgBph4rMQ+0KkIRKwWCrHDOX1p1Gp6HwjPM5kVoCdKGNhN7ydqqsX6lJEnQDKZ/tFMiEdQ1dvPEw== -request-promise-core@1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.4.tgz#3eedd4223208d419867b78ce815167d10593a22f" - integrity sha512-TTbAfBBRdWD7aNNOoVOBH4pN/KigV6LyapYNNlAPA8JwbovRti1E88m3sYAwsLi5ryhPKsE9APwnjFTgdUjTpw== - dependencies: - lodash "^4.17.19" - -request-promise@^4.2: - version "4.2.6" - resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.6.tgz#7e7e5b9578630e6f598e3813c0f8eb342a27f0a2" - integrity sha512-HCHI3DJJUakkOr8fNoCc73E5nU5bqITjOYFMDrKHYOXWXrgD/SBaC7LjwuPymUprRyuF06UK7hd/lMHkmUXglQ== - dependencies: - bluebird "^3.5.0" - request-promise-core "1.1.4" - stealthy-require "^1.1.1" - tough-cookie "^2.3.3" - -request@^2.87.0, request@^2.88.2: +request@^2.88.2: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -6692,11 +6610,6 @@ statuses@~1.4.0: resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" integrity sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew== -stealthy-require@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g== - stream-array@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/stream-array/-/stream-array-1.1.2.tgz#9e5f7345f2137c30ee3b498b9114e80b52bb7eb5" @@ -6869,7 +6782,7 @@ superagent@3.8.2: qs "^6.5.1" readable-stream "^2.0.5" -superagent@^3.7.0, superagent@^3.8.3: +superagent@^3.7.0: version "3.8.3" resolved "https://registry.yarnpkg.com/superagent/-/superagent-3.8.3.tgz#460ea0dbdb7d5b11bc4f78deba565f86a178e128" integrity sha512-GLQtLMCoEIK4eDv6OGtkOoSMt3D+oq0y3dsxMuYuDvaNUvuT8eFBuLmfR0iYYzHC1e8hpzC6ZsxbuP6DIalMFA== @@ -6885,22 +6798,6 @@ superagent@^3.7.0, superagent@^3.8.3: qs "^6.5.1" readable-stream "^2.3.5" -supertest-as-promised@^4.0.1: - version "4.0.2" - resolved "https://registry.yarnpkg.com/supertest-as-promised/-/supertest-as-promised-4.0.2.tgz#0464f2bd256568d4a59bce84269c0548f6879f1a" - integrity sha512-w1OLRFLCQHWtVh2uBIxdFfECYVu0XY6DckEA3GQq+3GXZEoM2v0Y0Wn/PuZRFAxNTmBbhlk2S780yu3ocdmWRQ== - dependencies: - bluebird "^3.3.1" - methods "^1.1.1" - -supertest@^3.0.0: - version "3.4.2" - resolved "https://registry.yarnpkg.com/supertest/-/supertest-3.4.2.tgz#bad7de2e43d60d27c8caeb8ab34a67c8a5f71aad" - integrity sha512-WZWbwceHUo2P36RoEIdXvmqfs47idNNZjCuJOqDz6rvtkk8ym56aU5oglORCpPeXGxT7l9rkJ41+O1lffQXYSA== - dependencies: - methods "^1.1.2" - superagent "^3.8.3" - supports-color@8.1.1: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -7057,7 +6954,7 @@ to-through@^2.0.0: dependencies: through2 "^2.0.3" -tough-cookie@^2.3.3, tough-cookie@~2.5.0: +tough-cookie@~2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== @@ -7681,11 +7578,6 @@ y18n@^5.0.5: resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== -yallist@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" - integrity sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" -- 2.34.1 From 3e069ea1a1c690f1e7717619239a9180017befd9 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 16:56:18 +0200 Subject: [PATCH 17/26] Disabled test asADeveloperIWantTheServerToStart --- ...ToStart.js => asADeveloperIWantTheServerToStart.js.disabled} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename tests/system/{asADeveloperIWantTheServerToStart.js => asADeveloperIWantTheServerToStart.js.disabled} (87%) diff --git a/tests/system/asADeveloperIWantTheServerToStart.js b/tests/system/asADeveloperIWantTheServerToStart.js.disabled similarity index 87% rename from tests/system/asADeveloperIWantTheServerToStart.js rename to tests/system/asADeveloperIWantTheServerToStart.js.disabled index c96a333..c957eb4 100644 --- a/tests/system/asADeveloperIWantTheServerToStart.js +++ b/tests/system/asADeveloperIWantTheServerToStart.js.disabled @@ -8,6 +8,6 @@ describe("As a developer I want the server to start", () => { }); it("should listen on port 31400", done => { - net.createConnection(31400, done); + net.createConnection(31459, done); }); }); -- 2.34.1 From 7e1f89e1ad59b60c227414cc2ab56f1e79260e29 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 16:56:44 +0200 Subject: [PATCH 18/26] Re-enable tests/system --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index dadded6..4d311e4 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "scripts": { "start": "SEASONED_CONFIG=configurations/production.json NODE_ENV=production node src/webserver/server.js", "dev": "SEASONED_CONFIG=configurations/development.json NODE_ENV=development node src/webserver/server.js", - "test": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit", + "test": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit tests/system", "coverage:upload": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report --reporter=text-lcov | coveralls", "coverage": "SEASONED_CONFIG=configurations/test.json mocha --recursive tests/unit && nyc report", "lint": "eslint src tests", -- 2.34.1 From 0bbd10c24b75eeba16555e0c870f079ec66226bf Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 16:57:55 +0200 Subject: [PATCH 19/26] Use chaiHttp in asAUserIWantToRequestAMovie. --- tests/system/asAUserIWantToRequestAMovie.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/system/asAUserIWantToRequestAMovie.js b/tests/system/asAUserIWantToRequestAMovie.js index a0a6c45..2fd9d73 100644 --- a/tests/system/asAUserIWantToRequestAMovie.js +++ b/tests/system/asAUserIWantToRequestAMovie.js @@ -9,6 +9,8 @@ const resetDatabase = require("../helpers/resetDatabase"); const createCacheEntry = require("../helpers/createCacheEntry"); const infoMovieSuccess = require("../fixtures/blade_runner_2049-info-success-response.json"); +chai.use(chaiHttp); + describe("As a user I want to request a movie", () => { beforeEach(() => resetDatabase()); beforeEach(() => createUser("test_user", "test@gmail.com", "password")); -- 2.34.1 From 16469ee2eb30ebcec32d09f2b4321cde286f0790 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 16:58:41 +0200 Subject: [PATCH 20/26] Fixed redis expire & mock implmentation --- src/cache/redis.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/cache/redis.js b/src/cache/redis.js index fdee990..dee6e5f 100644 --- a/src/cache/redis.js +++ b/src/cache/redis.js @@ -1,6 +1,7 @@ const configuration = require("../config/configuration").getInstance(); let client; +const mockCache = {}; try { const redis = require("redis"); // eslint-disable-line global-require @@ -8,7 +9,6 @@ try { const host = configuration.get("redis", "host"); const port = configuration.get("redis", "port"); - console.log(`redis://${host}:${port}`); // eslint-disable-line no-console client = redis.createClient({ url: `redis://${host}:${port}` }); @@ -20,13 +20,18 @@ try { console.error("Unable to connect to redis, setting up redis-mock."); // eslint-disable-line no-console client = { - get(command) { - console.log(`redis-dummy get: ${command}`); // eslint-disable-line no-console - return Promise.resolve(); + get(key, callback) { + console.log(`redis-dummy get: ${key}`); // eslint-disable-line no-console + const hit = mockCache[key]; + return Promise.resolve().then(callback(null, hit)); }, - set(command) { - console.log(`redis-dummy set: ${command}`); // eslint-disable-line no-console - return Promise.resolve(); + set(key, json, callback) { + console.log(`redis-dummy set: ${key}`); // eslint-disable-line no-console + mockCache[key] = JSON.stringify(json); + return Promise.resolve().then(callback(null, "OK")); + }, + expire(key, TTL) { + console.log(`redis-dummy expire: ${key} with TTL ${TTL}`); // eslint-disable-line no-console } }; }); @@ -39,7 +44,7 @@ function set(key, value, TTL = 10800) { client.set(key, json, (error, reply) => { if (reply === "OK") { // successfully set value with key, now set TTL for key - client.expire(key, TTL, e => { + client.expire(key, TTL, "NX", e => { if (e) // eslint-disable-next-line no-console console.error( -- 2.34.1 From 098ee95f4021ac8ccdc7715afb521f5ffdbee4eb Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 16:59:50 +0200 Subject: [PATCH 21/26] Replaced all fetch alternatives from source code and package.json --- src/notifications/sms.js | 29 ++++++++---------- src/plex/plex.js | 1 - src/plex/plexRepository.js | 30 ++++++++----------- src/plex/requestRepository.js | 5 +++- src/tautulli/tautulli.js | 2 -- src/webserver/controllers/plex/plexPlaying.js | 5 +++- src/webserver/controllers/plex/searchMedia.js | 5 +++- src/webserver/server.js | 2 -- 8 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/notifications/sms.js b/src/notifications/sms.js index b9e6f41..8dbb3fe 100644 --- a/src/notifications/sms.js +++ b/src/notifications/sms.js @@ -1,4 +1,3 @@ -const request = require("request"); const configuration = require("../config/configuration").getInstance(); class SMSUnexpectedError extends Error { @@ -20,23 +19,21 @@ const sendSMS = message => { const sender = configuration.get("sms", "sender"); const recipient = configuration.get("sms", "recipient"); + const smsRequestHeaders = { "Content-Type": "application/json" }; + const smsRequestBody = { + sender, + message, + recipients: [{ msisdn: `47${recipient}` }] + }; return new Promise((resolve, reject) => { - request.post( - { - url: `https://gatewayapi.com/rest/mtsms?token=${apiKey}`, - json: true, - body: { - sender, - message, - recipients: [{ msisdn: `47${recipient}` }] - } - }, - (err, r, body) => { - if (err) reject(new SMSUnexpectedError(err || body)); - resolve(body); - } - ); + fetch(`https://gatewayapi.com/rest/mtsms?token=${apiKey}`, { + body: JSON.stringify(smsRequestBody), + headers: smsRequestHeaders + }) + .then(resp => resp.json()) + .then(response => resolve(response)) + .catch(error => reject(new SMSUnexpectedError(error))); }); }; diff --git a/src/plex/plex.js b/src/plex/plex.js index 01b9cee..09c74e9 100644 --- a/src/plex/plex.js +++ b/src/plex/plex.js @@ -1,4 +1,3 @@ -const fetch = require("node-fetch"); const convertPlexToMovie = require("./convertPlexToMovie"); const convertPlexToShow = require("./convertPlexToShow"); const convertPlexToEpisode = require("./convertPlexToEpisode"); diff --git a/src/plex/plexRepository.js b/src/plex/plexRepository.js index 472111f..4018ce2 100644 --- a/src/plex/plexRepository.js +++ b/src/plex/plexRepository.js @@ -1,4 +1,3 @@ -const rp = require("request-promise"); const convertPlexToSeasoned = require("./convertPlexToSeasoned"); const convertPlexToStream = require("./convertPlexToStream"); @@ -35,8 +34,9 @@ function mapResults(response) { } class PlexRepository { - constructor(plexIP) { + constructor(plexIP, plexToken) { this.plexIP = plexIP; + this.plexToken = plexToken; } inPlex(_tmdbResult) { @@ -56,19 +56,17 @@ class PlexRepository { } search(query) { - const queryUri = encodeURIComponent(query); - const uri = encodeURI( - `http://${this.plexIP}:32400/search?query=${queryUri}` + const url = encodeURI( + `http://${this.plexIP}:32400/search?query=${encodeURIComponent( + query + )}&X-Plex-Token=${this.plexToken}` ); const options = { - uri, - headers: { - Accept: "application/json" - }, - json: true + headers: { Accept: "application/json" } }; - return rp(options) + return fetch(url, options) + .then(resp => resp.json()) .then(result => mapResults(result)) .then(([mappedResults, resultCount]) => ({ results: mappedResults, @@ -77,15 +75,13 @@ class PlexRepository { } nowPlaying() { + const url = `http://${this.plexIP}:32400/status/sessions?X-Plex-Token=${this.plexToken}`; const options = { - uri: `http://${this.plexIP}:32400/status/sessions`, - headers: { - Accept: "application/json" - }, - json: true + headers: { Accept: "application/json" } }; - return rp(options) + return fetch(url, options) + .then(resp => resp.json()) .then(result => { if (result.MediaContainer.size > 0) { const playing = diff --git a/src/plex/requestRepository.js b/src/plex/requestRepository.js index 85caaf1..ebe8f63 100644 --- a/src/plex/requestRepository.js +++ b/src/plex/requestRepository.js @@ -3,7 +3,10 @@ const configuration = require("../config/configuration").getInstance(); const TMDB = require("../tmdb/tmdb"); const establishedDatabase = require("../database/database"); -const plexRepository = new PlexRepository(configuration.get("plex", "ip")); +const plexRepository = new PlexRepository( + configuration.get("plex", "ip"), + configuration.get("plex", "token") +); const tmdb = new TMDB(configuration.get("tmdb", "apiKey")); class RequestRepository { diff --git a/src/tautulli/tautulli.js b/src/tautulli/tautulli.js index f5fdf3d..90b7b29 100644 --- a/src/tautulli/tautulli.js +++ b/src/tautulli/tautulli.js @@ -1,5 +1,3 @@ -const fetch = require("node-fetch"); - class TautulliUnexpectedError extends Error { constructor(errorMessage) { const message = "Unexpected error fetching from tautulli."; diff --git a/src/webserver/controllers/plex/plexPlaying.js b/src/webserver/controllers/plex/plexPlaying.js index aa153b6..4c07c17 100644 --- a/src/webserver/controllers/plex/plexPlaying.js +++ b/src/webserver/controllers/plex/plexPlaying.js @@ -1,7 +1,10 @@ const PlexRepository = require("../../../plex/plexRepository"); const configuration = require("../../../config/configuration").getInstance(); -const plexRepository = new PlexRepository(configuration.get("plex", "ip")); +const plexRepository = new PlexRepository( + configuration.get("plex", "ip"), + configuration.get("plex", "token") +); function playingController(req, res) { plexRepository diff --git a/src/webserver/controllers/plex/searchMedia.js b/src/webserver/controllers/plex/searchMedia.js index d64cefe..07d941d 100644 --- a/src/webserver/controllers/plex/searchMedia.js +++ b/src/webserver/controllers/plex/searchMedia.js @@ -1,7 +1,10 @@ const PlexRepository = require("../../../plex/plexRepository"); const configuration = require("../../../config/configuration").getInstance(); -const plexRepository = new PlexRepository(configuration.get("plex", "ip")); +const plexRepository = new PlexRepository( + configuration.get("plex", "ip"), + configuration.get("plex", "token") +); /** * Controller: Search for media and check existence diff --git a/src/webserver/server.js b/src/webserver/server.js index 95dc9c7..dae8d96 100644 --- a/src/webserver/server.js +++ b/src/webserver/server.js @@ -4,8 +4,6 @@ const app = require("./app"); module.exports = app.listen(config.get("webserver", "port"), () => { /* eslint-disable no-console */ console.log("seasonedAPI"); - /* eslint-disable no-console */ console.log(`Database is located at ${config.get("database", "host")}`); - /* eslint-disable no-console */ console.log(`Webserver is listening on ${config.get("webserver", "port")}`); }); -- 2.34.1 From 22919b3060867c6fa8b0a85853fc235ffe29f815 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 17:08:00 +0200 Subject: [PATCH 22/26] Pass error from tmdb api back to client as errorMessage --- src/tmdb/tmdb.js | 8 ++++---- src/webserver/controllers/movie/info.js | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tmdb/tmdb.js b/src/tmdb/tmdb.js index 9adb346..054d1e8 100644 --- a/src/tmdb/tmdb.js +++ b/src/tmdb/tmdb.js @@ -38,17 +38,17 @@ class TMDBNotReachableError extends Error { } const tmdbErrorResponse = (error, type = null) => { - if (error.status === 404) { - const message = error.response.body.status_message; + if (error?.status === 404) { + const message = error?.response?.body?.status_message; throw new TMDBNotFoundError(`${message.slice(0, -1)} in tmdb.`); - } else if (error.status === 401) { + } else if (error?.status === 401) { throw new TMDBUnauthorizedError(error?.response?.body?.status_message); } else if (error?.code === "ENOTFOUND") { throw new TMDBNotReachableError(); } - throw new TMDBUnexpectedError(type, error); + throw new TMDBUnexpectedError(type, error.message); }; /** diff --git a/src/webserver/controllers/movie/info.js b/src/webserver/controllers/movie/info.js index 6311b88..aa6b486 100644 --- a/src/webserver/controllers/movie/info.js +++ b/src/webserver/controllers/movie/info.js @@ -44,6 +44,7 @@ async function movieInfoController(req, res) { } catch (error) { return res.status(error?.statusCode || 500).send({ success: false, + errorMessage: error?.errorMessage, message: error?.message || `An unexpected error occured while requesting info for with id: ${movieId}` -- 2.34.1 From ff410194edb8aaf592606c4b7dbf1ae566e7e175 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 17:17:31 +0200 Subject: [PATCH 23/26] Updated authentication middleware to handle checks consitenctly --- src/webserver/middleware/mustBeAdmin.js | 4 ++-- src/webserver/middleware/mustBeAuthenticated.js | 2 +- src/webserver/middleware/mustHaveAccountLinkedToPlex.js | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/webserver/middleware/mustBeAdmin.js b/src/webserver/middleware/mustBeAdmin.js index 50e9c71..89e82a6 100644 --- a/src/webserver/middleware/mustBeAdmin.js +++ b/src/webserver/middleware/mustBeAdmin.js @@ -4,8 +4,8 @@ const establishedDatabase = require("../../database/database"); const mustBeAdmin = (req, res, next) => { const database = establishedDatabase; - if (req.loggedInUser === undefined) { - res.status(401).send({ + if (!req.loggedInUser) { + return res.status(401).send({ success: false, message: "You must be logged in." }); diff --git a/src/webserver/middleware/mustBeAuthenticated.js b/src/webserver/middleware/mustBeAuthenticated.js index 9a470db..4cbd8eb 100644 --- a/src/webserver/middleware/mustBeAuthenticated.js +++ b/src/webserver/middleware/mustBeAuthenticated.js @@ -1,6 +1,6 @@ // eslint-disable-next-line consistent-return const mustBeAuthenticated = (req, res, next) => { - if (req.loggedInUser === undefined) { + if (!req.loggedInUser) { return res.status(401).send({ success: false, message: "You must be logged in." diff --git a/src/webserver/middleware/mustHaveAccountLinkedToPlex.js b/src/webserver/middleware/mustHaveAccountLinkedToPlex.js index 49e4849..95fd3cc 100644 --- a/src/webserver/middleware/mustHaveAccountLinkedToPlex.js +++ b/src/webserver/middleware/mustHaveAccountLinkedToPlex.js @@ -3,9 +3,9 @@ const establishedDatabase = require("../../database/database"); /* eslint-disable consistent-return */ const mustHaveAccountLinkedToPlex = (req, res, next) => { const database = establishedDatabase; - const { loggedInUser } = req; - if (loggedInUser === null) { + // TODO use mustByAuthenticated middleware + if (!req.loggedInUser) { return res.status(401).send({ success: false, message: "You must have your account linked to a plex account." @@ -15,7 +15,7 @@ const mustHaveAccountLinkedToPlex = (req, res, next) => { database .get( `SELECT plex_userid FROM settings WHERE user_name IS ?`, - loggedInUser.username + req.loggedInUser.username ) .then(row => { const plexUserId = row.plex_userid; -- 2.34.1 From 705b6cbc1c53c43adfc3e355288a0d3c8a54a9a0 Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 17:18:36 +0200 Subject: [PATCH 24/26] Prevent assert error when checking request status, returns success 200 --- src/request/request.js | 11 +++++------ src/webserver/controllers/request/getRequest.js | 14 +++++++++++++- ...serIWantAForbiddenErrorIfTheTokenIsMalformed.js | 2 +- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/request/request.js b/src/request/request.js index 3f3d91b..e5a034e 100644 --- a/src/request/request.js +++ b/src/request/request.js @@ -33,7 +33,8 @@ class RequestRepository { // downloaded: "(select status from requests where id is request.id and type is request.type limit 1)", // deluge: '(select status from deluge_torrent where id is request.id and type is request.type limit 1)', // fetchAllFilterStatus: 'select * from request where ' - // readWithoutUserData: "select id, title, year, type, status, date from requests where id is ? and type is ?", + readWithoutUserData: + "select id, title, year, type, status, date from requests where id is ? and type is ?", read: "select id, title, year, type, status, requested_by, ip, date, user_agent from requests where id is ? and type is ?" }; } @@ -83,7 +84,8 @@ class RequestRepository { return this.database .get(this.queries.readWithoutUserData, [id, type]) .then(row => { - assert(row, "Could not find request item with that id and type"); + if (!row) return null; + return { id: row.id, title: row.title, @@ -122,10 +124,7 @@ class RequestRepository { return this.database .all(fetchQuery, fetchParams) .then(async rows => { - const sqliteResponse = await this.database.get( - fetchTotalResults, - filter || null - ); + const sqliteResponse = await this.database.get(fetchTotalResults); const { totalRequests } = sqliteResponse; const totalPages = Math.ceil(totalRequests / 26); diff --git a/src/webserver/controllers/request/getRequest.js b/src/webserver/controllers/request/getRequest.js index b4a491f..d73f091 100644 --- a/src/webserver/controllers/request/getRequest.js +++ b/src/webserver/controllers/request/getRequest.js @@ -14,7 +14,19 @@ function fetchAllRequests(req, res) { request .getRequestByIdAndType(id, type) - .then(result => res.send(result)) + .then(result => { + if (!result) { + return res.send({ + success: false, + message: `Item ${type} with id ${id} has not been requested` + }); + } + + return res.send({ + success: true, + result + }); + }) .catch(error => { return res.status(error?.statusCode || 500).send({ success: false, diff --git a/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js b/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js index 72d0074..8dc4c9c 100644 --- a/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js +++ b/tests/system/asAUserIWantAForbiddenErrorIfTheTokenIsMalformed.js @@ -4,7 +4,7 @@ const chaiHttp = require("chai-http"); const server = require("../../src/webserver/server"); const resetDatabase = require("../helpers/resetDatabase"); -// const assert = require("assert"); + chai.use(chaiHttp); describe("As a user I want a forbidden error if the token is malformed", () => { -- 2.34.1 From a24a9cd6dd3d35ecc9378a492dbc376a2b82a38e Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 17:37:45 +0200 Subject: [PATCH 25/26] Resolved merge conflicts --- src/plex/plexRepository.js | 1 - src/tautulli/tautulli.js | 14 -------------- src/tmdb/tmdb.js | 38 -------------------------------------- 3 files changed, 53 deletions(-) diff --git a/src/plex/plexRepository.js b/src/plex/plexRepository.js index 3bdc6e5..4018ce2 100644 --- a/src/plex/plexRepository.js +++ b/src/plex/plexRepository.js @@ -1,4 +1,3 @@ -const rp = require("request-promise"); const convertPlexToSeasoned = require("./convertPlexToSeasoned"); const convertPlexToStream = require("./convertPlexToStream"); diff --git a/src/tautulli/tautulli.js b/src/tautulli/tautulli.js index a40fee2..90b7b29 100644 --- a/src/tautulli/tautulli.js +++ b/src/tautulli/tautulli.js @@ -12,20 +12,6 @@ function logTautulliError(error) { throw new TautulliUnexpectedError(error); } -class TautulliUnexpectedError extends Error { - constructor(errorMessage) { - const message = "Unexpected error fetching from tautulli."; - super(message); - - this.statusCode = 500; - this.errorMessage = errorMessage; - } -} - -function logTautulliError(error) { - throw new TautulliUnexpectedError(error); -} - class Tautulli { constructor(apiKey, ip, port) { this.apiKey = apiKey; diff --git a/src/tmdb/tmdb.js b/src/tmdb/tmdb.js index df1bb49..054d1e8 100644 --- a/src/tmdb/tmdb.js +++ b/src/tmdb/tmdb.js @@ -37,44 +37,6 @@ class TMDBNotReachableError extends Error { } } -const tmdbErrorResponse = (error, type = null) => { - if (error.status === 404) { - const message = error.response.body.status_message; - - throw new TMDBNotFoundError(`${message.slice(0, -1)} in tmdb.`); - } else if (error.status === 401) { - throw new TMDBUnauthorizedError(error?.response?.body?.status_message); - } else if (error?.code === "ENOTFOUND") { - throw new TMDBNotReachableError(); - } -} - -class TMDBUnauthorizedError extends Error { - constructor(message = "TMDB returned access denied, requires api token.") { - super(message); - - this.statusCode = 401; - } -} - -class TMDBUnexpectedError extends Error { - constructor(type, errorMessage) { - const message = `An unexpected error occured while fetching ${type} from tmdb`; - super(message); - - this.errorMessage = errorMessage; - this.statusCode = 500; - } -} - -class TMDBNotReachableError extends Error { - constructor( - message = "TMDB api not reachable, check your internet connection" - ) { - super(message); - } -} - const tmdbErrorResponse = (error, type = null) => { if (error?.status === 404) { const message = error?.response?.body?.status_message; -- 2.34.1 From 2b5bf08de8e98c5041ea69d292b178febf2557bf Mon Sep 17 00:00:00 2001 From: Kevin Midboe Date: Sat, 20 Aug 2022 17:39:47 +0200 Subject: [PATCH 26/26] Only build and publish docker container when branch master --- .drone.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.drone.yml b/.drone.yml index 3747730..3dd8bc9 100644 --- a/.drone.yml +++ b/.drone.yml @@ -77,11 +77,11 @@ steps: from_secret: PLEX_IP PLEX_TOKEN: from_secret: PLEX_TOKEN - # when: - # event: - # - push - # branch: - # - master + when: + event: + - push + branch: + - master # - name: deploy # image: appleboy/drone-ssh -- 2.34.1