From cad932075247a9c86db32dc561bfcf21c1cfccb5 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Sun, 22 Nov 2020 21:10:27 +0000 Subject: [PATCH] Huge changes: - Update all packages - Move to EsLint - Update to @octokit/types - Fix linting - Fix the notifications code to not depend soley on GitHub --- package.json | 57 +- src/AdminRoom.ts | 73 +- src/BotCommands.ts | 22 +- src/CommentProcessor.ts | 15 +- src/Config.ts | 9 +- src/Connections/GithubIssue.ts | 33 +- src/Connections/GithubProject.ts | 13 +- src/Connections/GithubRepo.ts | 57 +- src/Connections/GitlabIssue.ts | 21 +- src/Connections/GitlabRepo.ts | 18 +- src/Connections/IConnection.ts | 4 +- src/FormatUtil.ts | 12 +- src/Github/GithubInstance.ts | 13 +- src/Github/Types.ts | 25 + src/GithubBridge.ts | 87 +- src/GithubWebhooks.ts | 34 +- src/Gitlab/Client.ts | 6 +- src/Gitlab/Types.ts | 51 +- src/Gitlab/WebhookTypes.ts | 1 + src/IntentUtils.ts | 2 +- src/MatrixSender.ts | 12 +- src/MessageQueue/LocalMQ.ts | 7 +- src/MessageQueue/MessageQueue.ts | 10 +- src/MessageQueue/RedisQueue.ts | 25 +- src/Notifications/GitHubWatcher.ts | 140 ++ src/Notifications/NotificationWatcherTask.ts | 13 + src/Notifications/UserNotificationWatcher.ts | 77 + src/NotificationsProcessor.ts | 39 +- src/Stores/MemoryStorageProvider.ts | 15 +- src/Stores/RedisStorageProvider.ts | 15 +- src/Stores/StorageProvider.ts | 7 +- src/UserNotificationWatcher.ts | 204 -- src/UserTokenStore.ts | 16 +- tests/FormatUtilTest.ts | 4 +- tests/MessageQueueTest.ts | 3 + yarn.lock | 1803 +++++++++++------- 36 files changed, 1735 insertions(+), 1208 deletions(-) create mode 100644 src/Github/Types.ts create mode 100644 src/Notifications/GitHubWatcher.ts create mode 100644 src/Notifications/NotificationWatcherTask.ts create mode 100644 src/Notifications/UserNotificationWatcher.ts delete mode 100644 src/UserNotificationWatcher.ts diff --git a/package.json b/package.json index eafd680f..d4091e0f 100644 --- a/package.json +++ b/package.json @@ -9,46 +9,49 @@ "private": false, "scripts": { "build": "tsc --project tsconfig.json", + "prepare": "yarn build", "start:app": "node lib/App/BridgeApp.js", "start:webhooks": "node lib/App/GithubWebhookApp.js", "start:matrixsender": "node lib/App/MatrixSenderApp.js", "test": "mocha -r ts-node/register tests/**/*.ts", - "lint": "tslint -p tsconfig.json" + "lint": "eslint -c .eslintrc.js src/**/*.ts" }, "dependencies": { - "@octokit/auth-app": "^2.4.2", - "@octokit/auth-token": "^2.4.0", - "@octokit/rest": "^16.43.1", - "argv-split": "^2.0.1", - "axios": "^0.19.2", + "@octokit/auth-app": "^2.10.2", + "@octokit/auth-token": "^2.4.3", + "@octokit/rest": "^18.0.9", + "axios": "^0.21.0", "express": "^4.17.1", - "ioredis": "^4.14.0", - "markdown-it": "^9.0.1", - "matrix-bot-sdk": "^0.5.4", + "ioredis": "^4.19.2", + "markdown-it": "^12.0.2", + "matrix-bot-sdk": "^0.5.8", "micromatch": "^4.0.2", - "mime": "^2.4.4", - "mocha": "^6.2.0", + "mime": "^2.4.6", + "mocha": "^8.2.1", "node-emoji": "^1.10.0", "reflect-metadata": "^0.1.13", - "uuid": "^3.3.2", - "winston": "^3.2.1", - "yaml": "^1.6.0" + "string-argv": "v0.3.1", + "uuid": "^8.3.1", + "winston": "^3.3.3", + "yaml": "^1.10.0" }, "devDependencies": { - "@types/chai": "^4.1.7", - "@types/express": "^4.17.0", - "@types/ioredis": "^4.0.13", - "@types/markdown-it": "^0.0.8", - "@types/micromatch": "^3.1.0", - "@types/mime": "^2.0.1", - "@types/mocha": "^5.2.7", - "@types/node": "^12.6.9", + "@types/chai": "^4.2.14", + "@types/express": "^4.17.9", + "@types/ioredis": "^4.17.8", + "@types/markdown-it": "^10.0.3", + "@types/micromatch": "^4.0.1", + "@types/mime": "^2.0.3", + "@types/mocha": "^8.0.4", + "@types/node": "^12", "@types/node-emoji": "^1.8.1", - "@types/uuid": "^3.4.5", - "@types/yaml": "^1.0.2", + "@types/uuid": "^8.3.0", + "@typescript-eslint/eslint-plugin": "^4.8.1", + "@typescript-eslint/parser": "^4.8.1", "chai": "^4.2.0", - "ts-node": "^8.3.0", - "tslint": "^5.18.0", - "typescript": "^3.9.7" + "eslint": "^7.14.0", + "eslint-plugin-mocha": "^8.0.0", + "ts-node": "^9.0.0", + "typescript": "^4.1.2" } } diff --git a/src/AdminRoom.ts b/src/AdminRoom.ts index bbd779fb..722caa12 100644 --- a/src/AdminRoom.ts +++ b/src/AdminRoom.ts @@ -1,9 +1,8 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ import { Intent } from "matrix-bot-sdk"; -import { Octokit } from "@octokit/rest"; -import { createTokenAuth } from "@octokit/auth-token"; import { UserTokenStore } from "./UserTokenStore"; import { BridgeConfig } from "./Config"; -import uuid from "uuid/v4"; +import {v4 as uuid} from "uuid"; import qs from "querystring"; import { EventEmitter } from "events"; import LogWrapper from "./LogWrapper"; @@ -13,14 +12,20 @@ import { FormatUtil } from "./FormatUtil"; import { botCommand, compileBotCommands, handleCommand, BotCommands } from "./BotCommands"; import { GitLabClient } from "./Gitlab/Client"; import { GetUserResponse } from "./Gitlab/Types"; +import { GithubInstance } from "./Github/GithubInstance"; +import { MatrixMessageContent } from "./MatrixEvent"; +import { ProjectsListForUserResponseData, ProjectsListForRepoResponseData } from "@octokit/types"; + const md = new markdown(); const log = new LogWrapper('AdminRoom'); export const BRIDGE_ROOM_TYPE = "uk.half-shot.matrix-github.room"; export const BRIDGE_NOTIF_TYPE = "uk.half-shot.matrix-github.notif_state"; +export const BRIDGE_GITLAB_NOTIF_TYPE = "uk.half-shot.matrix-github.gitlab.notif_state"; export interface AdminAccountData { + // eslint-disable-next-line camelcase admin_user: string; notifications?: { enabled: boolean; @@ -28,7 +33,7 @@ export interface AdminAccountData { }; } export class AdminRoom extends EventEmitter { - static helpMessage: any; + static helpMessage: MatrixMessageContent; static botCommands: BotCommands; private pendingOAuthState: string|null = null; @@ -94,11 +99,7 @@ export class AdminRoom extends EventEmitter { } let me; try { - const octokit = new Octokit({ - authStrategy: createTokenAuth, - auth: accessToken, - userAgent: "matrix-github v0.0.1", - }); + const octokit = GithubInstance.createUserOctokit(accessToken); me = await octokit.users.getAuthenticated(); } catch (ex) { await this.sendNotice("Could not authenticate with GitHub. Is your token correct?"); @@ -139,9 +140,9 @@ export class AdminRoom extends EventEmitter { await this.sendNotice(`You should follow ${url} to link your account to the bridge`); } - @botCommand("notifications toggle", "Toggle enabling/disabling GitHub notifications in this room") + @botCommand("github notifications toggle", "Toggle enabling/disabling GitHub notifications in this room") // @ts-ignore - property is used - private async setNotificationsStateToggle() { + private async setGitHubNotificationsStateToggle() { const data: AdminAccountData = await this.botIntent.underlyingClient.getRoomAccountData( BRIDGE_ROOM_TYPE, this.roomId, ); @@ -155,9 +156,9 @@ export class AdminRoom extends EventEmitter { await this.sendNotice(`${data.notifications.enabled ? "En" : "Dis"}abled GitHub notifcations`); } - @botCommand("notifications filter participating", "Toggle enabling/disabling GitHub notifications in this room") + @botCommand("github notifications filter participating", "Toggle enabling/disabling GitHub notifications in this room") // @ts-ignore - property is used - private async setNotificationsStateParticipating() { + private async setGitHubNotificationsStateParticipating() { const data: AdminAccountData = await this.botIntent.underlyingClient.getRoomAccountData( BRIDGE_ROOM_TYPE, this.roomId, ); @@ -187,7 +188,7 @@ export class AdminRoom extends EventEmitter { username = me.data.name; } - let res: Octokit.ProjectsListForUserResponse|Octokit.ProjectsListForRepoResponse; + let res: ProjectsListForUserResponseData|ProjectsListForRepoResponseData; try { if (repo) { res = (await octokit.projects.listForRepo({ @@ -203,7 +204,7 @@ export class AdminRoom extends EventEmitter { return this.sendNotice(`Failed to fetch projects due to an error. See logs for details`); } - const content = `Projects for ${username}:\n` + res.map(r => ` - ${FormatUtil.projectListing(r)}\n`).join("\n"); + const content = `Projects for ${username}:\n` + res.map(r => ` - ${FormatUtil.projectListing([r])}\n`).join("\n"); return this.botIntent.sendEvent(this.roomId,{ msgtype: "m.notice", body: content, @@ -223,7 +224,7 @@ export class AdminRoom extends EventEmitter { return this.sendNotice("You can not list projects without an account."); } - let res: Octokit.ProjectsListForUserResponse|Octokit.ProjectsListForRepoResponse; + let res: ProjectsListForUserResponseData|ProjectsListForRepoResponseData; try { if (repo) { res = (await octokit.projects.listForRepo({ @@ -239,7 +240,7 @@ export class AdminRoom extends EventEmitter { return this.sendNotice(`Failed to fetch projects due to an error. See logs for details`); } - const content = `Projects for ${org}:\n` + res.map(r => ` - ${FormatUtil.projectListing(r)}\n`).join("\n"); + const content = `Projects for ${org}:\n` + res.map(r => ` - ${FormatUtil.projectListing([r])}\n`).join("\n"); return this.botIntent.sendEvent(this.roomId,{ msgtype: "m.notice", body: content, @@ -319,7 +320,40 @@ export class AdminRoom extends EventEmitter { await this.tokenStore.storeUserToken("gitlab", this.userId, accessToken, instance.url); } - public async handleCommand(event_id: string, command: string) { + @botCommand("gitlab hastoken", "Check if you have a token stored for GitLab", ["instanceName"]) + // @ts-ignore - property is used + private async gitlabHasPersonalToken(instanceName: string) { + if (!this.config.gitlab) { + return this.sendNotice("The bridge is not configured with GitLab support"); + } + const instance = this.config.gitlab.instances[instanceName]; + if (!instance) { + return this.sendNotice("The bridge is not configured for this GitLab instance"); + } + const result = await this.tokenStore.getUserToken("gitlab", this.userId, instance.url); + if (result === null) { + await this.sendNotice("You do not currently have a token stored"); + return; + } + await this.sendNotice("A token is stored for your GitLab account."); + } + + @botCommand("gitlab notifications toggle", "Toggle enabling/disabling GitHub notifications in this room") + // @ts-ignore - property is used + private async setGitLabNotificationsStateToggle() { + const data: AdminAccountData = await this.botIntent.underlyingClient.getRoomAccountData( + BRIDGE_GITLAB_NOTIF_TYPE, this.roomId, + ); + const oldState = data.notifications || { + enabled: false, + }; + data.notifications = { enabled: !oldState?.enabled }; + await this.botIntent.underlyingClient.setRoomAccountData(BRIDGE_GITLAB_NOTIF_TYPE, this.roomId, data); + this.emit("settings.changed", this, data); + await this.sendNotice(`${data.notifications.enabled ? "En" : "Dis"}abled GitLab notifcations`); + } + + public async handleCommand(eventId: string, command: string) { const { error, handled } = await handleCommand(this.userId, command, AdminRoom.botCommands, this); if (!handled) { return this.sendNotice("Command not understood"); @@ -338,6 +372,7 @@ export class AdminRoom extends EventEmitter { } } -const res = compileBotCommands(AdminRoom.prototype); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const res = compileBotCommands(AdminRoom.prototype as any); AdminRoom.helpMessage = res.helpMessage; AdminRoom.botCommands = res.botCommands; \ No newline at end of file diff --git a/src/BotCommands.ts b/src/BotCommands.ts index d5b4b41f..17e083bc 100644 --- a/src/BotCommands.ts +++ b/src/BotCommands.ts @@ -1,11 +1,11 @@ import markdown from "markdown-it"; -// @ts-ignore -import argvSplit from "argv-split"; +import stringArgv from "string-argv"; +import { MatrixMessageContent } from "./MatrixEvent"; const md = new markdown(); export const botCommandSymbol = Symbol("botCommandMetadata"); -export function botCommand(prefix: string, help: string, requiredArgs: string[] = [], optionalArgs: string[] = [], includeUserId: boolean = false) { +export function botCommand(prefix: string, help: string, requiredArgs: string[] = [], optionalArgs: string[] = [], includeUserId = false) { return Reflect.metadata(botCommandSymbol, { prefix, help, @@ -15,21 +15,23 @@ export function botCommand(prefix: string, help: string, requiredArgs: string[] }); } +type BotCommandFunction = (...args: string[]) => Promise<{status: boolean}>; + export type BotCommands = {[prefix: string]: { - fn: (...args: string[]) => Promise<{status: boolean}>, + fn: BotCommandFunction, requiredArgs: string[], optionalArgs: string[], includeUserId: boolean, }}; -export function compileBotCommands(prototype: any): {helpMessage: any, botCommands: BotCommands} { +export function compileBotCommands(prototype: Record): {helpMessage: MatrixMessageContent, botCommands: BotCommands} { let content = "Commands:\n"; - let botCommands: BotCommands = {}; + const botCommands: BotCommands = {}; Object.getOwnPropertyNames(prototype).forEach(propetyKey => { const b = Reflect.getMetadata(botCommandSymbol, prototype, propetyKey); if (b) { - const requiredArgs = b.requiredArgs.join((arg: string) => `__${arg}__`); - const optionalArgs = b.optionalArgs.join((arg: string) => `\[${arg}\]`); + const requiredArgs = b.requiredArgs.join(" "); + const optionalArgs = b.optionalArgs.map((arg: string) => `[${arg}]`).join(" "); content += ` - \`${b.prefix}\` ${requiredArgs} ${optionalArgs} - ${b.help}\n`; // We know that this is safe. botCommands[b.prefix as string] = { @@ -51,8 +53,8 @@ export function compileBotCommands(prototype: any): {helpMessage: any, botComman } } -export async function handleCommand(userId: string, command: string, botCommands: BotCommands, obj: any): Promise<{error?: string, handled?: boolean}> { - const parts = argvSplit(command); +export async function handleCommand(userId: string, command: string, botCommands: BotCommands, obj: unknown): Promise<{error?: string, handled?: boolean}> { + const parts = stringArgv(command); for (let i = parts.length; i > 0; i--) { const prefix = parts.slice(0, i).join(" ").toLowerCase(); // We have a match! diff --git a/src/CommentProcessor.ts b/src/CommentProcessor.ts index 338c3c5b..2ab3ae63 100644 --- a/src/CommentProcessor.ts +++ b/src/CommentProcessor.ts @@ -1,4 +1,3 @@ -import { Octokit } from "@octokit/rest"; import { Appservice } from "matrix-bot-sdk"; import markdown from "markdown-it"; import mime from "mime"; @@ -7,6 +6,7 @@ import { MatrixMessageContent, MatrixEvent } from "./MatrixEvent"; import LogWrapper from "./LogWrapper"; import axios from "axios"; import { FormatUtil } from "./FormatUtil"; +import { IssuesGetCommentResponseData, ReposGetResponseData, IssuesGetResponseData } from "@octokit/types"; const REGEX_MENTION = /(^|\s)(@[a-z\d](?:[a-z\d]|-(?=[a-z\d])){0,38})(\s|$)/ig; const REGEX_MATRIX_MENTION = /(.*)<\/a>/gmi; @@ -14,11 +14,8 @@ const REGEX_IMAGES = /!\[.*]\((.*\.(\w+))\)/gm; const md = new markdown(); const log = new LogWrapper("CommentProcessor"); -interface IMatrixCommentEvent { - msgtype: string; - body: string; - formatted_body: string; - format: string; +interface IMatrixCommentEvent extends MatrixMessageContent { + // eslint-disable-next-line camelcase external_url: string; "uk.half-shot.matrix-github.comment": { id: number; @@ -59,9 +56,9 @@ export class CommentProcessor { return body; } - public async getEventBodyForComment(comment: Octokit.IssuesGetCommentResponse, - repo?: Octokit.ReposGetResponse, - issue?: Octokit.IssuesGetResponse): Promise { + public async getEventBodyForComment(comment: IssuesGetCommentResponseData, + repo?: ReposGetResponseData, + issue?: IssuesGetResponseData): Promise { let body = comment.body; body = this.replaceMentions(body); body = await this.replaceImages(body, true); diff --git a/src/Config.ts b/src/Config.ts index b1be25be..aa03b49b 100644 --- a/src/Config.ts +++ b/src/Config.ts @@ -10,12 +10,12 @@ export interface BridgeConfigGitHub { webhook: { secret: string; }, - userTokens: { - [userId: string]: string; - } oauth: { + // eslint-disable-next-line camelcase client_id: string; + // eslint-disable-next-line camelcase client_secret: string; + // eslint-disable-next-line camelcase redirect_uri: string; }; installationId: number|string; @@ -23,9 +23,6 @@ export interface BridgeConfigGitHub { export interface GitLabInstance { url: string; - userTokens: { - [userId: string]: string; - } // oauth: { // client_id: string; // client_secret: string; diff --git a/src/Connections/GithubIssue.ts b/src/Connections/GithubIssue.ts index 47436178..5e1516b3 100644 --- a/src/Connections/GithubIssue.ts +++ b/src/Connections/GithubIssue.ts @@ -12,12 +12,14 @@ import { FormatUtil } from "../FormatUtil"; import { IGitHubWebhookEvent } from "../GithubWebhooks"; import axios from "axios"; import { GithubInstance } from "../Github/GithubInstance"; +import { IssuesGetResponseData } from "@octokit/types"; export interface GitHubIssueConnectionState { org: string; repo: string; state: string; issues: string[]; + // eslint-disable-next-line camelcase comments_processed: number; } @@ -44,15 +46,19 @@ export class GitHubIssueConnection implements IConnection { static readonly QueryRoomRegex = /#github_(.+)_(.+)_(\d+):.*/; - static async onQueryRoom(result: RegExpExecArray, opts: IQueryRoomOpts): Promise { - const parts = result!.slice(1); + static async onQueryRoom(result: RegExpExecArray, opts: IQueryRoomOpts): Promise { + const parts = result?.slice(1); + if (!parts) { + log.error("Invalid alias pattern"); + throw Error("Could not find issue"); + } const owner = parts[0]; const repo = parts[1]; const issueNumber = parseInt(parts[2], 10); log.info(`Fetching ${owner}/${repo}/${issueNumber}`); - let issue: Octokit.IssuesGetResponse; + let issue: IssuesGetResponseData; try { issue = (await opts.octokit.issues.get({ owner, @@ -146,7 +152,10 @@ export class GitHubIssueConnection implements IConnection { } public async onCommentCreated(event: IGitHubWebhookEvent, updateState = true) { - const comment = event.comment!; + const comment = event.comment; + if (!comment || !comment.user) { + throw Error('Comment undefined'); + } if (event.repository) { // Delay to stop comments racing sends await new Promise((resolve) => setTimeout(resolve, 500)); @@ -241,7 +250,7 @@ export class GitHubIssueConnection implements IConnection { } - public async onMatrixIssueComment(event: MatrixEvent, allowEcho: boolean = false) { + public async onMatrixIssueComment(event: MatrixEvent, allowEcho = false) { const clientKit = await this.tokenStore.getOctokitForUser(event.sender); if (clientKit === null) { await this.as.botClient.sendEvent(this.roomId, "m.reaction", { @@ -273,25 +282,17 @@ export class GitHubIssueConnection implements IConnection { return; // No changes made. } - if (event.changes.title) { + if (event.issue && event.changes.title) { await this.as.botIntent.underlyingClient.sendStateEvent(this.roomId, "m.room.name", "", { - name: FormatUtil.formatIssueRoomName(event.issue!), + name: FormatUtil.formatIssueRoomName(event.issue), }); } } - public onIssueStateChange(event: IGitHubWebhookEvent) { + public onIssueStateChange() { return this.syncIssueState(); } - public async onEvent() { - - } - - public async onStateUpdate() { - - } - public async onMessageEvent(ev: MatrixEvent) { if (ev.content.body === '!sync') { // Sync data. diff --git a/src/Connections/GithubProject.ts b/src/Connections/GithubProject.ts index 214064c5..368fe1d2 100644 --- a/src/Connections/GithubProject.ts +++ b/src/Connections/GithubProject.ts @@ -1,9 +1,10 @@ import { IConnection } from "./IConnection"; import { Appservice } from "matrix-bot-sdk"; import LogWrapper from "../LogWrapper"; -import { Octokit } from "@octokit/rest"; +import { ProjectsGetResponseData } from "@octokit/types"; export interface GitHubProjectConnectionState { + // eslint-disable-next-line camelcase project_id: number; state: "open"|"closed"; } @@ -20,7 +21,7 @@ export class GitHubProjectConnection implements IConnection { GitHubProjectConnection.CanonicalEventType, // Legacy event, with an awful name. ]; - static async onOpenProject(project: Octokit.ProjectsGetResponse, as: Appservice, inviteUser: string): Promise { + static async onOpenProject(project: ProjectsGetResponseData, as: Appservice, inviteUser: string): Promise { log.info(`Fetching ${project.name} ${project.id}`); // URL hack so we don't need to fetch the repo itself. @@ -57,14 +58,6 @@ export class GitHubProjectConnection implements IConnection { return GitHubProjectConnection.EventTypes.includes(eventType) && this.stateKey === stateKey; } - public async onEvent() { - - } - - public async onStateUpdate() { - - } - public toString() { return `GitHubProjectConnection ${this.state.project_id}}`; } diff --git a/src/Connections/GithubRepo.ts b/src/Connections/GithubRepo.ts index 098c824f..024673dc 100644 --- a/src/Connections/GithubRepo.ts +++ b/src/Connections/GithubRepo.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ import { IConnection } from "./IConnection"; import { Appservice } from "matrix-bot-sdk"; import { MatrixMessageContent, MatrixEvent, MatrixReactionContent } from "../MatrixEvent"; @@ -11,6 +12,7 @@ import { FormatUtil } from "../FormatUtil"; import axios from "axios"; import { BotCommands, handleCommand, botCommand, compileBotCommands } from "../BotCommands"; import { IGitHubWebhookEvent } from "../GithubWebhooks"; +import { ReposGetResponseData } from "@octokit/types"; const log = new LogWrapper("GitHubRepoConnection"); const md = new markdown(); @@ -46,7 +48,7 @@ const ALLOWED_REACTIONS = { "👐": "open", } -function compareEmojiStrings(e0: string, e1: string, e0Index: number = 0) { +function compareEmojiStrings(e0: string, e1: string, e0Index = 0) { return e0.codePointAt(e0Index) === e1.codePointAt(0); } @@ -62,15 +64,19 @@ export class GitHubRepoConnection implements IConnection { static readonly QueryRoomRegex = /#github_(.+)_(.+):.*/; - static async onQueryRoom(result: RegExpExecArray, opts: IQueryRoomOpts): Promise { - const parts = result!.slice(1); + static async onQueryRoom(result: RegExpExecArray, opts: IQueryRoomOpts): Promise { + const parts = result?.slice(1); + if (!parts) { + log.error("Invalid alias pattern"); + throw Error("Could not find repo"); + } const owner = parts[0]; const repo = parts[1]; const issueNumber = parseInt(parts[2], 10); log.info(`Fetching ${owner}/${repo}/${issueNumber}`); - let repoRes: Octokit.ReposGetResponse; + let repoRes: ReposGetResponseData; try { repoRes = (await opts.octokit.repos.get({ owner, @@ -135,7 +141,7 @@ export class GitHubRepoConnection implements IConnection { }; } - static helpMessage: any; + static helpMessage: MatrixMessageContent; static botCommands: BotCommands; constructor(public readonly roomId: string, @@ -153,7 +159,7 @@ export class GitHubRepoConnection implements IConnection { return this.state.repo; } - public isInterestedInStateEvent(eventType: string) { + public isInterestedInStateEvent() { return false; } @@ -251,13 +257,18 @@ export class GitHubRepoConnection implements IConnection { public async onIssueCreated(event: IGitHubWebhookEvent) { log.info(`onIssueCreated ${this.roomId} ${this.org}/${this.repo} #${event.issue?.number}`); - const orgRepoName = event.issue!.repository_url.substr("https://api.github.com/repos/".length); - const content = `New issue created [${orgRepoName}#${event.issue!.number}](${event.issue!.html_url}): "${event.issue!.title}"`; - console.log(event.issue?.labels); - const labelsHtml = event.issue?.labels.map((label) => + if (!event.issue) { + throw Error('No issue content!'); + } + if (!event.repository) { + throw Error('No repository content!'); + } + const orgRepoName = event.issue.repository_url.substr("https://api.github.com/repos/".length); + const content = `New issue created [${orgRepoName}#${event.issue.number}](${event.issue.html_url}): "${event.issue.title}"`; + const labelsHtml = event.issue.labels.map((label: {color: string, name: string, description: string}) => `${label.name}` ).join(" ") || ""; - const labels = event.issue?.labels.map((label) => + const labels = event.issue?.labels.map((label: {name: string}) => label.name ).join(", ") || ""; await this.as.botIntent.sendEvent(this.roomId, { @@ -265,21 +276,27 @@ export class GitHubRepoConnection implements IConnection { body: content + (labels.length > 0 ? ` with labels ${labels}`: ""), formatted_body: md.renderInline(content) + (labelsHtml.length > 0 ? ` with labels ${labelsHtml}`: ""), format: "org.matrix.custom.html", - ...FormatUtil.getPartialBodyForIssue(event.repository!, event.issue!), + ...FormatUtil.getPartialBodyForIssue(event.repository, event.issue), }); } public async onIssueStateChange(event: IGitHubWebhookEvent) { log.info(`onIssueStateChange ${this.roomId} ${this.org}/${this.repo} #${event.issue?.number}`); - if (event.issue?.state === "closed") { - const orgRepoName = event.issue!.repository_url.substr("https://api.github.com/repos/".length); - const content = `**@${event.sender!.login}** closed issue [${orgRepoName}#${event.issue!.number}](${event.issue!.html_url}): "${event.issue!.title}"`; + if (!event.issue) { + throw Error('No issue content!'); + } + if (!event.repository) { + throw Error('No repository content!'); + } + if (event.issue.state === "closed" && event.sender) { + const orgRepoName = event.issue.repository_url.substr("https://api.github.com/repos/".length); + const content = `**@${event.sender.login}** closed issue [${orgRepoName}#${event.issue.number}](${event.issue.html_url}): "${event.issue.title}"`; await this.as.botIntent.sendEvent(this.roomId, { msgtype: "m.notice", body: content, formatted_body: md.renderInline(content), format: "org.matrix.custom.html", - ...FormatUtil.getPartialBodyForIssue(event.repository!, event.issue!), + ...FormatUtil.getPartialBodyForIssue(event.repository, event.issue), }); } } @@ -290,6 +307,7 @@ export class GitHubRepoConnection implements IConnection { return; } if (evt.type === 'm.reaction') { + // eslint-disable-next-line camelcase const {event_id, key} = (evt.content as MatrixReactionContent)["m.relates_to"]; const ev = await this.as.botClient.getEvent(this.roomId, event_id); const issueContent = ev.content["uk.half-shot.matrix-github.issue"]; @@ -297,7 +315,7 @@ export class GitHubRepoConnection implements IConnection { return; // Not our event. } - const [,reactionName] = Object.entries(GITHUB_REACTION_CONTENT).find(([emoji, content]) => compareEmojiStrings(emoji, key)) || [];; + const [,reactionName] = Object.entries(GITHUB_REACTION_CONTENT).find(([emoji]) => compareEmojiStrings(emoji, key)) || []; const [,action] = Object.entries(ALLOWED_REACTIONS).find(([emoji]) => compareEmojiStrings(emoji, key)) || []; if (reactionName) { log.info(`Sending reaction of ${reactionName} for ${this.org}${this.repo}#${issueContent.number}`) @@ -332,13 +350,12 @@ export class GitHubRepoConnection implements IConnection { } } - public async onStateUpdate() { } - public toString() { return `GitHubRepo`; } } -const res = compileBotCommands(GitHubRepoConnection.prototype); +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const res = compileBotCommands(GitHubRepoConnection.prototype as any); GitHubRepoConnection.helpMessage = res.helpMessage; GitHubRepoConnection.botCommands = res.botCommands; \ No newline at end of file diff --git a/src/Connections/GitlabIssue.ts b/src/Connections/GitlabIssue.ts index 36c9b366..92eb86c5 100644 --- a/src/Connections/GitlabIssue.ts +++ b/src/Connections/GitlabIssue.ts @@ -15,6 +15,7 @@ export interface GitLabIssueConnectionState { projects: string[]; state: string; issue: number; + // eslint-disable-next-line camelcase comments_processed: number; } @@ -44,7 +45,7 @@ export class GitLabIssueConnection implements IConnection { static readonly QueryRoomRegex = /#gitlab_(.+)_(.+)_(\d+):.*/; public static createRoomForIssue() { - + // Fill me in } public get projectPath() { @@ -169,7 +170,7 @@ export class GitLabIssueConnection implements IConnection { // } - public async onMatrixIssueComment(event: MatrixEvent, allowEcho: boolean = false) { + public async onMatrixIssueComment(event: MatrixEvent, allowEcho = false) { console.log(this.messageClient, this.commentProcessor); const clientKit = await this.tokenStore.getGitLabForUser(event.sender, this.instanceUrl); @@ -203,25 +204,13 @@ export class GitLabIssueConnection implements IConnection { return; // No changes made. } - if (event.changes.title) { + if (event.issue && event.changes.title) { await this.as.botIntent.underlyingClient.sendStateEvent(this.roomId, "m.room.name", "", { - name: FormatUtil.formatIssueRoomName(event.issue!), + name: FormatUtil.formatIssueRoomName(event.issue), }); } } - // public onIssueStateChange(event: IGitHubWebhookEvent) { - // return this.syncIssueState(); - // } - - public async onEvent() { - - } - - public async onStateUpdate() { - - } - public async onMessageEvent(ev: MatrixEvent) { if (ev.content.body === '!sync') { // Sync data. diff --git a/src/Connections/GitlabRepo.ts b/src/Connections/GitlabRepo.ts index 96b55cb8..670b18aa 100644 --- a/src/Connections/GitlabRepo.ts +++ b/src/Connections/GitlabRepo.ts @@ -1,3 +1,5 @@ +// We need to instantiate some functions which are not directly called, which confuses typescript. +/* eslint-disable @typescript-eslint/ban-ts-comment */ import { IConnection } from "./IConnection"; import { UserTokenStore } from "../UserTokenStore"; import { Appservice } from "matrix-bot-sdk"; @@ -27,7 +29,7 @@ export class GitLabRepoConnection implements IConnection { GitLabRepoConnection.CanonicalEventType, // Legacy event, with an awful name. ]; - static helpMessage: any; + static helpMessage: MatrixMessageContent; static botCommands: BotCommands; constructor(public readonly roomId: string, @@ -46,7 +48,7 @@ export class GitLabRepoConnection implements IConnection { return this.state.repo; } - public isInterestedInStateEvent(eventType: string) { + public isInterestedInStateEvent() { return false; } @@ -99,7 +101,7 @@ export class GitLabRepoConnection implements IConnection { @botCommand("gl close", "Close an issue", ["number"], ["comment"], true) // @ts-ignore - private async onClose(userId: string, number: string, comment?: string) { + private async onClose(userId: string, number: string) { const client = await this.tokenStore.getGitLabForUser(userId, this.instance.url); if (!client) { await this.as.botIntent.sendText(this.roomId, "You must login to create an issue", "m.notice"); @@ -121,17 +123,13 @@ export class GitLabRepoConnection implements IConnection { // } - public async onEvent(evt: MatrixEvent) { - - } - - public async onStateUpdate() { } - public toString() { return `GitHubRepo`; } } -const res = compileBotCommands(GitLabRepoConnection.prototype); +// Typescript doesn't understand Prototypes very well yet. +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const res = compileBotCommands(GitLabRepoConnection.prototype as any); GitLabRepoConnection.helpMessage = res.helpMessage; GitLabRepoConnection.botCommands = res.botCommands; \ No newline at end of file diff --git a/src/Connections/IConnection.ts b/src/Connections/IConnection.ts index 556f2a0a..c1c66bf3 100644 --- a/src/Connections/IConnection.ts +++ b/src/Connections/IConnection.ts @@ -6,11 +6,11 @@ export interface IConnection { /** * When a room gets an update to it's state. */ - onStateUpdate: (ev: any) => Promise; + onStateUpdate?: (ev: MatrixEvent) => Promise; /** * When a room gets any event */ - onEvent: (ev: MatrixEvent) => Promise; + onEvent?: (ev: MatrixEvent) => Promise; /** * When a room gets a message event diff --git a/src/FormatUtil.ts b/src/FormatUtil.ts index 1e1b8d38..28f53fcb 100644 --- a/src/FormatUtil.ts +++ b/src/FormatUtil.ts @@ -1,4 +1,4 @@ -import { Octokit } from "@octokit/rest"; +import { IssuesGetCommentResponseData, IssuesGetResponseData, ProjectsListForOrgResponseData, ProjectsListForUserResponseData, ProjectsListForRepoResponseData } from "@octokit/types"; interface IMinimalRepository { id: number; @@ -36,7 +36,7 @@ export class FormatUtil { }; } - public static getPartialBodyForIssue(repo: IMinimalRepository, issue: Octokit.IssuesGetResponse) { + public static getPartialBodyForIssue(repo: IMinimalRepository, issue: IssuesGetResponseData) { return { ...FormatUtil.getPartialBodyForRepo(repo), "external_url": issue.html_url, @@ -50,9 +50,9 @@ export class FormatUtil { }; } - public static getPartialBodyForComment(comment: Octokit.IssuesGetCommentResponse, + public static getPartialBodyForComment(comment: IssuesGetCommentResponseData, repo?: IMinimalRepository, - issue?: Octokit.IssuesGetResponse) { + issue?: IssuesGetResponseData) { return { ...(issue && repo ? FormatUtil.getPartialBodyForIssue(repo, issue) : undefined), "external_url": comment.html_url, @@ -62,7 +62,7 @@ export class FormatUtil { }; } - public static projectListing(projectItem: Octokit.ProjectsListForOrgResponseItem|Octokit.ProjectsListForUserResponseItem|Octokit.ProjectsListForRepoResponseItem) { - return `${projectItem.name} (#${projectItem.number}) - Project ID: ${projectItem.id}` + public static projectListing(projectItem: ProjectsListForOrgResponseData|ProjectsListForUserResponseData|ProjectsListForRepoResponseData) { + return `${projectItem[0].name} (#${projectItem[0].number}) - Project ID: ${projectItem[0].id}` } } diff --git a/src/Github/GithubInstance.ts b/src/Github/GithubInstance.ts index cd596ecc..2ddcfc9d 100644 --- a/src/Github/GithubInstance.ts +++ b/src/Github/GithubInstance.ts @@ -1,4 +1,5 @@ import { createAppAuth } from "@octokit/auth-app"; +import { createTokenAuth } from "@octokit/auth-token"; import { Octokit } from "@octokit/rest"; import { promises as fs } from "fs"; import { BridgeConfigGitHub } from "../Config"; @@ -6,6 +7,8 @@ import LogWrapper from "../LogWrapper"; const log = new LogWrapper("GithubInstance"); +const USER_AGENT = "matrix-github v0.0.1"; + export class GithubInstance { private internalOctokit!: Octokit; @@ -17,6 +20,14 @@ export class GithubInstance { } + public static createUserOctokit(token: string) { + return new Octokit({ + authStrategy: createTokenAuth, + auth: token, + userAgent: USER_AGENT, + }); + } + public async start() { // TODO: Make this generic. const auth = { @@ -28,7 +39,7 @@ export class GithubInstance { this.internalOctokit = new Octokit({ authStrategy: createAppAuth, auth, - userAgent: "matrix-github v0.0.1", + userAgent: USER_AGENT, }); try { diff --git a/src/Github/Types.ts b/src/Github/Types.ts new file mode 100644 index 00000000..0331a358 --- /dev/null +++ b/src/Github/Types.ts @@ -0,0 +1,25 @@ +import { IssuesGetResponseData, IssuesGetCommentResponseData, PullsListReviewsResponseData, ReposGetResponseData, PullsListRequestedReviewersResponseData } from "@octokit/types"; + +/* eslint-disable camelcase */ +export interface GitHubUserNotification { + id: string; + reason: "assign"|"author"|"comment"|"invitation"|"manual"|"mention"|"review_requested"| + "security_alert"|"state_change"|"subscribed"|"team_mention"; + unread: boolean; + updated_at: number; + last_read_at: number; + url: string; + subject: { + title: string; + url: string; + latest_comment_url: string|null; + type: "PullRequest"|"Issue"|"RepositoryVulnerabilityAlert"; + // Probably. + url_data?: IssuesGetResponseData; + latest_comment_url_data?: IssuesGetCommentResponseData; + requested_reviewers?: PullsListRequestedReviewersResponseData; + reviews?: PullsListReviewsResponseData; + }; + // Not quite the right type but good nuff. + repository: ReposGetResponseData; +} diff --git a/src/GithubBridge.ts b/src/GithubBridge.ts index ffb7f105..86a0cdd2 100644 --- a/src/GithubBridge.ts +++ b/src/GithubBridge.ts @@ -1,5 +1,5 @@ import { Appservice, IAppserviceRegistration, RichRepliesPreprocessor, IRichReplyMetadata } from "matrix-bot-sdk"; -import { Octokit } from "@octokit/rest"; +import { ProjectsGetResponseData } from "@octokit/types"; import { BridgeConfig, GitLabInstance } from "./Config"; import { IGitHubWebhookEvent, IOAuthRequest, IOAuthTokens, NotificationsEnableEvent, NotificationsDisableEvent } from "./GithubWebhooks"; @@ -10,7 +10,7 @@ import { UserTokenStore } from "./UserTokenStore"; import { MatrixEvent, MatrixMemberContent, MatrixMessageContent } from "./MatrixEvent"; import LogWrapper from "./LogWrapper"; import { MessageSenderClient } from "./MatrixSender"; -import { UserNotificationsEvent } from "./UserNotificationWatcher"; +import { UserNotificationsEvent } from "./Notifications/UserNotificationWatcher"; import { RedisStorageProvider } from "./Stores/RedisStorageProvider"; import { MemoryStorageProvider } from "./Stores/MemoryStorageProvider"; import { NotificationProcessor } from "./NotificationsProcessor"; @@ -113,7 +113,7 @@ export class GithubBridge { public stop() { this.as.stop(); - this.queue.stop(); + if(this.queue.stop) this.queue.stop(); } public async start() { @@ -189,60 +189,75 @@ export class GithubBridge { this.queue.subscribe("merge_request.*"); this.queue.subscribe("gitlab.*"); - this.queue.on("comment.created", async (msg) => { - const connections = this.getConnectionsForGithubIssue(msg.data.repository!.owner.login, msg.data.repository!.name, msg.data.issue!.number); + const validateRepoIssue = (data: IGitHubWebhookEvent) => { + if (!data.repository || !data.issue) { + throw Error("Malformed webhook event, missing repository or issue"); + } + return { + repository: data.repository, + issue: data.issue, + }; + } + + this.queue.on("comment.created", async ({ data }) => { + const { repository, issue } = validateRepoIssue(data); + const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number); connections.map(async (c) => { try { if (c.onCommentCreated) - await c.onCommentCreated(msg.data); + await c.onCommentCreated(data); } catch (ex) { log.warn(`Connection ${c.toString()} failed to handle comment.created:`, ex); } }) }); - this.queue.on("issue.opened", async (msg) => { - const connections = this.getConnectionsForGithubIssue(msg.data.repository!.owner.login, msg.data.repository!.name, msg.data.issue!.number); + this.queue.on("issue.opened", async ({ data }) => { + const { repository, issue } = validateRepoIssue(data); + const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number); connections.map(async (c) => { try { if (c.onIssueCreated) - await c.onIssueCreated(msg.data); + await c.onIssueCreated(data); } catch (ex) { log.warn(`Connection ${c.toString()} failed to handle comment.created:`, ex); } }) }); - this.queue.on("issue.edited", async (msg) => { - const connections = this.getConnectionsForGithubIssue(msg.data.repository!.owner.login, msg.data.repository!.name, msg.data.issue!.number); + this.queue.on("issue.edited", async ({ data }) => { + const { repository, issue } = validateRepoIssue(data); + const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number); connections.map(async (c) => { try { if (c.onIssueEdited) - await c.onIssueEdited(msg.data); + await c.onIssueEdited(data); } catch (ex) { log.warn(`Connection ${c.toString()} failed to handle comment.created:`, ex); } }) }); - this.queue.on("issue.closed", async (msg) => { - const connections = this.getConnectionsForGithubIssue(msg.data.repository!.owner.login, msg.data.repository!.name, msg.data.issue!.number); + this.queue.on("issue.closed", async ({ data }) => { + const { repository, issue } = validateRepoIssue(data); + const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number); connections.map(async (c) => { try { if (c.onIssueStateChange) - await c.onIssueStateChange(msg.data); + await c.onIssueStateChange(data); } catch (ex) { log.warn(`Connection ${c.toString()} failed to handle comment.created:`, ex); } }) }); - this.queue.on("issue.reopened", async (msg) => { - const connections = this.getConnectionsForGithubIssue(msg.data.repository!.owner.login, msg.data.repository!.name, msg.data.issue!.number); + this.queue.on("issue.reopened", async ({ data }) => { + const { repository, issue } = validateRepoIssue(data); + const connections = this.getConnectionsForGithubIssue(repository.owner.login, repository.name, issue.number); connections.map(async (c) => { try { if (c.onIssueStateChange) - await c.onIssueStateChange(msg.data); + await c.onIssueStateChange(data); } catch (ex) { log.warn(`Connection ${c.toString()} failed to handle comment.created:`, ex); } @@ -305,13 +320,12 @@ export class GithubBridge { }); // Fetch all room state - let joinedRooms: string[]; - while(true) { + let joinedRooms: string[]|undefined; + while(joinedRooms === undefined) { try { log.info("Connecting to homeserver and fetching joined rooms.."); joinedRooms = await this.as.botIntent.underlyingClient.getJoinedRooms(); log.info(`Found ${joinedRooms.length} rooms`); - break; } catch (ex) { // This is our first interaction with the homeserver, so wait if it's not ready yet. log.warn("Failed to connect to homeserver:", ex, "retrying in 5s"); @@ -428,14 +442,17 @@ export class GithubBridge { } const command = event.content.body; - if (command) { - await this.adminRooms.get(roomId)!.handleCommand(event.event_id, command); + const adminRoom = this.adminRooms.get(roomId); + if (command && adminRoom) { + await adminRoom.handleCommand(event.event_id, command); } } - for (const connection of this.connections.filter((c) => c.roomId === roomId && c.onMessageEvent)) { + for (const connection of this.connections.filter((c) => c.roomId === roomId)) { try { - await connection.onMessageEvent!(event); + if (connection.onMessageEvent) { + await connection.onMessageEvent(event); + } } catch (ex) { log.warn(`Connection ${connection.toString()} failed to handle message:`, ex); } @@ -461,7 +478,7 @@ export class GithubBridge { if (event.state_key) { // A state update, hurrah! const existingConnection = this.connections.find((c) => c.roomId === roomId && c.isInterestedInStateEvent(event.type, event.state_key || "")); - if (existingConnection) { + if (existingConnection?.onStateUpdate) { existingConnection.onStateUpdate(event); } else { // Is anyone interested in this state? @@ -475,7 +492,7 @@ export class GithubBridge { } // Alas, it's just an event. - return this.connections.filter((c) => c.roomId === roomId).map((c) => c.onEvent(event)) + return this.connections.filter((c) => c.roomId === roomId).map((c) => c.onEvent ? c.onEvent(event) : undefined); } private async onQueryRoom(roomAlias: string) { @@ -535,11 +552,13 @@ export class GithubBridge { eventName: "notifications.user.enable", sender: "GithubBridge", data: { - user_id: adminRoom.userId, - room_id: adminRoom.roomId, + userId: adminRoom.userId, + roomId: adminRoom.roomId, token, since: await adminRoom.getNotifSince(), - filter_participating: adminRoom.notificationsParticipating, + filterParticipating: adminRoom.notificationsParticipating, + type: "github", + instanceUrl: undefined, }, }); } else { @@ -550,7 +569,9 @@ export class GithubBridge { eventName: "notifications.user.disable", sender: "GithubBridge", data: { - user_id: adminRoom.userId, + userId: adminRoom.userId, + type: "github", + instanceUrl: undefined, }, }); } @@ -561,12 +582,12 @@ export class GithubBridge { roomId, accountData, this.as.botIntent, this.tokenStore, this.config, ); adminRoom.on("settings.changed", this.onAdminRoomSettingsChanged.bind(this)); - adminRoom.on("open.project", async (project: Octokit.ProjectsGetResponse) => { + adminRoom.on("open.project", async (project: ProjectsGetResponseData) => { const connection = await GitHubProjectConnection.onOpenProject(project, this.as, adminRoom.userId); this.connections.push(connection); }); adminRoom.on("open.gitlab-issue", async (issueInfo: GetIssueOpts, res: GetIssueResponse, instance: GitLabInstance) => { - let [ connection ] = this.getConnectionsForGitLabIssue(instance, issueInfo.projects, issueInfo.issue); + const [ connection ] = this.getConnectionsForGitLabIssue(instance, issueInfo.projects, issueInfo.issue); if (connection) { return this.as.botClient.inviteUser(adminRoom.userId, connection.roomId); } diff --git a/src/GithubWebhooks.ts b/src/GithubWebhooks.ts index 8f3607d9..6dea3b1b 100644 --- a/src/GithubWebhooks.ts +++ b/src/GithubWebhooks.ts @@ -1,24 +1,26 @@ import { BridgeConfig } from "./Config"; import { Application, default as express, Request, Response } from "express"; import { createHmac } from "crypto"; -import { Octokit } from "@octokit/rest"; +import { IssuesGetResponseData, IssuesGetCommentResponseData, ReposGetResponseData } from "@octokit/types"; import { EventEmitter } from "events"; import { MessageQueue, createMessageQueue, MessageQueueMessage } from "./MessageQueue/MessageQueue"; import LogWrapper from "./LogWrapper"; import qs from "querystring"; import { Server } from "http"; import axios from "axios"; -import { UserNotificationWatcher } from "./UserNotificationWatcher"; +import { UserNotificationWatcher } from "./Notifications/UserNotificationWatcher"; import { IGitLabWebhookEvent } from "./Gitlab/WebhookTypes"; const log = new LogWrapper("GithubWebhooks"); export interface IGitHubWebhookEvent { action: string; - issue?: Octokit.IssuesGetResponse; - comment?: Octokit.IssuesGetCommentResponse; - repository?: Octokit.ReposGetResponse; - sender?: Octokit.IssuesGetResponseUser; + issue?: IssuesGetResponseData; + comment?: IssuesGetCommentResponseData; + repository?: ReposGetResponseData; + sender?: { + login: string; + } changes?: { title?: { from: string; @@ -38,15 +40,19 @@ export interface IOAuthTokens { } export interface NotificationsEnableEvent { - user_id: string; - room_id: string; + userId: string; + roomId: string; since: number; token: string; - filter_participating: boolean; + filterParticipating: boolean; + type: "github"|"gitlab"; + instanceUrl?: string; } export interface NotificationsDisableEvent { - user_id: string; + userId: string; + type: "github"|"gitlab"; + instanceUrl?: string; } export class GithubWebhooks extends EventEmitter { @@ -69,7 +75,7 @@ export class GithubWebhooks extends EventEmitter { this.userNotificationWatcher.addUser(msg.data); }); this.queue.on("notifications.user.disable", (msg: MessageQueueMessage) => { - this.userNotificationWatcher.removeUser(msg.data.user_id); + this.userNotificationWatcher.removeUser(msg.data.userId, msg.data.type, msg.data.instanceUrl); }); // This also listens for notifications for users, which is long polly. @@ -85,7 +91,9 @@ export class GithubWebhooks extends EventEmitter { } public stop() { - this.queue.stop(); + if (this.queue.stop) { + this.queue.stop(); + } if (this.server) { this.server.close(); } @@ -125,7 +133,7 @@ export class GithubWebhooks extends EventEmitter { log.debug(`New webhook: ${req.url}`); try { let eventName: string|null = null; - let body = req.body; + const body = req.body; res.sendStatus(200); if (req.headers['x-hub-signature']) { eventName = this.onGitHubPayload(body); diff --git a/src/Gitlab/Client.ts b/src/Gitlab/Client.ts index db106c33..a9070583 100644 --- a/src/Gitlab/Client.ts +++ b/src/Gitlab/Client.ts @@ -1,5 +1,5 @@ import axios from "axios"; -import { GetIssueResponse, GetUserResponse, CreateIssueOpts, CreateIssueResponse, GetIssueOpts, EditIssueOpts } from "./Types"; +import { GetIssueResponse, GetUserResponse, CreateIssueOpts, CreateIssueResponse, GetIssueOpts, EditIssueOpts, GetTodosResponse } from "./Types"; export class GitLabClient { constructor(private instanceUrl: string, private token: string) { @@ -37,6 +37,10 @@ export class GitLabClient { return (await axios.put(`${this.instanceUrl}/api/v4/projects/${opts.id}/issues/${opts.issue_iid}`, opts, this.defaultConfig)).data; } + public async getTodos() { + return (await axios.get(`${this.instanceUrl}/api/v4/todos`, this.defaultConfig)).data as GetTodosResponse[]; + } + get issues() { return { create: this.createIssue.bind(this), diff --git a/src/Gitlab/Types.ts b/src/Gitlab/Types.ts index 1cdaf8ea..861b54cb 100644 --- a/src/Gitlab/Types.ts +++ b/src/Gitlab/Types.ts @@ -1,3 +1,15 @@ +/* eslint-disable camelcase */ +export interface GitLabAuthor { + author: { + id: number; + name: string; + username: string; + state: 'active'; + avatar_url: string; + web_url: string; + }; +} + export interface GetUserResponse { id: number; username: string; @@ -78,18 +90,41 @@ export interface GetIssueResponse { title: string; description: string; state: 'opened'|'closed'; - author: { - id: number; - name: string; - username: string; - state: 'active'; - avatar_url: string; - web_url: string; - }; + author: GitLabAuthor; references: { short: string; relative: string; full: string; } web_url: string; +} + +export interface GetTodosResponse { + id: number; + author: GitLabAuthor; + action_name: string; + project: { + id: number; + name: string; + name_with_namespace: string; + path: string; + path_with_namespace: string; + }; + target: { + title: string; + description: string; + state: 'opened'|'closed'; + assignee: { + name: string; + username: string; + id: 1; + state: "active"; + avatar_url: string; + web_url: string; + } + } + target_url: string; + body: string; + created_at: string; + updated_at: string; } \ No newline at end of file diff --git a/src/Gitlab/WebhookTypes.ts b/src/Gitlab/WebhookTypes.ts index 10476945..3eeb5f86 100644 --- a/src/Gitlab/WebhookTypes.ts +++ b/src/Gitlab/WebhookTypes.ts @@ -1,3 +1,4 @@ +/* eslint-disable camelcase */ export interface IGitLabWebhookEvent { object_kind: string; diff --git a/src/IntentUtils.ts b/src/IntentUtils.ts index 3103088a..228fa565 100644 --- a/src/IntentUtils.ts +++ b/src/IntentUtils.ts @@ -4,7 +4,7 @@ import { Appservice } from "matrix-bot-sdk"; const log = new LogWrapper("IntentUtils"); -export async function getIntentForUser(user: Octokit.IssuesGetResponseUser, as: Appservice, octokit: Octokit) { +export async function getIntentForUser(user: {avatar_url?: string, login: string}, as: Appservice, octokit: Octokit) { const intent = as.getIntentForSuffix(user.login); const displayName = `${user.login}`; // Verify up-to-date profile diff --git a/src/MatrixSender.ts b/src/MatrixSender.ts index e3ef8249..2dc85ce7 100644 --- a/src/MatrixSender.ts +++ b/src/MatrixSender.ts @@ -3,7 +3,7 @@ import { MessageQueue, createMessageQueue } from "./MessageQueue/MessageQueue"; import { MatrixEventContent, MatrixMessageContent } from "./MatrixEvent"; import { Appservice, IAppserviceRegistration } from "matrix-bot-sdk"; import LogWrapper from "./LogWrapper"; - +import { v4 as uuid } from "uuid"; export interface IMatrixSendMessage { sender: string|null; type: string; @@ -35,7 +35,7 @@ export class MatrixSender { this.mq.subscribe("matrix.message"); this.mq.on("matrix.message", async (msg) => { try { - await this.sendMatrixMessage(msg.messageId!, msg.data); + await this.sendMatrixMessage(msg.messageId || uuid(), msg.data); } catch (ex) { log.error(`Failed to send message (${msg.data.roomId}, ${msg.data.sender}, ${msg.data.type})`); } @@ -43,7 +43,9 @@ export class MatrixSender { } public stop() { - this.mq.stop(); + if (this.mq.stop) { + this.mq.stop(); + } } public async sendMatrixMessage(messageId: string, msg: IMatrixSendMessage) { @@ -65,7 +67,7 @@ export class MatrixSender { export class MessageSenderClient { constructor(private queue: MessageQueue) { } - public async sendMatrixText(roomId: string, text: string, msgtype: string = "m.text", + public async sendMatrixText(roomId: string, text: string, msgtype = "m.text", sender: string|null = null): Promise { return this.sendMatrixMessage(roomId, { msgtype, @@ -74,7 +76,7 @@ export class MessageSenderClient { } public async sendMatrixMessage(roomId: string, - content: MatrixEventContent, eventType: string = "m.room.message", + content: MatrixEventContent, eventType = "m.room.message", sender: string|null = null): Promise { return (await this.queue.pushWait({ eventName: "matrix.message", diff --git a/src/MessageQueue/LocalMQ.ts b/src/MessageQueue/LocalMQ.ts index eb44792f..30b8549c 100644 --- a/src/MessageQueue/LocalMQ.ts +++ b/src/MessageQueue/LocalMQ.ts @@ -1,7 +1,7 @@ import { EventEmitter } from "events"; import { MessageQueue, MessageQueueMessage, DEFAULT_RES_TIMEOUT } from "./MessageQueue"; import micromatch from "micromatch"; -import uuid from "uuid/v4"; +import {v4 as uuid} from "uuid"; export class LocalMQ extends EventEmitter implements MessageQueue { private subs: Set; @@ -30,7 +30,6 @@ export class LocalMQ extends EventEmitter implements MessageQueue { public async pushWait(message: MessageQueueMessage, timeout: number = DEFAULT_RES_TIMEOUT): Promise { - let awaitResponse: (response: MessageQueueMessage) => void; let resolve: (value: X) => void; let timer: NodeJS.Timer; @@ -41,7 +40,7 @@ export class LocalMQ extends EventEmitter implements MessageQueue { }, timeout); }); - awaitResponse = (response: MessageQueueMessage) => { + const awaitResponse = (response: MessageQueueMessage) => { if (response.messageId === message.messageId) { clearTimeout(timer); this.removeListener(`response.${message.eventName}`, awaitResponse); @@ -53,6 +52,4 @@ export class LocalMQ extends EventEmitter implements MessageQueue { this.push(message); return p; } - - public stop() { } } diff --git a/src/MessageQueue/MessageQueue.ts b/src/MessageQueue/MessageQueue.ts index 2b7a3302..f942efc6 100644 --- a/src/MessageQueue/MessageQueue.ts +++ b/src/MessageQueue/MessageQueue.ts @@ -7,22 +7,26 @@ export const DEFAULT_RES_TIMEOUT = 30000; const staticLocalMq = new LocalMQ(); let staticRedisMq: RedisMQ|null = null; + export interface MessageQueueMessage { sender: string; eventName: string; data: T; - ts?: number; messageId?: string; for?: string; } +export interface MessageQueueMessageOut extends MessageQueueMessage { + ts: number; +} + export interface MessageQueue { subscribe: (eventGlob: string) => void; unsubscribe: (eventGlob: string) => void; push: (data: MessageQueueMessage, single?: boolean) => Promise; pushWait: (data: MessageQueueMessage, timeout?: number, single?: boolean) => Promise; - on: (eventName: string, cb: (data: MessageQueueMessage) => void) => void; - stop(): void; + on: (eventName: string, cb: (data: MessageQueueMessageOut) => void) => void; + stop?(): void; } export function createMessageQueue(config: BridgeConfig): MessageQueue { diff --git a/src/MessageQueue/RedisQueue.ts b/src/MessageQueue/RedisQueue.ts index a3ae7f0f..e1643a77 100644 --- a/src/MessageQueue/RedisQueue.ts +++ b/src/MessageQueue/RedisQueue.ts @@ -1,10 +1,10 @@ -import { MessageQueue, MessageQueueMessage, DEFAULT_RES_TIMEOUT } from "./MessageQueue"; +import { MessageQueue, MessageQueueMessage, DEFAULT_RES_TIMEOUT, MessageQueueMessageOut } from "./MessageQueue"; import { Redis, default as redis } from "ioredis"; import { BridgeConfig } from "../Config"; import { EventEmitter } from "events"; import LogWrapper from "../LogWrapper"; -import uuid from "uuid/v4"; +import {v4 as uuid} from "uuid"; const log = new LogWrapper("RedisMq"); @@ -26,13 +26,13 @@ export class RedisMQ extends EventEmitter implements MessageQueue { this.redisPub = new redis(config.queue.port, config.queue.host); this.redis = new redis(config.queue.port, config.queue.host); this.myUuid = uuid(); - this.redisSub.on("pmessage", (pattern: string, channel: string, message: string) => { - const msg = JSON.parse(message) as MessageQueueMessage; + this.redisSub.on("pmessage", (_: string, channel: string, message: string) => { + const msg = JSON.parse(message) as MessageQueueMessageOut; if (msg.for && msg.for !== this.myUuid) { log.debug(`Got message for ${msg.for}, dropping`); return; } - const delay = (process.hrtime()[1]) - msg.ts!; + const delay = (process.hrtime()[1]) - msg.ts; log.debug("Delay: ", delay / 1000000, "ms"); this.emit(channel, JSON.parse(message)); }); @@ -49,7 +49,7 @@ export class RedisMQ extends EventEmitter implements MessageQueue { this.redis.srem(`${CONSUMER_TRACK_PREFIX}${eventGlob}`, this.myUuid); } - public async push(message: MessageQueueMessage, single: boolean = false) { + public async push(message: MessageQueueMessage, single = false) { if (!message.messageId) { message.messageId = uuid(); } @@ -60,9 +60,12 @@ export class RedisMQ extends EventEmitter implements MessageQueue { } message.for = recipient; } - message.ts = process.hrtime()[1]; + const outMsg: MessageQueueMessageOut = { + ...message, + ts: process.hrtime()[1], + } try { - await this.redisPub.publish(message.eventName, JSON.stringify(message)); + await this.redisPub.publish(message.eventName, JSON.stringify(outMsg)); log.debug(`Pushed ${message.eventName}`); } catch (ex) { log.warn("Failed to push an event:", ex); @@ -71,9 +74,7 @@ export class RedisMQ extends EventEmitter implements MessageQueue { } public async pushWait(message: MessageQueueMessage, - timeout: number = DEFAULT_RES_TIMEOUT, - single: boolean = false): Promise { - let awaitResponse: (response: MessageQueueMessage) => void; + timeout: number = DEFAULT_RES_TIMEOUT): Promise { let resolve: (value: X) => void; let timer: NodeJS.Timer; @@ -84,7 +85,7 @@ export class RedisMQ extends EventEmitter implements MessageQueue { }, timeout); }); - awaitResponse = (response: MessageQueueMessage) => { + const awaitResponse = (response: MessageQueueMessage) => { if (response.messageId === message.messageId) { clearTimeout(timer); this.removeListener(`response.${message.eventName}`, awaitResponse); diff --git a/src/Notifications/GitHubWatcher.ts b/src/Notifications/GitHubWatcher.ts new file mode 100644 index 00000000..746651ca --- /dev/null +++ b/src/Notifications/GitHubWatcher.ts @@ -0,0 +1,140 @@ +import { Octokit } from "@octokit/rest"; +import { EventEmitter } from "events"; +import { GithubInstance } from "../Github/GithubInstance"; +import LogWrapper from "../LogWrapper"; +import { NotificationWatcherTask } from "./NotificationWatcherTask"; +import { RequestError } from "@octokit/request-error"; +import { GitHubUserNotification } from "../Github/Types"; +import { OctokitResponse } from "@octokit/types"; + +const log = new LogWrapper("GitHubWatcher"); + +const GH_API_THRESHOLD = 50; +const GH_API_RETRY_IN = 1000 * 60; + +export class GitHubWatcher extends EventEmitter implements NotificationWatcherTask { + private static apiFailureCount: number; + private static globalRetryIn: number; + + public static checkGitHubStatus() { + this.apiFailureCount = Math.min(this.apiFailureCount + 1, GH_API_THRESHOLD); + if (this.apiFailureCount < GH_API_THRESHOLD) { + log.warn(`API Failure count at ${this.apiFailureCount}`); + return; + } + // The API is actively failing. + if (this.globalRetryIn > 0) { + this.globalRetryIn = Date.now() + GH_API_RETRY_IN; + } + log.warn(`API Failure limit reached, holding off new requests for ${GH_API_RETRY_IN / 1000}s`); + } + + private octoKit: Octokit; + public failureCount = 0; + private interval?: NodeJS.Timeout; + private lastReadTs = 0; + public readonly type = "github"; + public readonly instanceUrl = undefined; + + constructor(token: string, public userId: string, public roomId: string, public since: number, private participating = false) { + super(); + this.octoKit = GithubInstance.createUserOctokit(token); + } + + public start(intervalMs: number) { + this.interval = setTimeout(() => { + this.getNotifications(); + }, intervalMs); + } + + public stop() { + if (this.interval) { + clearInterval(this.interval); + } + } + + private handleGitHubFailure(ex: RequestError) { + log.error("An error occured getting notifications:", ex); + if (ex.status === 401 || ex.status === 404) { + log.warn(`Got status ${ex.status} when handing user stream: ${ex.message}`); + this.failureCount++; + } else if (ex.status >= 500) { + setImmediate(() => GitHubWatcher.checkGitHubStatus()); + } + this.emit("fetch_failure", this); + } + + private async getNotifications() { + if (GitHubWatcher.globalRetryIn !== 0 && GitHubWatcher.globalRetryIn > Date.now()) { + log.info(`Not getting notifications for ${this.userId}, API is still down.`); + return; + } + log.info(`Getting notifications for ${this.userId} ${this.lastReadTs}`); + const since = this.lastReadTs !== 0 ? `&since=${new Date(this.lastReadTs).toISOString()}`: ""; + let response: OctokitResponse; + try { + response = await this.octoKit.request( + `/notifications?participating=${this.participating}${since}`, + ); + // We were succesful, clear any timeouts. + GitHubWatcher.globalRetryIn = 0; + // To avoid a bouncing issue, gradually reduce the failure count. + GitHubWatcher.apiFailureCount = Math.max(0, GitHubWatcher.apiFailureCount - 2); + } catch (ex) { + await this.handleGitHubFailure(ex); + return; + } + log.info(`Got ${response.data.length} notifications`); + this.lastReadTs = Date.now(); + const events: GitHubUserNotification[] = []; + + for (const rawEvent of response.data) { + try { + await (async () => { + if (rawEvent.subject.url) { + const res = await this.octoKit.request(rawEvent.subject.url); + rawEvent.subject.url_data = res.data; + } + if (rawEvent.subject.latest_comment_url) { + const res = await this.octoKit.request(rawEvent.subject.latest_comment_url); + rawEvent.subject.latest_comment_url_data = res.data; + } + if (rawEvent.reason === "review_requested") { + if (!rawEvent.subject.url_data?.number) { + log.warn("review_requested was missing subject.url_data.number"); + return; + } + rawEvent.subject.requested_reviewers = (await this.octoKit.pulls.listRequestedReviewers({ + pull_number: rawEvent.subject.url_data.number, + owner: rawEvent.repository.owner.login, + repo: rawEvent.repository.name, + })).data; + rawEvent.subject.reviews = (await this.octoKit.pulls.listReviews({ + pull_number: rawEvent.subject.url_data.number, + owner: rawEvent.repository.owner.login, + repo: rawEvent.repository.name, + })).data; + } + events.push(rawEvent); + })(); + } catch (ex) { + log.warn(`Failed to pre-process ${rawEvent.id}: ${ex}`); + // If it fails, we can just push the raw thing. + events.push(rawEvent); + } + } + + if (events.length > 0) { + this.emit("notification_events", { + eventName: "notifications.user.events", + data: { + roomId: this.roomId, + events, + lastReadTs: this.lastReadTs, + }, + sender: "GithubWebhooks", + }); + } + } + +} \ No newline at end of file diff --git a/src/Notifications/NotificationWatcherTask.ts b/src/Notifications/NotificationWatcherTask.ts new file mode 100644 index 00000000..942d0490 --- /dev/null +++ b/src/Notifications/NotificationWatcherTask.ts @@ -0,0 +1,13 @@ +import { EventEmitter } from "events"; + +type NotificationTypes = "github"|"gitlab"; + +export interface NotificationWatcherTask extends EventEmitter { + userId: string; + type: NotificationTypes; + instanceUrl?: string; + roomId: string; + failureCount: number; + start(intervalMs: number): void; + stop(): void; +} \ No newline at end of file diff --git a/src/Notifications/UserNotificationWatcher.ts b/src/Notifications/UserNotificationWatcher.ts new file mode 100644 index 00000000..df556c70 --- /dev/null +++ b/src/Notifications/UserNotificationWatcher.ts @@ -0,0 +1,77 @@ +import { NotificationsEnableEvent } from "../GithubWebhooks"; +import LogWrapper from "../LogWrapper"; +import { MessageQueue } from "../MessageQueue/MessageQueue"; +import { MessageSenderClient } from "../MatrixSender"; +import { NotificationWatcherTask } from "./NotificationWatcherTask"; +import { GitHubWatcher } from "./GitHubWatcher"; +import { GitHubUserNotification } from "../Github/Types"; + +export interface UserNotificationsEvent { + roomId: string; + lastReadTs: number; + events: GitHubUserNotification[]; +} + +const MIN_INTERVAL_MS = 15000; +const FAILURE_THRESHOLD = 50; + +const log = new LogWrapper("UserNotificationWatcher"); + +export class UserNotificationWatcher { + /* Key: userId:type:instanceUrl */ + private userIntervals = new Map(); + private matrixMessageSender: MessageSenderClient; + + constructor(private queue: MessageQueue) { + this.matrixMessageSender = new MessageSenderClient(queue); + } + + private static constructMapKey(userId: string, type: "github"|"gitlab", instanceUrl?: string) { + return `${userId}:${type}:${instanceUrl || ""}`; + } + + public start() { + // No-op + } + + public removeUser(userId: string, type: "github"|"gitlab", instanceUrl?: string) { + const key = UserNotificationWatcher.constructMapKey(userId, type, instanceUrl); + const task = this.userIntervals.get(key); + if (task) { + task.stop(); + this.userIntervals.delete(key); + log.info(`Removed ${key} from the notif queue`); + } + } + + private onFetchFailure(task: NotificationWatcherTask) { + if (task.failureCount > FAILURE_THRESHOLD) { + this.removeUser(task.userId, task.type, task.instanceUrl); + this.matrixMessageSender.sendMatrixText( + task.roomId, +`The bridge has been unable to process your notification stream for some time, and has disabled notifications. +Check your token is still valid, and then turn notifications back on.`, "m.notice", + ); + } + } + + public addUser(data: NotificationsEnableEvent) { + let task: NotificationWatcherTask; + const key = UserNotificationWatcher.constructMapKey(data.userId, data.type, data.instanceUrl); + if (data.type === "github") { + this.userIntervals.get(key)?.stop(); + task = new GitHubWatcher(data.token, data.userId, data.roomId, data.since, data.filterParticipating); + task.start(MIN_INTERVAL_MS); + }/* else if (data.type === "gitlab") { + + }*/ else { + throw Error('Notification type not known'); + } + task.on("fetch_failure", this.onFetchFailure.bind(this)); + task.on("new_events", (payload) => { + this.queue.push(payload); + }); + this.userIntervals.set(key, task); + log.info(`Inserted ${key} into the notif queue`); + } +} diff --git a/src/NotificationsProcessor.ts b/src/NotificationsProcessor.ts index 8e1fb3a3..38230735 100644 --- a/src/NotificationsProcessor.ts +++ b/src/NotificationsProcessor.ts @@ -1,44 +1,49 @@ import { MessageSenderClient } from "./MatrixSender"; import { IStorageProvider } from "./Stores/StorageProvider"; -import { UserNotificationsEvent, UserNotification } from "./UserNotificationWatcher"; +import { UserNotificationsEvent } from "./Notifications/UserNotificationWatcher"; import LogWrapper from "./LogWrapper"; import { AdminRoom } from "./AdminRoom"; import markdown from "markdown-it"; -import { Octokit } from "@octokit/rest"; import { FormatUtil } from "./FormatUtil"; +import { IssuesListAssigneesResponseData, PullsGetResponseData, IssuesGetResponseData, PullsListRequestedReviewersResponseData, PullsListReviewsResponseData, IssuesGetCommentResponseData } from "@octokit/types"; +import { GitHubUserNotification } from "./Github/Types"; const log = new LogWrapper("GithubBridge"); const md = new markdown(); export interface IssueDiff { state: null|string; - assignee: null|Octokit.IssuesGetResponseAssignee; + assignee: null|IssuesListAssigneesResponseData; title: null|string; merged: boolean; mergedBy: null|{ login: string; + // eslint-disable-next-line camelcase html_url: string; }; user: { login: string; + // eslint-disable-next-line camelcase html_url: string; }; } export interface CachedReviewData { - requested_reviewers: Octokit.PullsListReviewRequestsResponse; - reviews: Octokit.PullsListReviewsResponse; + // eslint-disable-next-line camelcase + requested_reviewers: PullsListRequestedReviewersResponseData; + reviews: PullsListReviewsResponseData; } -type PROrIssue = Octokit.IssuesGetResponse|Octokit.PullsGetResponse; +type PROrIssue = IssuesGetResponseData|PullsGetResponseData; export class NotificationProcessor { + // eslint-disable-next-line camelcase private static formatUser(user: {login: string, html_url: string}) { return `**[${user.login}](${user.html_url})**`; } - private static formatNotification(notif: UserNotification, diff: IssueDiff|null, newComment: boolean) { + private static formatNotification(notif: GitHubUserNotification, diff: IssueDiff|null, newComment: boolean) { const user = diff ? ` by ${this.formatUser(diff?.user)}` : ""; let plain = `${this.getEmojiForNotifType(notif)} [${notif.subject.title}](${notif.subject.url_data?.html_url})${user}`; @@ -61,11 +66,11 @@ export class NotificationProcessor { plain += `\n\n Title changed to: ${diff.title}`; } if (diff.assignee) { - plain += `\n\n Assigned to: ${diff.assignee.login}`; + plain += `\n\n Assigned to: ${diff.assignee[0].login}`; } } if (newComment) { - const comment = notif.subject.latest_comment_url_data as Octokit.IssuesGetCommentResponse; + const comment = notif.subject.latest_comment_url_data as IssuesGetCommentResponseData; plain += `\n\n ${NotificationProcessor.formatUser(comment.user)}:\n\n > ${comment.body}`; } return { @@ -74,7 +79,7 @@ export class NotificationProcessor { }; } - private static getEmojiForNotifType(notif: UserNotification): string { + private static getEmojiForNotifType(notif: GitHubUserNotification): string { let reasonFlag = ""; switch (notif.reason) { case "review_requested": @@ -167,7 +172,7 @@ export class NotificationProcessor { // } // } - private formatSecurityAlert(notif: UserNotification) { + private formatSecurityAlert(notif: GitHubUserNotification) { const body = `⚠️ ${notif.subject.title} - ` + `for **[${notif.repository.full_name}](${notif.repository.html_url})**`; return { @@ -182,26 +187,26 @@ export class NotificationProcessor { private diffIssueChanges(curr: PROrIssue, prev: PROrIssue): IssueDiff { let merged = false; let mergedBy = null; - if ((curr as Octokit.PullsGetResponse).merged !== (prev as Octokit.PullsGetResponse).merged) { + if ((curr as PullsGetResponseData).merged !== (prev as PullsGetResponseData).merged) { merged = true; - mergedBy = (curr as Octokit.PullsGetResponse).merged_by; + mergedBy = (curr as PullsGetResponseData).merged_by; } const diff: IssueDiff = { state: curr.state === prev.state ? null : curr.state, merged, mergedBy, - assignee: curr.assignee?.id === prev.assignee?.id ? null : curr.assignee, + assignee: curr.assignee?.id === prev.assignee?.id ? null : [curr.assignee], title: curr.title === prev.title ? null : curr.title, user: curr.user, }; return diff; } - private async formatIssueOrPullRequest(roomId: string, notif: UserNotification) { + private async formatIssueOrPullRequest(roomId: string, notif: GitHubUserNotification) { const issueNumber = notif.subject.url_data?.number.toString(); let diff = null; if (issueNumber) { - const prevIssue: Octokit.IssuesGetResponse|null = await this.storage.getGithubIssue( + const prevIssue: IssuesGetResponseData|null = await this.storage.getGithubIssue( notif.repository.full_name, issueNumber, roomId); if (prevIssue && notif.subject.url_data) { diff = this.diffIssueChanges(notif.subject.url_data, prevIssue); @@ -240,7 +245,7 @@ export class NotificationProcessor { return this.matrixSender.sendMatrixMessage(roomId, body); } - private async handleUserNotification(roomId: string, notif: UserNotification) { + private async handleUserNotification(roomId: string, notif: GitHubUserNotification) { log.info("New notification event:", notif); if (notif.reason === "security_alert") { return this.matrixSender.sendMatrixMessage(roomId, this.formatSecurityAlert(notif)); diff --git a/src/Stores/MemoryStorageProvider.ts b/src/Stores/MemoryStorageProvider.ts index e4650827..912e67e8 100644 --- a/src/Stores/MemoryStorageProvider.ts +++ b/src/Stores/MemoryStorageProvider.ts @@ -1,36 +1,37 @@ import { MemoryStorageProvider as MSP } from "matrix-bot-sdk"; import { IStorageProvider } from "./StorageProvider"; +import { IssuesGetResponseData } from "@octokit/types"; export class MemoryStorageProvider extends MSP implements IStorageProvider { - private issues: Map = new Map(); + private issues: Map = new Map(); private issuesLastComment: Map = new Map(); private reviewData: Map = new Map(); constructor() { super(); } - public async setGithubIssue(repo: string, issueNumber: string, data: any, scope: string = "") { + public async setGithubIssue(repo: string, issueNumber: string, data: IssuesGetResponseData, scope = "") { this.issues.set(`${scope}${repo}/${issueNumber}`, data); } - public async getGithubIssue(repo: string, issueNumber: string, scope: string = "") { + public async getGithubIssue(repo: string, issueNumber: string, scope = "") { return this.issues.get(`${scope}${repo}/${issueNumber}`) || null; } - public async setLastNotifCommentUrl(repo: string, issueNumber: string, url: string, scope: string = "") { + public async setLastNotifCommentUrl(repo: string, issueNumber: string, url: string, scope = "") { this.issuesLastComment.set(`${scope}${repo}/${issueNumber}`, url); } - public async getLastNotifCommentUrl(repo: string, issueNumber: string, scope: string = "") { + public async getLastNotifCommentUrl(repo: string, issueNumber: string, scope = "") { return this.issuesLastComment.get(`${scope}${repo}/${issueNumber}`) || null; } - public async setPRReviewData(repo: string, issueNumber: string, data: any, scope: string = "") { + public async setPRReviewData(repo: string, issueNumber: string, data: any, scope = "") { const key = `${scope}:${repo}/${issueNumber}`; this.reviewData.set(key, data); } - public async getPRReviewData(repo: string, issueNumber: string, scope: string = "") { + public async getPRReviewData(repo: string, issueNumber: string, scope = "") { const key = `${scope}:${repo}/${issueNumber}`; return this.reviewData.get(key) || null; } diff --git a/src/Stores/RedisStorageProvider.ts b/src/Stores/RedisStorageProvider.ts index b8c3d240..08dbf09a 100644 --- a/src/Stores/RedisStorageProvider.ts +++ b/src/Stores/RedisStorageProvider.ts @@ -1,3 +1,4 @@ +import { IssuesGetResponseData } from "@octokit/types"; import { Redis, default as redis } from "ioredis"; import LogWrapper from "../LogWrapper"; @@ -20,7 +21,7 @@ export class RedisStorageProvider implements IStorageProvider { constructor(host: string, port: number) { this.redis = new redis(port, host); this.redis.expire(COMPLETED_TRANSACTIONS_KEY, COMPLETED_TRANSACTIONS_EXPIRE_AFTER).catch((ex) => { - log.warn("Failed to set expiry time on as.completed_transactions"); + log.warn("Failed to set expiry time on as.completed_transactions", ex); }); } @@ -40,35 +41,35 @@ export class RedisStorageProvider implements IStorageProvider { return (await this.redis.sismember(COMPLETED_TRANSACTIONS_KEY, transactionId)) === 1; } - public async setGithubIssue(repo: string, issueNumber: string, data: any, scope: string = "") { + public async setGithubIssue(repo: string, issueNumber: string, data: IssuesGetResponseData, scope = "") { const key = `${scope}${GH_ISSUES_KEY}:${repo}/${issueNumber}`; await this.redis.set(key, JSON.stringify(data)); await this.redis.expire(key, ISSUES_EXPIRE_AFTER); } - public async getGithubIssue(repo: string, issueNumber: string, scope: string = "") { + public async getGithubIssue(repo: string, issueNumber: string, scope = "") { const res = await this.redis.get(`${scope}:${GH_ISSUES_KEY}:${repo}/${issueNumber}`); return res ? JSON.parse(res) : null; } - public async setLastNotifCommentUrl(repo: string, issueNumber: string, url: string, scope: string = "") { + public async setLastNotifCommentUrl(repo: string, issueNumber: string, url: string, scope = "") { const key = `${scope}${GH_ISSUES_LAST_COMMENT_KEY}:${repo}/${issueNumber}`; await this.redis.set(key, url); await this.redis.expire(key, ISSUES_LAST_COMMENT_EXPIRE_AFTER); } - public async getLastNotifCommentUrl(repo: string, issueNumber: string, scope: string = "") { + public async getLastNotifCommentUrl(repo: string, issueNumber: string, scope = "") { const res = await this.redis.get(`${scope}:${GH_ISSUES_LAST_COMMENT_KEY}:${repo}/${issueNumber}`); return res ? res : null; } - public async setPRReviewData(repo: string, issueNumber: string, url: string, scope: string = "") { + public async setPRReviewData(repo: string, issueNumber: string, url: string, scope = "") { const key = `${scope}${GH_ISSUES_REVIEW_DATA_KEY}:${repo}/${issueNumber}`; await this.redis.set(key, url); await this.redis.expire(key, ISSUES_LAST_COMMENT_EXPIRE_AFTER); } - public async getPRReviewData(repo: string, issueNumber: string, scope: string = "") { + public async getPRReviewData(repo: string, issueNumber: string, scope = "") { const res = await this.redis.get(`${scope}:${GH_ISSUES_REVIEW_DATA_KEY}:${repo}/${issueNumber}`); return res ? res : null; } diff --git a/src/Stores/StorageProvider.ts b/src/Stores/StorageProvider.ts index 524966e1..35413153 100644 --- a/src/Stores/StorageProvider.ts +++ b/src/Stores/StorageProvider.ts @@ -1,10 +1,11 @@ import { IAppserviceStorageProvider } from "matrix-bot-sdk"; +import { IssuesGetResponseData } from "@octokit/types"; export interface IStorageProvider extends IAppserviceStorageProvider { - setGithubIssue(repo: string, issueNumber: string, data: any, scope?: string): Promise; - getGithubIssue(repo: string, issueNumber: string, scope?: string): Promise; + setGithubIssue(repo: string, issueNumber: string, data: IssuesGetResponseData, scope?: string): Promise; + getGithubIssue(repo: string, issueNumber: string, scope?: string): Promise; setLastNotifCommentUrl(repo: string, issueNumber: string, url: string, scope?: string): Promise; getLastNotifCommentUrl(repo: string, issueNumber: string, scope?: string): Promise; - setPRReviewData(repo: string, issueNumber: string, data: any, scope?: string): Promise; + setPRReviewData(repo: string, issueNumber: string, data: unknown, scope?: string): Promise; getPRReviewData(repo: string, issueNumber: string, scope?: string): Promise; } \ No newline at end of file diff --git a/src/UserNotificationWatcher.ts b/src/UserNotificationWatcher.ts deleted file mode 100644 index 0fde8fad..00000000 --- a/src/UserNotificationWatcher.ts +++ /dev/null @@ -1,204 +0,0 @@ -import { NotificationsEnableEvent } from "./GithubWebhooks"; -import { Octokit } from "@octokit/rest"; -import { createTokenAuth } from "@octokit/auth-token"; -import { RequestError } from "@octokit/request-error"; -import LogWrapper from "./LogWrapper"; -import { MessageQueue } from "./MessageQueue/MessageQueue"; -import { MessageSenderClient } from "./MatrixSender"; - -interface UserStream { - octoKit: Octokit; - userId: string; - roomId: string; - lastReadTs: number; - participating: boolean; - failureCount: number; -} - -export interface UserNotificationsEvent { - roomId: string; - lastReadTs: number; - events: UserNotification[]; -} - -export interface UserNotification { - id: string; - reason: "assign"|"author"|"comment"|"invitation"|"manual"|"mention"|"review_requested"| - "security_alert"|"state_change"|"subscribed"|"team_mention"; - unread: boolean; - updated_at: number; - last_read_at: number; - url: string; - subject: { - title: string; - url: string; - latest_comment_url: string|null; - type: "PullRequest"|"Issue"|"RepositoryVulnerabilityAlert"; - // Probably. - url_data?: Octokit.IssuesGetResponse; - latest_comment_url_data?: Octokit.IssuesGetCommentResponse; - requested_reviewers?: Octokit.PullsListReviewRequestsResponse; - reviews?: Octokit.PullsListReviewsResponse; - }; - repository: Octokit.ActivityGetThreadResponseRepository; -} - -const MIN_INTERVAL_MS = 15000; -const FAILURE_THRESHOLD = 50; -const GH_API_THRESHOLD = 50; -const GH_API_RETRY_IN = 1000 * 60; - -const log = new LogWrapper("UserNotificationWatcher"); - -export class UserNotificationWatcher { - private userIntervals: Map = new Map(); - private matrixMessageSender: MessageSenderClient; - private apiFailureCount: number = 0; - private globalRetryIn: number = 0; - - constructor(private queue: MessageQueue) { - this.matrixMessageSender = new MessageSenderClient(queue); - } - - public checkGitHubStatus() { - this.apiFailureCount = Math.min(this.apiFailureCount + 1, GH_API_THRESHOLD); - if (this.apiFailureCount < GH_API_THRESHOLD) { - log.warn(`API Failure count at ${this.apiFailureCount}`); - return; - } - // The API is actively failing. - if (this.globalRetryIn > 0) { - this.globalRetryIn = Date.now() + GH_API_RETRY_IN; - } - log.warn(`API Failure limit reached, holding off new requests for ${GH_API_RETRY_IN / 1000}s`); - } - - public start() { - // No-op - } - - public async fetchUserNotifications(stream: UserStream) { - if (this.globalRetryIn !== 0 && this.globalRetryIn > Date.now()) { - log.info(`Not getting notifications for ${stream.userId}, API is still down.`); - return stream; - } - log.info(`Getting notifications for ${stream.userId} ${stream.lastReadTs}`); - const since = stream.lastReadTs !== 0 ? `&since=${new Date(stream.lastReadTs).toISOString()}`: ""; - let response: Octokit.AnyResponse; - try { - response = await stream.octoKit.request( - `/notifications?participating=${stream.participating}${since}`, - ); - // We were succesful, clear any timeouts. - this.globalRetryIn = 0; - // To avoid a bouncing issue, gradually reduce the failure count. - this.apiFailureCount = Math.max(0, this.apiFailureCount - 2); - } catch (ex) { - await this.handleGitHubFailure(stream, ex); - return stream; - } - log.info(`Got ${response.data.length} notifications`); - stream.lastReadTs = Date.now(); - const events: UserNotification[] = []; - - for (const rawEvent of response.data as UserNotification[]) { - try { - await (async () => { - if (rawEvent.subject.url) { - const res = await stream.octoKit.request(rawEvent.subject.url); - rawEvent.subject.url_data = res.data; - } - if (rawEvent.subject.latest_comment_url) { - const res = await stream.octoKit.request(rawEvent.subject.latest_comment_url); - rawEvent.subject.latest_comment_url_data = res.data; - } - if (rawEvent.reason === "review_requested") { - rawEvent.subject.requested_reviewers = (await stream.octoKit.pulls.listReviewRequests({ - pull_number: rawEvent.subject.url_data?.number!, - owner: rawEvent.repository.owner.login, - repo: rawEvent.repository.name, - })).data; - rawEvent.subject.reviews = (await stream.octoKit.pulls.listReviews({ - pull_number: rawEvent.subject.url_data?.number!, - owner: rawEvent.repository.owner.login, - repo: rawEvent.repository.name, - })).data; - } - events.push(rawEvent); - })(); - } catch (ex) { - log.warn(`Failed to pre-process ${rawEvent.id}: ${ex}`); - // If it fails, we can just push the raw thing. - events.push(rawEvent); - } - } - - if (events.length > 0) { - await this.queue.push({ - eventName: "notifications.user.events", - data: { - roomId: stream.roomId, - events, - lastReadTs: stream.lastReadTs, - }, - sender: "GithubWebhooks", - }); - } - return stream; - } - - public handleGitHubFailure(stream: UserStream, ex: RequestError) { - log.error("An error occured getting notifications:", ex); - if (ex.status === 401 || ex.status === 404) { - log.warn(`Got status ${ex.status} when handing user stream: ${ex.message}`); - stream.failureCount++; - } else if (ex.status >= 500) { - setImmediate(() => this.checkGitHubStatus()); - } - - if (stream.failureCount > FAILURE_THRESHOLD) { - this.removeUser(stream.userId); - return this.matrixMessageSender.sendMatrixText( - stream.roomId, -`The bridge has been unable to process your notification stream for some time, and has disabled notifications. -Check your GitHub token is still valid, and then turn notifications back on.`, "m.notice", - ); - } - return null; - } - - public removeUser(userId: string) { - const timer = this.userIntervals.get(userId); - if (timer) { - clearInterval(timer); - log.info(`Removed ${userId} to notif queue`); - } - } - - public addUser(data: NotificationsEnableEvent) { - const clientKit = new Octokit({ - authStrategy: createTokenAuth, - auth: data.token, - userAgent: "matrix-github v0.0.1", - }); - - const userId = data.user_id; - this.removeUser(userId); - - let stream: UserStream = { - octoKit: clientKit, - userId, - roomId: data.room_id, - lastReadTs: data.since, - participating: data.filter_participating, - failureCount: 0, - }; - - log.info(`Inserted ${userId} into the notif queue`); - const interval = setInterval(async () => { - stream = await this.fetchUserNotifications(stream); - }, MIN_INTERVAL_MS); - this.userIntervals.set(userId, interval); - return; - } -} diff --git a/src/UserTokenStore.ts b/src/UserTokenStore.ts index 39b70592..e4e0d3bd 100644 --- a/src/UserTokenStore.ts +++ b/src/UserTokenStore.ts @@ -2,9 +2,8 @@ import { Intent } from "matrix-bot-sdk"; import { promises as fs } from "fs"; import { publicEncrypt, privateDecrypt } from "crypto"; import LogWrapper from "./LogWrapper"; -import { Octokit } from "@octokit/rest"; -import { createTokenAuth } from "@octokit/auth-token"; import { GitLabClient } from "./Gitlab/Client"; +import { GithubInstance } from "./Github/GithubInstance"; const ACCOUNT_DATA_TYPE = "uk.half-shot.matrix-github.password-store:"; const ACCOUNT_DATA_GITLAB_TYPE = "uk.half-shot.matrix-github.gitlab.password-store:"; @@ -23,7 +22,7 @@ export class UserTokenStore { } public async storeUserToken(type: "github"|"gitlab", userId: string, token: string, instance?: string): Promise { - let prefix = type === "github" ? ACCOUNT_DATA_TYPE : ACCOUNT_DATA_GITLAB_TYPE; + const prefix = type === "github" ? ACCOUNT_DATA_TYPE : ACCOUNT_DATA_GITLAB_TYPE; await this.intent.underlyingClient.setAccountData(`${prefix}${userId}`, { encrypted: publicEncrypt(this.key, Buffer.from(token)).toString("base64"), instance: instance, @@ -33,8 +32,9 @@ export class UserTokenStore { } public async getUserToken(type: "github"|"gitlab", userId: string, instance?: string): Promise { - if (this.userTokens.has(userId)) { - return this.userTokens.get(userId)!; + const existingToken = this.userTokens.get(userId); + if (existingToken) { + return existingToken; } let obj; try { @@ -61,11 +61,7 @@ export class UserTokenStore { if (!senderToken) { return null; } - return new Octokit({ - authStrategy: createTokenAuth, - auth: senderToken, - userAgent: "matrix-github v0.0.1", - }); + return GithubInstance.createUserOctokit(senderToken); } public async getGitLabForUser(userId: string, instanceUrl: string) { diff --git a/tests/FormatUtilTest.ts b/tests/FormatUtilTest.ts index fecc94d1..0ff3a8a1 100644 --- a/tests/FormatUtilTest.ts +++ b/tests/FormatUtilTest.ts @@ -5,13 +5,15 @@ const SIMPLE_ISSUE = { number: 123, state: "open", title: "A simple title", + full_name: "evilcorp/lab", + url: "https://github.com/evilcorp/lab/issues/123", html_url: "https://github.com/evilcorp/lab/issues/123", repository_url: "https://api.github.com/repos/evilcorp/lab", }; describe("FormatUtilTest", () => { it("correctly formats a room name", () => { - expect(FormatUtil.formatRoomName(SIMPLE_ISSUE)).to.equal( + expect(FormatUtil.formatRepoRoomName(SIMPLE_ISSUE)).to.equal( "evilcorp/lab#123: A simple title", ); }); diff --git a/tests/MessageQueueTest.ts b/tests/MessageQueueTest.ts index 9bf8e53c..3fa2ea84 100644 --- a/tests/MessageQueueTest.ts +++ b/tests/MessageQueueTest.ts @@ -26,6 +26,7 @@ describe("MessageQueueTest", () => { eventName: "fakeevent", messageId: "foooo", data: 51, + ts: 0, }); }); it("should be able to push an event, and respond to it", async () => { @@ -43,6 +44,7 @@ describe("MessageQueueTest", () => { eventName: "response.fakeevent2", messageId: "foooo", data: "worked", + ts: 0, }); }); const response = await mq.pushWait({ @@ -50,6 +52,7 @@ describe("MessageQueueTest", () => { eventName: "fakeevent2", messageId: "foooo", data: 49, + ts: 0, }); expect(response).to.equal("worked"); }); diff --git a/yarn.lock b/yarn.lock index f6f6a6d3..d6e8b05a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -32,120 +32,151 @@ enabled "2.0.x" kuler "^2.0.0" -"@octokit/auth-app@^2.4.2": - version "2.4.10" - resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-2.4.10.tgz#8e58a5e665513f5e5a4e9a8645f4ac74fbd55f47" - integrity sha512-0MmbzxNsUyWW4/dQ/gKe6D+QJNFa/QA8TD9VdxO+f0F00c1RTxT8FtH1Gd0BCq/+4e0uaJy58RjC5Rqe9f8D2g== +"@eslint/eslintrc@^0.2.1": + version "0.2.1" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-0.2.1.tgz#f72069c330461a06684d119384435e12a5d76e3c" + integrity sha512-XRUeBZ5zBWLYgSANMpThFddrZZkEbGHgUdt5UJjZfnlN9BGCiUBrf+nvbRupSjMvqzwnQN0qwCmOxITt1cfywA== + dependencies: + ajv "^6.12.4" + debug "^4.1.1" + espree "^7.3.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.2.1" + js-yaml "^3.13.1" + lodash "^4.17.19" + minimatch "^3.0.4" + strip-json-comments "^3.1.1" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@octokit/auth-app@^2.10.2": + version "2.10.2" + resolved "https://registry.yarnpkg.com/@octokit/auth-app/-/auth-app-2.10.2.tgz#5cfdc69c8866d1acc353688421e85851f55aac11" + integrity sha512-3PLyDISHtdCxQx0LS0Ut2E+zy2PVfDFCxDnFJ+QRvABHow/Zqj2Im7GF8zYYn8nwI1tgaoewwwd0unfXuPi48Q== dependencies: "@octokit/request" "^5.3.0" "@octokit/request-error" "^2.0.0" "@octokit/types" "^5.0.0" "@types/lru-cache" "^5.1.0" + deprecation "^2.3.1" lru-cache "^6.0.0" universal-github-app-jwt "^1.0.1" universal-user-agent "^6.0.0" -"@octokit/auth-token@^2.4.0": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.2.tgz#10d0ae979b100fa6b72fa0e8e63e27e6d0dbff8a" - integrity sha512-jE/lE/IKIz2v1+/P0u4fJqv0kYwXOTujKemJMFr6FeopsxlIK3+wKDCJGnysg81XID5TgZQbIfuJ5J0lnTiuyQ== +"@octokit/auth-token@^2.4.0", "@octokit/auth-token@^2.4.3": + version "2.4.3" + resolved "https://registry.yarnpkg.com/@octokit/auth-token/-/auth-token-2.4.3.tgz#b868b5f2366533a7e62933eaa1181a8924228cc4" + integrity sha512-fdGoOQ3kQJh+hrilc0Plg50xSfaCKOeYN9t6dpJKXN9BxhhfquL0OzoQXg3spLYymL5rm29uPeI3KEXRaZQ9zg== dependencies: "@octokit/types" "^5.0.0" -"@octokit/endpoint@^6.0.1": - version "6.0.4" - resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.4.tgz#da3eafdee1fabd6e5b6ca311efcba26f0dd99848" - integrity sha512-ZJHIsvsClEE+6LaZXskDvWIqD3Ao7+2gc66pRG5Ov4MQtMvCU9wGu1TItw9aGNmRuU9x3Fei1yb+uqGaQnm0nw== +"@octokit/core@^3.0.0": + version "3.2.1" + resolved "https://registry.yarnpkg.com/@octokit/core/-/core-3.2.1.tgz#9e04df3f4e7f825ac0559327490ce34299140af5" + integrity sha512-XfFSDDwv6tclUenS0EmB6iA7u+4aOHBT1Lz4PtQNQQg3hBbNaR/+Uv5URU+egeIuuGAiMRiDyY92G4GBOWOqDA== dependencies: + "@octokit/auth-token" "^2.4.0" + "@octokit/graphql" "^4.3.1" + "@octokit/request" "^5.4.0" "@octokit/types" "^5.0.0" - is-plain-object "^3.0.0" + before-after-hook "^2.1.0" universal-user-agent "^6.0.0" -"@octokit/plugin-paginate-rest@^1.1.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-1.1.2.tgz#004170acf8c2be535aba26727867d692f7b488fc" - integrity sha512-jbsSoi5Q1pj63sC16XIUboklNw+8tL9VOnJsWycWYR78TKss5PVpIPb1TUUcMQ+bBh7cY579cVAWmf5qG+dw+Q== +"@octokit/endpoint@^6.0.1": + version "6.0.9" + resolved "https://registry.yarnpkg.com/@octokit/endpoint/-/endpoint-6.0.9.tgz#c6a772e024202b1bd19ab69f90e0536a2598b13e" + integrity sha512-3VPLbcCuqji4IFTclNUtGdp9v7g+nspWdiCUbK3+iPMjJCZ6LEhn1ts626bWLOn0GiDb6j+uqGvPpqLnY7pBgw== dependencies: - "@octokit/types" "^2.0.1" + "@octokit/types" "^5.0.0" + is-plain-object "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/graphql@^4.3.1": + version "4.5.7" + resolved "https://registry.yarnpkg.com/@octokit/graphql/-/graphql-4.5.7.tgz#f4562dcd9e80ea94602068e85aefac19a88f8578" + integrity sha512-Gk0AR+DcwIK/lK/GX+OQ99UqtenQhcbrhHHfOYlrCQe17ADnX3EKAOKRsAZ9qZvpi5MuwWm/Nm+9aO2kTDSdyA== + dependencies: + "@octokit/request" "^5.3.0" + "@octokit/types" "^5.0.0" + universal-user-agent "^6.0.0" + +"@octokit/plugin-paginate-rest@^2.2.0": + version "2.6.0" + resolved "https://registry.yarnpkg.com/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.6.0.tgz#03416396e7a227b268c5b827365238f620a9c5c1" + integrity sha512-o+O8c1PqsC5++BHXfMZabRRsBIVb34tXPWyQLyp2IXq5MmkxdipS7TXM4Y9ldL1PzY9CTrCsn/lzFFJGM3oRRA== + dependencies: + "@octokit/types" "^5.5.0" "@octokit/plugin-request-log@^1.0.0": - version "1.0.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.0.tgz#eef87a431300f6148c39a7f75f8cfeb218b2547e" - integrity sha512-ywoxP68aOT3zHCLgWZgwUJatiENeHE7xJzYjfz8WI0goynp96wETBF+d95b8g/uL4QmS6owPVlaxiz3wyMAzcw== + version "1.0.2" + resolved "https://registry.yarnpkg.com/@octokit/plugin-request-log/-/plugin-request-log-1.0.2.tgz#394d59ec734cd2f122431fbaf05099861ece3c44" + integrity sha512-oTJSNAmBqyDR41uSMunLQKMX0jmEXbwD1fpz8FG27lScV3RhtGfBa1/BBLym+PxcC16IBlF7KH9vP1BUYxA+Eg== -"@octokit/plugin-rest-endpoint-methods@2.4.0": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-2.4.0.tgz#3288ecf5481f68c494dd0602fc15407a59faf61e" - integrity sha512-EZi/AWhtkdfAYi01obpX0DF7U6b1VRr30QNQ5xSFPITMdLSfhcBqjamE3F+sKcxPbD7eZuMHu3Qkk2V+JGxBDQ== +"@octokit/plugin-rest-endpoint-methods@4.2.1": + version "4.2.1" + resolved "https://registry.yarnpkg.com/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-4.2.1.tgz#8224833a45c3394836dc6e86f1e6c49269a2c350" + integrity sha512-QyFr4Bv807Pt1DXZOC5a7L5aFdrwz71UHTYoHVajYV5hsqffWm8FUl9+O7nxRu5PDMtB/IKrhFqTmdBTK5cx+A== dependencies: - "@octokit/types" "^2.0.1" + "@octokit/types" "^5.5.0" deprecation "^2.3.1" -"@octokit/request-error@^1.0.2": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-1.2.1.tgz#ede0714c773f32347576c25649dc013ae6b31801" - integrity sha512-+6yDyk1EES6WK+l3viRDElw96MvwfJxCt45GvmjDUKWjYIb3PJZQkq3i46TwGwoPD4h8NmTrENmtyA1FwbmhRA== - dependencies: - "@octokit/types" "^2.0.0" - deprecation "^2.0.0" - once "^1.4.0" - "@octokit/request-error@^2.0.0": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.2.tgz#0e76b83f5d8fdda1db99027ea5f617c2e6ba9ed0" - integrity sha512-2BrmnvVSV1MXQvEkrb9zwzP0wXFNbPJij922kYBTLIlIafukrGOb+ABBT2+c6wZiuyWDH1K1zmjGQ0toN/wMWw== + version "2.0.3" + resolved "https://registry.yarnpkg.com/@octokit/request-error/-/request-error-2.0.3.tgz#b51b200052bf483f6fa56c9e7e3aa51ead36ecd8" + integrity sha512-GgD5z8Btm301i2zfvJLk/mkhvGCdjQ7wT8xF9ov5noQY8WbKZDH9cOBqXzoeKd1mLr1xH2FwbtGso135zGBgTA== dependencies: "@octokit/types" "^5.0.1" deprecation "^2.0.0" once "^1.4.0" -"@octokit/request@^5.2.0", "@octokit/request@^5.3.0": - version "5.4.6" - resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.6.tgz#e8cc8d4cfc654d30428ea92aaa62168fd5ead7eb" - integrity sha512-9r8Sn4CvqFI9LDLHl9P17EZHwj3ehwQnTpTE+LEneb0VBBqSiI/VS4rWIBfBhDrDs/aIGEGZRSB0QWAck8u+2g== +"@octokit/request@^5.3.0", "@octokit/request@^5.4.0": + version "5.4.10" + resolved "https://registry.yarnpkg.com/@octokit/request/-/request-5.4.10.tgz#402d2c53768bde12b99348329ba4129746aebb9c" + integrity sha512-egA49HkqEORVGDZGav1mh+VD+7uLgOxtn5oODj6guJk0HCy+YBSYapFkSLFgeYj3Fr18ZULKGURkjyhkAChylw== dependencies: "@octokit/endpoint" "^6.0.1" "@octokit/request-error" "^2.0.0" "@octokit/types" "^5.0.0" deprecation "^2.0.0" - is-plain-object "^3.0.0" - node-fetch "^2.3.0" + is-plain-object "^5.0.0" + node-fetch "^2.6.1" once "^1.4.0" universal-user-agent "^6.0.0" -"@octokit/rest@^16.43.1": - version "16.43.2" - resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-16.43.2.tgz#c53426f1e1d1044dee967023e3279c50993dd91b" - integrity sha512-ngDBevLbBTFfrHZeiS7SAMAZ6ssuVmXuya+F/7RaVvlysgGa1JKJkKWY+jV6TCJYcW0OALfJ7nTIGXcBXzycfQ== +"@octokit/rest@^18.0.9": + version "18.0.9" + resolved "https://registry.yarnpkg.com/@octokit/rest/-/rest-18.0.9.tgz#964d707d914eb34b1787895fdcacff96de47844d" + integrity sha512-CC5+cIx974Ygx9lQNfUn7/oXDQ9kqGiKUC6j1A9bAVZZ7aoTF8K6yxu0pQhQrLBwSl92J6Z3iVDhGhGFgISCZg== dependencies: - "@octokit/auth-token" "^2.4.0" - "@octokit/plugin-paginate-rest" "^1.1.1" + "@octokit/core" "^3.0.0" + "@octokit/plugin-paginate-rest" "^2.2.0" "@octokit/plugin-request-log" "^1.0.0" - "@octokit/plugin-rest-endpoint-methods" "2.4.0" - "@octokit/request" "^5.2.0" - "@octokit/request-error" "^1.0.2" - atob-lite "^2.0.0" - before-after-hook "^2.0.0" - btoa-lite "^1.0.0" - deprecation "^2.0.0" - lodash.get "^4.4.2" - lodash.set "^4.3.2" - lodash.uniq "^4.5.0" - octokit-pagination-methods "^1.1.0" - once "^1.4.0" - universal-user-agent "^4.0.0" + "@octokit/plugin-rest-endpoint-methods" "4.2.1" -"@octokit/types@^2.0.0", "@octokit/types@^2.0.1": - version "2.16.2" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-2.16.2.tgz#4c5f8da3c6fecf3da1811aef678fda03edac35d2" - integrity sha512-O75k56TYvJ8WpAakWwYRN8Bgu60KrmX0z1KqFp1kNiFNkgW+JW+9EBKZ+S33PU6SLvbihqd+3drvPxKK68Ee8Q== - dependencies: - "@types/node" ">= 8" - -"@octokit/types@^5.0.0", "@octokit/types@^5.0.1": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.1.0.tgz#4377a3f39edad3e60753fb5c3c310756f1ded57f" - integrity sha512-OFxUBgrEllAbdEmWp/wNmKIu5EuumKHG4sgy56vjZ8lXPgMhF05c76hmulfOdFHHYRpPj49ygOZJ8wgVsPecuA== +"@octokit/types@^5.0.0", "@octokit/types@^5.0.1", "@octokit/types@^5.5.0": + version "5.5.0" + resolved "https://registry.yarnpkg.com/@octokit/types/-/types-5.5.0.tgz#e5f06e8db21246ca102aa28444cdb13ae17a139b" + integrity sha512-UZ1pErDue6bZNjYOotCNveTXArOMZQFG6hKJfOnGnulVCMcVVi7YIIuuR4WfBhjo7zgpmzn/BkPDnUXtNx+PcQ== dependencies: "@types/node" ">= 8" @@ -162,15 +193,10 @@ resolved "https://registry.yarnpkg.com/@types/braces/-/braces-3.0.0.tgz#7da1c0d44ff1c7eb660a36ec078ea61ba7eb42cb" integrity sha512-TbH79tcyi9FHwbyboOKeRachRq63mSuWYXOflsNO9ZyE5ClQ/JaozNKl+aWUq87qPNsXasXxi2AbgfwIJ+8GQw== -"@types/chai@^4.1.7": - version "4.2.11" - resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.11.tgz#d3614d6c5f500142358e6ed24e1bf16657536c50" - integrity sha512-t7uW6eFafjO+qJ3BIV2gGUyZs27egcNRkUdalkud+Qa3+kg//f129iuOFivHDXQ+vnU3fDXuwgv0cqMCbcE8sw== - -"@types/color-name@^1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" - integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== +"@types/chai@^4.2.14": + version "4.2.14" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.2.14.tgz#44d2dd0b5de6185089375d976b4ec5caf6861193" + integrity sha512-G+ITQPXkwTrslfG5L/BksmbLUA0M1iybEsmCWPqzSxsRRhJZimBKJkoMi8fr/CPygPTj4zO5pJH7I2/cm9M7SQ== "@types/connect@*": version "3.4.33" @@ -180,31 +206,41 @@ "@types/node" "*" "@types/express-serve-static-core@*": - version "4.17.8" - resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz#b8f7b714138536742da222839892e203df569d1c" - integrity sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw== + version "4.17.13" + resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.13.tgz#d9af025e925fc8b089be37423b8d1eac781be084" + integrity sha512-RgDi5a4nuzam073lRGKTUIaL3eF2+H7LJvJ8eUnCI0wA6SNjXc44DCmWNiTLs/AZ7QlsFWZiw/gTG3nSQGL0fA== dependencies: "@types/node" "*" "@types/qs" "*" "@types/range-parser" "*" -"@types/express@^4.17.0", "@types/express@^4.17.2": - version "4.17.7" - resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.7.tgz#42045be6475636d9801369cd4418ef65cdb0dd59" - integrity sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ== +"@types/express@^4.17.7", "@types/express@^4.17.9": + version "4.17.9" + resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.9.tgz#f5f2df6add703ff28428add52bdec8a1091b0a78" + integrity sha512-SDzEIZInC4sivGIFY4Sz1GG6J9UObPwCInYJjko2jzOf/Imx/dlpume6Xxwj1ORL82tBbmN4cPDIDkLbWHk9hw== dependencies: "@types/body-parser" "*" "@types/express-serve-static-core" "*" "@types/qs" "*" "@types/serve-static" "*" -"@types/ioredis@^4.0.13": - version "4.17.2" - resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.17.2.tgz#2a9b0aeba5cf8d5f38afdeb85ef77ec95040d80c" - integrity sha512-T0sEKyqkhr4/RfgM2iTtmy0uPI4QZ9c0syq3mmAPNS5ZZMzjdtKv1ziuTdyNUvh0mZihXfKcRcWZI2wRYnxO7Q== +"@types/highlight.js@^9.7.0": + version "9.12.4" + resolved "https://registry.yarnpkg.com/@types/highlight.js/-/highlight.js-9.12.4.tgz#8c3496bd1b50cc04aeefd691140aa571d4dbfa34" + integrity sha512-t2szdkwmg2JJyuCM20e8kR2X59WCE5Zkl4bzm1u1Oukjm79zpbiAv+QjnwLnuuV0WHEcX2NgUItu0pAMKuOPww== + +"@types/ioredis@^4.17.8": + version "4.17.8" + resolved "https://registry.yarnpkg.com/@types/ioredis/-/ioredis-4.17.8.tgz#a761c9adac03a9f0413157691fdae247262eb523" + integrity sha512-13WwLG9jMvzjabpBydDXKSPdvAnKI8pZOKk9rEFp3QizyJS8riyNyVRV5ATvU1DCKsz31KM9g90etnTGgMFh3g== dependencies: "@types/node" "*" +"@types/json-schema@^7.0.3": + version "7.0.6" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.6.tgz#f4c7ec43e81b319a9815115031709f26987891f0" + integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw== + "@types/jsonwebtoken@^8.3.3": version "8.5.0" resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.0.tgz#2531d5e300803aa63279b232c014acf780c981c5" @@ -222,29 +258,37 @@ resolved "https://registry.yarnpkg.com/@types/lru-cache/-/lru-cache-5.1.0.tgz#57f228f2b80c046b4a1bd5cac031f81f207f4f03" integrity sha512-RaE0B+14ToE4l6UqdarKPnXwVDuigfFv+5j9Dze/Nqr23yyuqdNvzcZi3xB+3Agvi5R4EOgAksfv3lXX4vBt9w== -"@types/markdown-it@^0.0.8": - version "0.0.8" - resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-0.0.8.tgz#9af8704acde87fec70475369ba0413d50717bd8d" - integrity sha512-ouaTOi5kAdkTPl97u6uDkth9od4pQffPF9STcjYVZKFrEwLYf15s7Z772WxWE3IOcYBJglaT0XqdyNEiEfGgYg== +"@types/markdown-it@^10.0.3": + version "10.0.3" + resolved "https://registry.yarnpkg.com/@types/markdown-it/-/markdown-it-10.0.3.tgz#a9800d14b112c17f1de76ec33eff864a4815eec7" + integrity sha512-daHJk22isOUvNssVGF2zDnnSyxHhFYhtjeX4oQaKD6QzL3ZR1QSgiD1g+Q6/WSWYVogNXYDXODtbgW/WiFCtyw== dependencies: + "@types/highlight.js" "^9.7.0" "@types/linkify-it" "*" + "@types/mdurl" "*" + highlight.js "^9.7.0" -"@types/micromatch@^3.1.0": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@types/micromatch/-/micromatch-3.1.1.tgz#98eac88894da6606c2690624a9893a59c812d9fa" - integrity sha512-Wr5y4uv3r7JP4jEUqv7rZeYiMBGRHcbojDVsl11wq6gw1v/ZZQvJexd9rtvVx3EIVqw8dwtcRjSs8m2DV9qHjQ== +"@types/mdurl@*": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@types/mdurl/-/mdurl-1.0.2.tgz#e2ce9d83a613bacf284c7be7d491945e39e1f8e9" + integrity sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA== + +"@types/micromatch@^4.0.1": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@types/micromatch/-/micromatch-4.0.1.tgz#9381449dd659fc3823fd2a4190ceacc985083bc7" + integrity sha512-my6fLBvpY70KattTNzYOK6KU1oR1+UCz9ug/JbcF5UrEmeCt9P7DV2t7L8+t18mMPINqGQCE4O8PLOPbI84gxw== dependencies: "@types/braces" "*" -"@types/mime@*", "@types/mime@^2.0.1": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.2.tgz#857a118d8634c84bba7ae14088e4508490cd5da5" - integrity sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q== +"@types/mime@*", "@types/mime@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/mime/-/mime-2.0.3.tgz#c893b73721db73699943bfc3653b1deb7faa4a3a" + integrity sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q== -"@types/mocha@^5.2.7": - version "5.2.7" - resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.7.tgz#315d570ccb56c53452ff8638738df60726d5b6ea" - integrity sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ== +"@types/mocha@^8.0.4": + version "8.0.4" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-8.0.4.tgz#b840c2dce46bacf286e237bfb59a29e843399148" + integrity sha512-M4BwiTJjHmLq6kjON7ZoI2JMlBvpY3BYSdiP6s/qCT3jb1s9/DeJF0JELpAxiVSIxXDzfNKe+r7yedMIoLbknQ== "@types/node-emoji@^1.8.1": version "1.8.1" @@ -252,19 +296,19 @@ integrity sha512-0fRfA90FWm6KJfw6P9QGyo0HDTCmthZ7cWaBQndITlaWLTZ6njRyKwrwpzpg+n6kBXBIGKeUHEQuBx7bphGJkA== "@types/node@*", "@types/node@>= 8": - version "14.0.23" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.23.tgz#676fa0883450ed9da0bb24156213636290892806" - integrity sha512-Z4U8yDAl5TFkmYsZdFPdjeMa57NOvnaf1tljHzhouaPEp7LCj2JKkejpI1ODviIAQuW4CcQmxkQ77rnLsOOoKw== + version "14.14.9" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.14.9.tgz#04afc9a25c6ff93da14deabd65dc44485b53c8d6" + integrity sha512-JsoLXFppG62tWTklIoO4knA+oDTYsmqWxHRvd4lpmfQRNhX6osheUOWETP2jMoV/2bEHuMra8Pp3Dmo/stBFcw== -"@types/node@^12.6.9": - version "12.12.50" - resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.50.tgz#e9b2e85fafc15f2a8aa8fdd41091b983da5fd6ee" - integrity sha512-5ImO01Fb8YsEOYpV+aeyGYztcYcjGsBvN4D7G5r1ef2cuQOpymjWNQi5V0rKHE6PC2ru3HkoUr/Br2/8GUA84w== +"@types/node@^12": + version "12.19.6" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.19.6.tgz#fbf249fa46487dd8c7386d785231368b92a33a53" + integrity sha512-U2VopDdmBoYBmtm8Rz340mvvSz34VgX/K9+XCuckvcLGMkt3rbMX8soqFOikIPlPBc5lmw8By9NUK7bEFSBFlQ== "@types/qs@*": - version "6.9.3" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.3.tgz#b755a0934564a200d3efdf88546ec93c369abd03" - integrity sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA== + version "6.9.5" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.5.tgz#434711bdd49eb5ee69d90c1d67c354a9a8ecb18b" + integrity sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ== "@types/range-parser@*": version "1.2.3" @@ -272,24 +316,92 @@ integrity sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA== "@types/serve-static@*": - version "1.13.4" - resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.4.tgz#6662a93583e5a6cabca1b23592eb91e12fa80e7c" - integrity sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug== + version "1.13.8" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.13.8.tgz#851129d434433c7082148574ffec263d58309c46" + integrity sha512-MoJhSQreaVoL+/hurAZzIm8wafFR6ajiTM1m4A0kv6AGeVBl4r4pOV8bGFrjjq1sGxDTnCoF8i22o0/aE5XCyA== dependencies: - "@types/express-serve-static-core" "*" "@types/mime" "*" + "@types/node" "*" -"@types/uuid@^3.4.5": - version "3.4.9" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-3.4.9.tgz#fcf01997bbc9f7c09ae5f91383af076d466594e1" - integrity sha512-XDwyIlt/47l2kWLTzw/mtrpLdB+GPSskR2n/PIcPn+VYhVO77rGhRncIR5GPU0KRzXuqkDO+J5qqrG0Y8P6jzQ== +"@types/uuid@^8.3.0": + version "8.3.0" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.0.tgz#215c231dff736d5ba92410e6d602050cce7e273f" + integrity sha512-eQ9qFW/fhfGJF8WKHGEHZEyVWfZxrT+6CLIJGBcZPfxUh/+BnEj+UCGYMlr9qZuX/2AltsvwrGqp0LhEW8D0zQ== -"@types/yaml@^1.0.2": - version "1.9.7" - resolved "https://registry.yarnpkg.com/@types/yaml/-/yaml-1.9.7.tgz#2331f36e0aac91311a63d33eb026c21687729679" - integrity sha512-8WMXRDD1D+wCohjfslHDgICd2JtMATZU8CkhH8LVJqcJs6dyYj5TGptzP8wApbmEullGBSsCEzzap73DQ1HJaA== +"@typescript-eslint/eslint-plugin@^4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-4.8.1.tgz#b362abe0ee478a6c6d06c14552a6497f0b480769" + integrity sha512-d7LeQ7dbUrIv5YVFNzGgaW3IQKMmnmKFneRWagRlGYOSfLJVaRbj/FrBNOBC1a3tVO+TgNq1GbHvRtg1kwL0FQ== dependencies: - yaml "*" + "@typescript-eslint/experimental-utils" "4.8.1" + "@typescript-eslint/scope-manager" "4.8.1" + debug "^4.1.1" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-4.8.1.tgz#27275c20fa4336df99ebcf6195f7d7aa7aa9f22d" + integrity sha512-WigyLn144R3+lGATXW4nNcDJ9JlTkG8YdBWHkDlN0lC3gUGtDi7Pe3h5GPvFKMcRz8KbZpm9FJV9NTW8CpRHpg== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/scope-manager" "4.8.1" + "@typescript-eslint/types" "4.8.1" + "@typescript-eslint/typescript-estree" "4.8.1" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.8.1.tgz#4fe2fbdbb67485bafc4320b3ae91e34efe1219d1" + integrity sha512-QND8XSVetATHK9y2Ltc/XBl5Ro7Y62YuZKnPEwnNPB8E379fDsvzJ1dMJ46fg/VOmk0hXhatc+GXs5MaXuL5Uw== + dependencies: + "@typescript-eslint/scope-manager" "4.8.1" + "@typescript-eslint/types" "4.8.1" + "@typescript-eslint/typescript-estree" "4.8.1" + debug "^4.1.1" + +"@typescript-eslint/scope-manager@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-4.8.1.tgz#e343c475f8f1d15801b546cb17d7f309b768fdce" + integrity sha512-r0iUOc41KFFbZdPAdCS4K1mXivnSZqXS5D9oW+iykQsRlTbQRfuFRSW20xKDdYiaCoH+SkSLeIF484g3kWzwOQ== + dependencies: + "@typescript-eslint/types" "4.8.1" + "@typescript-eslint/visitor-keys" "4.8.1" + +"@typescript-eslint/types@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-4.8.1.tgz#23829c73c5fc6f4fcd5346a7780b274f72fee222" + integrity sha512-ave2a18x2Y25q5K05K/U3JQIe2Av4+TNi/2YuzyaXLAsDx6UZkz1boZ7nR/N6Wwae2PpudTZmHFXqu7faXfHmA== + +"@typescript-eslint/typescript-estree@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-4.8.1.tgz#7307e3f2c9e95df7daa8dc0a34b8c43b7ec0dd32" + integrity sha512-bJ6Fn/6tW2g7WIkCWh3QRlaSU7CdUUK52shx36/J7T5oTQzANvi6raoTsbwGM11+7eBbeem8hCCKbyvAc0X3sQ== + dependencies: + "@typescript-eslint/types" "4.8.1" + "@typescript-eslint/visitor-keys" "4.8.1" + debug "^4.1.1" + globby "^11.0.1" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + +"@typescript-eslint/visitor-keys@4.8.1": + version "4.8.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-4.8.1.tgz#794f68ee292d1b2e3aa9690ebedfcb3a8c90e3c3" + integrity sha512-3nrwXFdEYALQh/zW8rFwP4QltqsanCDz4CwWMPiIZmwlk9GlvBeueEIbq05SEq4ganqM0g9nh02xXgv5XI3PeQ== + dependencies: + "@typescript-eslint/types" "4.8.1" + eslint-visitor-keys "^2.0.0" + +"@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== accepts@~1.3.7: version "1.3.7" @@ -299,20 +411,30 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" -ajv@^6.5.5: - version "6.12.3" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706" - integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA== +acorn-jsx@^5.2.0: + version "5.3.1" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.1.tgz#fc8661e11b7ac1539c47dbfea2e72b3af34d267b" + integrity sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng== + +acorn@^7.4.0: + version "7.4.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" + integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== + +ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== dependencies: fast-deep-equal "^3.1.1" fast-json-stable-stringify "^2.0.0" json-schema-traverse "^0.4.1" uri-js "^4.2.2" -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, 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-regex@^3.0.0: version "3.0.0" @@ -324,6 +446,11 @@ ansi-regex@^4.1.0: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -332,13 +459,20 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: color-convert "^1.9.0" ansi-styles@^4.1.0: - version "4.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" - integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: - "@types/color-name" "^1.1.1" color-convert "^2.0.1" +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + arg@^4.1.0: version "4.1.3" resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" @@ -351,16 +485,21 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" -argv-split@^2.0.1: +argparse@^2.0.1: version "2.0.1" - resolved "https://registry.yarnpkg.com/argv-split/-/argv-split-2.0.1.tgz#be264117790dbd5ccd63ec3f449a1804814ac4c5" - integrity sha1-viZBF3kNvVzNY+w/RJoYBIFKxMU= + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== array-flatten@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + asn1@~0.2.3: version "0.2.4" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" @@ -378,6 +517,11 @@ assertion-error@^1.1.0: resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +astral-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-1.0.0.tgz#6c8c3fb827dd43ee3918f27b82782ab7658a6fd9" + integrity sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg== + async@^3.1.0: version "3.2.0" resolved "https://registry.yarnpkg.com/async/-/async-3.2.0.tgz#b3a2685c5ebb641d3de02d161002c60fc9f85720" @@ -388,27 +532,22 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= -atob-lite@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/atob-lite/-/atob-lite-2.0.0.tgz#0fef5ad46f1bd7a8502c65727f0367d5ee43d696" - integrity sha1-D+9a1G8b16hQLGVyfwNn1e5D1pY= - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= aws4@^1.8.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.0.tgz#a17b3a8ea811060e74d47d306122400ad4497ae2" - integrity sha512-3YDiu347mtVtjpyV3u5kVqQLP242c06zwDOgpeRnybmXlYYsLbtTrUBUm8i8srONt+FWobl5aibnU1030PeeuA== + version "1.11.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" + integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== -axios@^0.19.2: - version "0.19.2" - resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27" - integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA== +axios@^0.21.0: + version "0.21.0" + resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.0.tgz#26df088803a2350dff2c27f96fef99fe49442aca" + integrity sha512-fmkJBknJKoZwem3/IKSSLpkdNXZeBu5Q7GA/aRsr2btgrptmSCxi2oFjZHqGdK9DoTil9PIHlPIZw2EcRJXRvw== dependencies: - follow-redirects "1.5.10" + follow-redirects "^1.10.0" balanced-match@^1.0.0: version "1.0.0" @@ -429,11 +568,16 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -before-after-hook@^2.0.0: +before-after-hook@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.1.0.tgz#b6c03487f44e24200dd30ca5e6a1979c5d2fb635" integrity sha512-IWIbu7pMqyw3EAJHzzHbWa85b6oud/yfKYg5rqB5hNE8CeMi3nX+2C2sj0HswfblST86hpVEOAb9x34NZd6P7A== +binary-extensions@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + bluebird@^3.5.0: version "3.7.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" @@ -463,7 +607,7 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -braces@^3.0.1: +braces@^3.0.1, 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== @@ -475,11 +619,6 @@ browser-stdout@1.3.1: resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== -btoa-lite@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/btoa-lite/-/btoa-lite-1.0.0.tgz#337766da15801210fdd956c22e9c6891ab9d0337" - integrity sha1-M3dm2hWAEhD92VbCLpxokaudAzc= - buffer-equal-constant-time@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819" @@ -490,21 +629,26 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== -builtin-modules@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= - bytes@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + camelcase@^5.0.0: 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.2.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -522,7 +666,7 @@ chai@^4.2.0: pathval "^1.1.0" type-detect "^4.0.5" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2: +chalk@^2.0.0, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -531,10 +675,10 @@ chalk@^2.0.0, chalk@^2.0.1, chalk@^2.3.0, chalk@^2.4.2: escape-string-regexp "^1.0.5" supports-color "^5.3.0" -chalk@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" - integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== +chalk@^4.0.0, chalk@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== dependencies: ansi-styles "^4.1.0" supports-color "^7.1.0" @@ -544,6 +688,21 @@ check-error@^1.0.2: resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" integrity sha1-V00xLt2Iu13YkS6Sht1sCu1KrII= +chokidar@3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== + 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.1.2" + cliui@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" @@ -583,9 +742,9 @@ color-name@^1.0.0, color-name@~1.1.4: integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== color-string@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" - integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== + version "1.5.4" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.4.tgz#dd51cd25cfee953d138fe4002372cc3d0e504cb6" + integrity sha512-57yF5yt8Xa3czSEW1jfQDE79Idk0+AkN/4KWad6tbdxUmAs3MvjxlWSWD4deYytcRfoZ9nhKyFl1kj5tBvidbw== dependencies: color-name "^1.0.0" simple-swizzle "^0.2.2" @@ -618,11 +777,6 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@^2.12.1: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -655,16 +809,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0: resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= -cross-spawn@^6.0.0: - version "6.0.5" - resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" - integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== dependencies: - nice-try "^1.0.4" - path-key "^2.0.1" - semver "^5.5.0" - shebang-command "^1.2.0" - which "^1.2.9" + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" dashdash@^1.12.0: version "1.14.1" @@ -680,32 +832,30 @@ debug@2.6.9: 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== +debug@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== dependencies: - ms "^2.1.1" + 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== +debug@^4.0.1, debug@^4.1.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== dependencies: - ms "2.0.0" - -debug@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" - integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== - dependencies: - ms "^2.1.1" + ms "2.1.2" decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +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== + deep-eql@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" @@ -713,12 +863,10 @@ deep-eql@^3.0.1: dependencies: type-detect "^4.0.0" -define-properties@^1.1.2, define-properties@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== - dependencies: - object-keys "^1.0.12" +deep-is@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" + integrity sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ= delayed-stream@~1.0.0: version "1.0.0" @@ -750,44 +898,54 @@ destroy@~1.0.4: resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= -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@^4.0.1: +diff@4.0.2, diff@^4.0.1: version "4.0.2" resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== -dom-serializer@^0.2.1: - version "0.2.2" - resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" - integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +dom-serializer@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.1.0.tgz#5f7c828f1bfc44887dc2a315ab5c45691d544b58" + integrity sha512-ox7bvGXt2n+uLWtCRLybYx60IrOlWL/aCebWJk1T0d4m3y2tzf4U3ij9wBMUb6YJZpz06HCCYuyCDveE2xXmzQ== dependencies: domelementtype "^2.0.1" + domhandler "^3.0.0" entities "^2.0.0" domelementtype@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" - integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + version "2.0.2" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.2.tgz#f3b6e549201e46f588b59463dd77187131fe6971" + integrity sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA== -domhandler@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.0.0.tgz#51cd13efca31da95bbb0c5bee3a48300e333b3e9" - integrity sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw== +domhandler@^3.0.0, domhandler@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-3.3.0.tgz#6db7ea46e4617eb15cf875df68b2b8524ce0037a" + integrity sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA== dependencies: domelementtype "^2.0.1" domutils@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.1.0.tgz#7ade3201af43703fde154952e3a868eb4b635f16" - integrity sha512-CD9M0Dm1iaHfQ1R/TI+z3/JWp/pgub0j4jIQKH89ARR4ATAV2nbaOQS5XxU9maJP5jHaPdDDQSEHuE2UmpUTKg== + version "2.4.2" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.4.2.tgz#7ee5be261944e1ad487d9aa0616720010123922b" + integrity sha512-NKbgaM8ZJOecTZsIzW5gSuplsX2IWW2mIK7xVr8hTQF2v1CJWTmLZ1HOCh5sH+IzVPAGE5IucooOkvwBRAdowA== dependencies: - dom-serializer "^0.2.1" + dom-serializer "^1.0.1" domelementtype "^2.0.1" - domhandler "^3.0.0" + domhandler "^3.3.0" ecc-jsbn@~0.1.1: version "0.1.2" @@ -824,82 +982,162 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= -end-of-stream@^1.1.0: - version "1.4.4" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" - integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== +enquirer@^2.3.5: + version "2.3.6" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" + integrity sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg== dependencies: - once "^1.4.0" + ansi-colors "^4.1.1" entities@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.1.0.tgz#992d3129cf7df6870b96c57858c249a120f8b8b5" + integrity sha512-hCx1oky9PFrJ611mf0ifBLBRW8lUUVRlFolb5gWRfIELabBlbp9xZvrqZLZAs+NxFnbfQoeGd8wDkygjg7U85w== + +entities@~2.0.0: version "2.0.3" resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.3.tgz#5c487e5742ab93c15abb5da22759b8590ec03b7f" integrity sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ== -entities@~1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" - integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== - -es-abstract@^1.17.0-next.1, es-abstract@^1.17.5: - version "1.17.6" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.6.tgz#9142071707857b2cacc7b89ecb670316c3e2d52a" - integrity sha512-Fr89bON3WFyUi5EvAeI48QTWX0AyekGgLA8H+c+7fbfCkJwRWRMLd8CQedNEyJuoYYhmtEqY92pgte1FAhBlhw== - dependencies: - es-to-primitive "^1.2.1" - function-bind "^1.1.1" - has "^1.0.3" - has-symbols "^1.0.1" - is-callable "^1.2.0" - is-regex "^1.1.0" - object-inspect "^1.7.0" - object-keys "^1.1.1" - object.assign "^4.1.0" - string.prototype.trimend "^1.0.1" - string.prototype.trimstart "^1.0.1" - -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== - dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" - escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.5: +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 sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +eslint-plugin-mocha@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-mocha/-/eslint-plugin-mocha-8.0.0.tgz#7ec5d228bcb3735301701dfbc3376320a1ca3791" + integrity sha512-n67etbWDz6NQM+HnTwZHyBwz/bLlYPOxUbw7bPuCyFujv7ZpaT/Vn6KTAbT02gf7nRljtYIjWcTxK/n8a57rQQ== + dependencies: + eslint-utils "^2.1.0" + ramda "^0.27.1" + +eslint-scope@^5.0.0, eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-utils@^2.0.0, eslint-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-2.1.0.tgz#d2de5e03424e707dc10c74068ddedae708741b27" + integrity sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg== + dependencies: + eslint-visitor-keys "^1.1.0" + +eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz#30ebd1ef7c2fdff01c3a4f151044af25fab0523e" + integrity sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ== + +eslint-visitor-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.0.0.tgz#21fdc8fbcd9c795cc0321f0563702095751511a8" + integrity sha512-QudtT6av5WXels9WjIM7qz1XD1cWGvX4gGXvp/zBn9nXG02D0utdU3Em2m/QjTnrsk6bBjmCygl3rmj118msQQ== + +eslint@^7.14.0: + version "7.14.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-7.14.0.tgz#2d2cac1d28174c510a97b377f122a5507958e344" + integrity sha512-5YubdnPXrlrYAFCKybPuHIAH++PINe1pmKNc5wQRB9HSbqIK1ywAnntE3Wwua4giKu0bjligf1gLF6qxMGOYRA== + dependencies: + "@babel/code-frame" "^7.0.0" + "@eslint/eslintrc" "^0.2.1" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.0.1" + doctrine "^3.0.0" + enquirer "^2.3.5" + eslint-scope "^5.1.1" + eslint-utils "^2.1.0" + eslint-visitor-keys "^2.0.0" + espree "^7.3.0" + esquery "^1.2.0" + esutils "^2.0.2" + file-entry-cache "^5.0.1" + functional-red-black-tree "^1.0.1" + glob-parent "^5.0.0" + globals "^12.1.0" + ignore "^4.0.6" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-yaml "^3.13.1" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash "^4.17.19" + minimatch "^3.0.4" + natural-compare "^1.4.0" + optionator "^0.9.1" + progress "^2.0.0" + regexpp "^3.1.0" + semver "^7.2.1" + strip-ansi "^6.0.0" + strip-json-comments "^3.1.0" + table "^5.2.3" + text-table "^0.2.0" + v8-compile-cache "^2.0.3" + +espree@^7.3.0: + version "7.3.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-7.3.0.tgz#dc30437cf67947cf576121ebd780f15eeac72348" + integrity sha512-dksIWsvKCixn1yrEXO8UosNSxaDoSYpq9reEjZSbHLpT5hpaCAKTLBwq0RHtLrIr+c0ByiYzWT8KTMRzoRCNlw== + dependencies: + acorn "^7.4.0" + acorn-jsx "^5.2.0" + eslint-visitor-keys "^1.3.0" + esprima@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +esquery@^1.2.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.3.1.tgz#b78b5828aa8e214e29fb74c4d5b752e1c033da57" + integrity sha512-olpvt9QG0vniUBZspVRN6lwB7hOZoTRtT+jzR+tS4ffYx2mzbw+z0XCOk44aaLYKApNX5nMm+E+P6o25ip/DHQ== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.2.0.tgz#307df42547e6cc7324d3cf03c155d5cdb8c53880" + integrity sha512-BxbNGGNm0RyRYvUdHpIwv9IWzeM9XClbOxwoATuFdOE7ZE6wHL+HQ5T8hoPM+zHvmKzzsEqhgy0GrQ5X13afiQ== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= -execa@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" - integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== - dependencies: - cross-spawn "^6.0.0" - get-stream "^4.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" - express@^4.17.1: version "4.17.1" resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" @@ -956,21 +1194,52 @@ fast-deep-equal@^3.1.1: resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== +fast-glob@^3.1.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.4.tgz#d20aefbf99579383e7f3cc66529158c9b98554d3" + integrity sha512-kr/Oo6PX51265qeuCYsyGypiO5uJFgBS0jksyG7FUeCyQzNwYnzrNIMR1NXfkZXsMYXYLRAHgISHBz8gQcxKHQ== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + picomatch "^2.2.1" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= + fast-safe-stringify@^2.0.4: version "2.0.7" resolved "https://registry.yarnpkg.com/fast-safe-stringify/-/fast-safe-stringify-2.0.7.tgz#124aa885899261f68aedb42a7c080de9da608743" integrity sha512-Utm6CdzT+6xsDk2m8S6uL8VHxNwI6Jub+e9NYTcAms28T84pTa25GJQV9j0CY0N1rM8hK4x6grpF2BQf+2qwVA== +fastq@^1.6.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.9.0.tgz#e16a72f338eaca48e91b5c23593bcc2ef66b7947" + integrity sha512-i7FVWL8HhVY+CTkwFxkN2mk3h+787ixS5S63eb78diVRc1MCssarHq3W5cj0av7YDSwmaV928RNag+U1etRQ7w== + dependencies: + reusify "^1.0.4" + fecha@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/fecha/-/fecha-4.2.0.tgz#3ffb6395453e3f3efff850404f0a59b6747f5f41" integrity sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg== +file-entry-cache@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-5.0.1.tgz#ca0f6efa6dd3d561333fb14515065c2fafdf439c" + integrity sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g== + dependencies: + flat-cache "^2.0.1" + fill-range@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" @@ -991,31 +1260,49 @@ finalhandler@~1.1.2: statuses "~1.5.0" unpipe "~1.0.0" -find-up@3.0.0, find-up@^3.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" -flat@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/flat/-/flat-4.1.0.tgz#090bec8b05e39cba309747f1d588f04dbaf98db2" - integrity sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw== +flat-cache@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" + integrity sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA== dependencies: - is-buffer "~2.0.3" + flatted "^2.0.0" + rimraf "2.6.3" + write "1.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@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" + integrity sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA== fn.name@1.x.x: version "1.1.0" resolved "https://registry.yarnpkg.com/fn.name/-/fn.name-1.1.0.tgz#26cad8017967aea8731bc42961d04a3d5988accc" integrity sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw== -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" +follow-redirects@^1.10.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.13.0.tgz#b42e8d93a2a7eea5ed88633676d6597bc8e384db" + integrity sha512-aq6gF1BEKje4a9i9+5jimNFIpq4Q1WiwBToeRK5NvZBd/TRsmW8BsJfOEGkr76TbOyPVD3OVDN910EcUNtRYEA== forever-agent@~0.6.1: version "0.6.1" @@ -1046,10 +1333,15 @@ fs.realpath@^1.0.0: resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +fsevents@~2.1.2: + version "2.1.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= get-caller-file@^2.0.1: version "2.0.5" @@ -1061,13 +1353,6 @@ get-func-name@^2.0.0: resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" integrity sha1-6td0q+5y4gQJQzoGY2YCPdaIekE= -get-stream@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" - integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== - dependencies: - pump "^3.0.0" - getpass@^0.1.1: version "0.1.7" resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" @@ -1075,24 +1360,19 @@ getpass@^0.1.1: dependencies: assert-plus "^1.0.0" +glob-parent@^5.0.0, glob-parent@^5.1.0, glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + glob-to-regexp@^0.4.1: version "0.4.1" resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@7.1.3: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.1.1: +glob@7.1.6, glob@^7.1.3: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -1104,6 +1384,25 @@ glob@^7.1.1: once "^1.3.0" path-is-absolute "^1.0.0" +globals@^12.1.0: + version "12.4.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-12.4.0.tgz#a18813576a41b00a24a97e7f815918c2e19925f8" + integrity sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg== + dependencies: + type-fest "^0.8.1" + +globby@^11.0.1: + version "11.0.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.1.tgz#9a2bf107a068f3ffeabc49ad702c79ede8cfd357" + integrity sha512-iH9RmgwCmUJHi2z5o2l3eTtGBtXek1OYlHrbcxOYugyHLmAsZrPj43OtHThd62Buh/Vv6VyCBD2bdyWcGNQqoQ== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.1.1" + ignore "^5.1.4" + merge2 "^1.3.0" + slash "^3.0.0" + graceful-fs@^4.1.3: version "4.2.4" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb" @@ -1120,11 +1419,11 @@ har-schema@^2.0.0: integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= har-validator@~5.1.3: - version "5.1.3" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" - integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + version "5.1.5" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" + integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== dependencies: - ajv "^6.5.5" + ajv "^6.12.3" har-schema "^2.0.0" has-flag@^3.0.0: @@ -1137,18 +1436,6 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-symbols@^1.0.0, has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - hash.js@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -1162,6 +1449,11 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +highlight.js@^9.7.0: + version "9.18.5" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-9.18.5.tgz#d18a359867f378c138d6819edfc2a8acd5f29825" + integrity sha512-a5bFyofd/BHCX52/8i8uJkjr9DYwXIPnM/plwI6W7ezItLGqzt7X2G2nXuYSfsIJdkwwj/g9DG1LkcGJI/dDoA== + htmlencode@^0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/htmlencode/-/htmlencode-0.0.4.tgz#f7e2d6afbe18a87a78e63ba3308e753766740e3f" @@ -1215,6 +1507,29 @@ iconv-lite@0.4.24: dependencies: safer-buffer ">= 2.1.2 < 3" +ignore@^4.0.6: + version "4.0.6" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-4.0.6.tgz#750e3db5862087b4737ebac8207ffd1ef27b25fc" + integrity sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg== + +ignore@^5.1.4: + version "5.1.8" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.8.tgz#f150a8b50a34289b33e22f5889abd4d8016f0e57" + integrity sha512-BMpfD7PpiETpBl/A6S498BaIJ6Y/ABT93ETbby2fP00v4EbvPBXWEoaR1UBPKs3iR53pJY7EtZk5KACI57i1Uw== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.2.2" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.2.tgz#fc129c160c5d68235507f4331a6baad186bdbc3e" + integrity sha512-cTPNrlvJT6twpYy+YmKUKrTSjWFs3bjYjAhCwm+z4EOCubZxAuO+hHpRN64TqjEaYSHs7tJAE0w1CKMGmsG/lw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -1233,17 +1548,18 @@ inherits@2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= -ioredis@^4.14.0: - version "4.17.3" - resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.17.3.tgz#9938c60e4ca685f75326337177bdc2e73ae9c9dc" - integrity sha512-iRvq4BOYzNFkDnSyhx7cmJNOi1x/HWYe+A4VXHBu4qpwJaGT1Mp+D2bVGJntH9K/Z/GeOM/Nprb8gB3bmitz1Q== +ioredis@^4.19.2: + version "4.19.2" + resolved "https://registry.yarnpkg.com/ioredis/-/ioredis-4.19.2.tgz#e3eab394c653cea5aea07c0c784d8c772dce8801" + integrity sha512-SZSIwMrbd96b7rJvJwyTWSP6XQ0m1kAIIqBnwglJKrIJ6na7TeY4F2EV2vDY0xm/fLrUY8cEg81dR7kVFt2sKA== dependencies: cluster-key-slot "^1.1.0" debug "^4.1.1" denque "^1.1.0" lodash.defaults "^4.2.0" lodash.flatten "^4.4.0" - redis-commands "1.5.0" + p-map "^2.1.0" + redis-commands "1.6.0" redis-errors "^1.2.0" redis-parser "^3.0.0" standard-as-callback "^2.0.1" @@ -1258,65 +1574,55 @@ is-arrayish@^0.3.1: resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== -is-buffer@~2.0.3: - version "2.0.4" - resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" - integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== +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-callable@^1.1.4, is-callable@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.0.tgz#83336560b54a38e35e3a2df7afd0454d691468bb" - integrity sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw== - -is-date-object@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" - integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== -is-plain-object@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" - integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== +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@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" + integrity sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q== is-promise@^2.1.0: version "2.2.2" resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== -is-regex@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.0.tgz#ece38e389e490df0dc21caea2bd596f987f767ff" - integrity sha512-iI97M8KTWID2la5uYXlkbSDQIg4F6o1sYboZKKTDpnDQMLtUL86zxhgDet3Q2SriaYsyGqZ6Mn2SjbRKeLHdqw== - dependencies: - has-symbols "^1.0.1" - -is-stream@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= - is-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== -is-symbol@^1.0.2: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" - integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== - dependencies: - has-symbols "^1.0.1" - is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -1342,15 +1648,7 @@ js-tokens@^4.0.0: resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -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.13.1: +js-yaml@3.14.0, js-yaml@^3.13.1: version "3.14.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== @@ -1373,6 +1671,11 @@ json-schema@0.2.3: resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= + json-stringify-safe@~5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" @@ -1426,10 +1729,18 @@ kuler@^2.0.0: resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== -linkify-it@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-2.2.0.tgz#e3b54697e78bf915c70a38acd78fd09e0058b1cf" - integrity sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw== +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +linkify-it@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/linkify-it/-/linkify-it-3.0.2.tgz#f55eeb8bc1d3ae754049e124ab3bb56d97797fb8" + integrity sha512-gDBO4aHNZS6coiZCKVhSNh43F9ioIL4JwRjLZPkoLIY4yZFwg264Y5lu2x6rb1Js42Gh6Yqm2f6L2AJcnkzinQ== dependencies: uc.micro "^1.0.1" @@ -1441,6 +1752,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash.defaults@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -1451,11 +1769,6 @@ lodash.flatten@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= -lodash.get@^4.4.2: - version "4.4.2" - resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" - integrity sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk= - lodash.includes@^4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f" @@ -1491,32 +1804,22 @@ lodash.once@^4.0.0: resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac" integrity sha1-DdOXEhPHxW34gJd9UEyI+0cal6w= -lodash.set@^4.3.2: - version "4.3.2" - resolved "https://registry.yarnpkg.com/lodash.set/-/lodash.set-4.3.2.tgz#d8757b1da807dde24816b0d6a84bea1a76230b23" - integrity sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM= - lodash.toarray@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= -lodash.uniq@^4.5.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" - integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= +lodash@4, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19: + version "4.17.20" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.20.tgz#b44a9b6297bcb698f1c51a3545a2b3b368d59c52" + integrity sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA== -lodash@4, lodash@^4.17.15: - version "4.17.19" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b" - integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ== - -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" logform@^2.2.0: version "2.2.0" @@ -1540,13 +1843,6 @@ lowdb@^1.0.0: pify "^3.0.0" steno "^0.4.1" -lru-cache@^5.1.1: - version "5.1.1" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" - integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== - dependencies: - yallist "^3.0.2" - lru-cache@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" @@ -1554,45 +1850,40 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -macos-release@^2.2.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/macos-release/-/macos-release-2.4.0.tgz#837b39fc01785c3584f103c5599e0f0c8068b49e" - integrity sha512-ko6deozZYiAkqa/0gmcsz+p4jSy3gY7/ZsCEokPaYd8k+6/aXGkiTgr61+Owup7Sf+xjqW8u2ElhoM9SEcEfuA== - make-error@^1.1.1: version "1.3.6" resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== -markdown-it@^9.0.1: - version "9.1.0" - resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-9.1.0.tgz#df9601c168568704d554b1fff9af0c5b561168d9" - integrity sha512-xHKG4C8iPriyfu/jc2hsCC045fKrMQ0VexX2F1FGYiRxDxqMB2aAhF8WauJ3fltn2kb90moGBkiiEdooGIg55w== +markdown-it@^12.0.2: + version "12.0.2" + resolved "https://registry.yarnpkg.com/markdown-it/-/markdown-it-12.0.2.tgz#4401beae8df8aa2221fc6565a7188e60a06ef0ed" + integrity sha512-4Lkvjbv2kK+moL9TbeV+6/NHx+1Q+R/NIdUlFlkqkkzUcTod4uiyTJRiBidKR9qXSdkNFkgv+AELY8KN9vSgVA== dependencies: - argparse "^1.0.7" - entities "~1.1.1" - linkify-it "^2.0.0" + argparse "^2.0.1" + entities "~2.0.0" + linkify-it "^3.0.1" mdurl "^1.0.1" uc.micro "^1.0.5" -matrix-bot-sdk@^0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/matrix-bot-sdk/-/matrix-bot-sdk-0.5.4.tgz#8c26bef826bd0b3fc9b693c8d07b52c30d843fd7" - integrity sha512-nUAE1WW7ast+Xsfux1+qBPmKSY6OG0RoZfeh0WfMP42JW6GRnNiY3hq7aiifomnJAMASZ6EwkdHS3ChWpIRYzg== +matrix-bot-sdk@^0.5.8: + version "0.5.8" + resolved "https://registry.yarnpkg.com/matrix-bot-sdk/-/matrix-bot-sdk-0.5.8.tgz#84861208e410accc6bc9533991c2bc48162d528e" + integrity sha512-YgtiAqJsX6uauB0WotJSukbnPE2OtaWvRCAtiWGTYn374QD350U7DYHpFiSbM/X1DpB7s7hbCNZglKyuBk8c/w== dependencies: - "@types/express" "^4.17.2" - chalk "^3.0.0" + "@types/express" "^4.17.7" + chalk "^4.1.0" express "^4.17.1" glob-to-regexp "^0.4.1" hash.js "^1.1.7" htmlencode "^0.0.4" lowdb "^1.0.0" - lru-cache "^5.1.1" - mkdirp "^0.5.1" - morgan "^1.9.1" - request "^2.88.0" - request-promise "^4.2.5" - sanitize-html "^1.20.1" + lru-cache "^6.0.0" + mkdirp "^1.0.4" + morgan "^1.10.0" + request "^2.88.2" + request-promise "^4.2.6" + sanitize-html "^1.27.2" mdurl@^1.0.1: version "1.0.1" @@ -1609,6 +1900,11 @@ merge-descriptors@1.0.1: resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -1639,7 +1935,7 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== -mime@^2.4.4: +mime@^2.4.6: version "2.4.6" resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.6.tgz#e5b407c90db442f2beb5b162373d07b69affa4d1" integrity sha512-RZKhC3EmpBchfTGBVb8fb+RL2cWyw/32lshnsETttkBAyAUXSGHxbEJWWRXc751DrIxG1q04b8QwMbAwkRPpUA== @@ -1661,13 +1957,6 @@ minimist@^1.2.5: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== -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.1: version "0.5.5" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" @@ -1675,36 +1964,43 @@ mkdirp@^0.5.1: dependencies: minimist "^1.2.5" -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== +mkdirp@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" + integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== + +mocha@^8.2.1: + version "8.2.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.2.1.tgz#f2fa68817ed0e53343d989df65ccd358bc3a4b39" + integrity sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w== 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.4.3" + debug "4.2.0" + diff "4.0.2" + 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 "3.14.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.2" + nanoid "3.1.12" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "7.2.0" + which "2.0.2" wide-align "1.1.3" + workerpool "6.0.2" yargs "13.3.2" yargs-parser "13.1.2" - yargs-unparser "1.6.0" + yargs-unparser "2.0.0" -morgan@^1.9.1: +morgan@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/morgan/-/morgan-1.10.0.tgz#091778abc1fc47cd3509824653dae1faab6b17d7" integrity sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ== @@ -1725,21 +2021,26 @@ ms@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.1: +ms@2.1.2, ms@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +nanoid@3.1.12: + version "3.1.12" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654" + integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= + negotiator@0.6.2: version "0.6.2" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== -nice-try@^1.0.4: - version "1.0.5" - resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" - integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== - node-emoji@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" @@ -1747,64 +2048,21 @@ node-emoji@^1.10.0: dependencies: lodash.toarray "^4.4.0" -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-fetch@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052" + integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw== -node-fetch@^2.3.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.0.tgz#e633456386d4aa55863f676a7ab0daa8fdecb0fd" - integrity sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA== - -npm-run-path@^2.0.0: - version "2.0.2" - resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" - integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= - dependencies: - path-key "^2.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== oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== -object-inspect@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.8.0.tgz#df807e5ecf53a609cc6bfe93eac3cc7be5b3a9d0" - integrity sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA== - -object-keys@^1.0.11, object-keys@^1.0.12, 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== - -object.assign@4.1.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.getownpropertydescriptors@^2.0.3: - version "2.1.0" - resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" - integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.0-next.1" - -octokit-pagination-methods@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz#cf472edc9d551055f9ef73f6e42b4dbb4c80bea4" - integrity sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ== - on-finished@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" @@ -1817,7 +2075,7 @@ on-headers@~1.0.2: resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== -once@^1.3.0, once@^1.3.1, once@^1.4.0: +once@^1.3.0, once@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= @@ -1831,18 +2089,17 @@ one-time@^1.0.0: dependencies: fn.name "1.x.x" -os-name@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/os-name/-/os-name-3.1.0.tgz#dec19d966296e1cd62d701a5a66ee1ddeae70801" - integrity sha512-h8L+8aNjNcMpo/mAIBPn5PXCM16iyPGjHNWo6U1YO8sJTMHtEtyczI6QJnLoplswm6goopQkqc7OAnjhWcugVg== +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== dependencies: - macos-release "^2.2.0" - windows-release "^3.1.0" - -p-finally@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" - integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" p-limit@^2.0.0: version "2.3.0" @@ -1851,6 +2108,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + p-locate@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" @@ -1858,11 +2122,35 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + 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== +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-srcset@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/parse-srcset/-/parse-srcset-1.0.2.tgz#f2bd221f6cc970a938d88556abc589caaaa2bde1" + integrity sha1-8r0iH2zJcKk42IVWq8WJyqqiveE= + parseurl@~1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" @@ -1873,26 +2161,31 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= -path-key@^2.0.0, path-key@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" - integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= - -path-parse@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== path-to-regexp@0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-type@^4.0.0: + version "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.0: version "1.1.0" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" @@ -1903,7 +2196,7 @@ performance-now@^2.1.0: resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= -picomatch@^2.0.5: +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.2.1: version "2.2.2" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== @@ -1914,19 +2207,29 @@ pify@^3.0.0: integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= postcss@^7.0.27: - version "7.0.32" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.32.tgz#4310d6ee347053da3433db2be492883d62cec59d" - integrity sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw== + version "7.0.35" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.35.tgz#d2be00b998f7f211d8a276974079f2e92b970e24" + integrity sha512-3QT8bBJeX/S5zKTTjTCIjRF3If4avAT6kqxcASlTWEtAFCb9NH0OUxNDfgZSWdP5fJnBYCMEWkIFfWeugjzYMg== dependencies: chalk "^2.4.2" source-map "^0.6.1" supports-color "^6.1.0" +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== +progress@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" + integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== + proxy-addr@~2.0.5: version "2.0.6" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" @@ -1940,14 +2243,6 @@ psl@^1.1.28: resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== -pump@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" - integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== - dependencies: - end-of-stream "^1.1.0" - once "^1.3.1" - punycode@^2.1.0, punycode@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" @@ -1963,6 +2258,18 @@ qs@~6.5.2: resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== +ramda@^0.27.1: + version "0.27.1" + resolved "https://registry.yarnpkg.com/ramda/-/ramda-0.27.1.tgz#66fc2df3ef873874ffc2da6aa8984658abacf5c9" + integrity sha512-PgIdVpn5y5Yns8vqb8FzBUEYn98V3xcPgawAkkgj0YJ0qDsnHCiNmZYfOGMgOvoB0eWFLpYbhxUR3mxfDIMvpw== + +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: + safe-buffer "^5.1.0" + range-parser@~1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" @@ -2000,10 +2307,17 @@ readable-stream@^3.4.0: string_decoder "^1.1.1" util-deprecate "^1.0.1" -redis-commands@1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.5.0.tgz#80d2e20698fe688f227127ff9e5164a7dd17e785" - integrity sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg== +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.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/redis-commands/-/redis-commands-1.6.0.tgz#36d4ca42ae9ed29815cdb30ad9f97982eba1ce23" + integrity sha512-2jnZ0IkjZxvguITjFTrGiLyzQZcTvaw8DAaCXxZq/dsHXz7KfMQ3OUJy7Tz9vnRtZRVz6VRCPDvruvU8Ts44wQ== redis-errors@^1.0.0, redis-errors@^1.2.0: version "1.2.0" @@ -2022,24 +2336,29 @@ reflect-metadata@^0.1.13: resolved "https://registry.yarnpkg.com/reflect-metadata/-/reflect-metadata-0.1.13.tgz#67ae3ca57c972a2aa1642b10fe363fe32d49dc08" integrity sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg== -request-promise-core@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.3.tgz#e9a3c081b51380dfea677336061fea879a829ee9" - integrity sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ== - dependencies: - lodash "^4.17.15" +regexpp@^3.0.0, regexpp@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.1.0.tgz#206d0ad0a5648cffbdb8ae46438f3dc51c9f78e2" + integrity sha512-ZOIzd8yVsQQA7j8GCSlPGXwg5PfmA1mrq0JP4nGhh54LaKN3xdai/vHUDu74pKwV8OxseMS65u2NImosQcSD0Q== -request-promise@^4.2.5: - version "4.2.5" - resolved "https://registry.yarnpkg.com/request-promise/-/request-promise-4.2.5.tgz#186222c59ae512f3497dfe4d75a9c8461bd0053c" - integrity sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg== +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.6: + 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.3" + request-promise-core "1.1.4" stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.88.0: +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== @@ -2075,19 +2394,34 @@ 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@^1.3.2: - version "1.17.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.17.0.tgz#b25941b54968231cc2d1bb76a79cb7f2c0bf8444" - integrity sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w== +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== + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" + integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== dependencies: - path-parse "^1.0.6" + glob "^7.1.3" + +run-parallel@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.10.tgz#60a51b2ae836636c81377df16cb107351bcd13ef" + integrity sha512-zb/1OuZ6flOlH6tQyMPUrE3x3Ulxjlo9WIVXR4yVYi4H9UXQaeIsPbLn2R3O3vQCnDKkAl2qHiuocKKX4Tz/Sw== safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: +safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -2097,21 +2431,26 @@ safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== -sanitize-html@^1.20.1: - version "1.27.1" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.27.1.tgz#ce147951aa3defba13448e2ca8a4e18d8f2e2cd7" - integrity sha512-C+N7E+7ikYaLHdb9lEkQaFOgmj+9ddZ311Ixs/QsBsoLD411/vdLweiFyGqrswUVgLqagOS5NCDxcEPH7trObQ== +sanitize-html@^1.27.2: + version "1.27.5" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-1.27.5.tgz#6c8149462adb23e360e1bb71cc0bae7f08c823c7" + integrity sha512-M4M5iXDAUEcZKLXkmk90zSYWEtk5NH3JmojQxKxV371fnMh+x9t1rqdmXaGoyEHw3z/X/8vnFhKjGL5xFGOJ3A== dependencies: htmlparser2 "^4.1.0" lodash "^4.17.15" + parse-srcset "^1.0.2" postcss "^7.0.27" - srcset "^2.0.1" -semver@^5.3.0, semver@^5.5.0, semver@^5.6.0, semver@^5.7.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== +semver@^7.2.1, semver@^7.3.2: + version "7.3.2" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.2.tgz#604962b052b81ed0786aae84389ffba70ffd3938" + integrity sha512-OrOb32TeeambH6UrhtShmF7CRDqhL6/5XpPNp2DuRH6+9QLw/orhp72j87v8Qa1ScDkvrrBNpZcDejAirJmfXQ== + send@0.17.1: version "0.17.1" resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" @@ -2131,6 +2470,13 @@ send@0.17.1: range-parser "~1.2.1" statuses "~1.5.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.14.1: version "1.14.1" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" @@ -2151,22 +2497,17 @@ setprototypeof@1.1.1: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== -shebang-command@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" - integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: - shebang-regex "^1.0.0" + shebang-regex "^3.0.0" -shebang-regex@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" - integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= - -signal-exit@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" - integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== simple-swizzle@^0.2.2: version "0.2.2" @@ -2175,6 +2516,20 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +slice-ansi@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-2.1.0.tgz#cacd7693461a637a5788d92a7dd4fba068e81636" + integrity sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ== + dependencies: + ansi-styles "^3.2.0" + astral-regex "^1.0.0" + is-fullwidth-code-point "^2.0.0" + source-map-support@^0.5.17: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -2193,11 +2548,6 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= -srcset@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/srcset/-/srcset-2.0.1.tgz#8f842d357487eb797f413d9c309de7a5149df5ac" - integrity sha512-00kZI87TdRKwt+P8jj8UZxbfp7mK2ufxcIMWvhAOZNJTRROimpHeruWrGvCZneiuVDLqdyHefVp748ECTnyUBQ== - sshpk@^1.7.0: version "1.16.1" resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" @@ -2240,6 +2590,11 @@ steno@^0.4.1: dependencies: graceful-fs "^4.1.3" +string-argv@v0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" + integrity sha512-a1uQGz7IyVy9YwhqjZIZu1c8JO8dNIe20xBmSS6qu9kv++k3JGzCVmprbNN5Kn+BgzD5E7YYwg1CcjuJMRNsvg== + "string-width@^1.0.2 || 2": version "2.1.1" resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" @@ -2257,22 +2612,6 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" -string.prototype.trimend@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz#85812a6b847ac002270f5808146064c995fb6913" - integrity sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - -string.prototype.trimstart@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz#14af6d9f34b053f7cfc89b72f8f2ee14b9039a54" - integrity sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw== - dependencies: - define-properties "^1.1.3" - es-abstract "^1.17.5" - string_decoder@^1.1.1: version "1.3.0" resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" @@ -2301,22 +2640,24 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-eof@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= - -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 sha1-PFMZQukIwml8DsNEhYwobHygpgo= - -supports-color@6.0.0: +strip-ansi@^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== + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== dependencies: - has-flag "^3.0.0" + ansi-regex "^5.0.0" + +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== + +supports-color@7.2.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" supports-color@^5.3.0: version "5.5.0" @@ -2332,18 +2673,26 @@ supports-color@^6.1.0: dependencies: has-flag "^3.0.0" -supports-color@^7.1.0: - version "7.1.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" - integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== +table@^5.2.3: + version "5.4.6" + resolved "https://registry.yarnpkg.com/table/-/table-5.4.6.tgz#1292d19500ce3f86053b05f0e8e7e4a3bb21079e" + integrity sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug== dependencies: - has-flag "^4.0.0" + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" text-hex@1.0.x: version "1.0.0" resolved "https://registry.yarnpkg.com/text-hex/-/text-hex-1.0.0.tgz#69dc9c1b17446ee79a92bf5b884bb4b9127506f5" integrity sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg== +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -2369,10 +2718,10 @@ triple-beam@^1.2.0, triple-beam@^1.3.0: resolved "https://registry.yarnpkg.com/triple-beam/-/triple-beam-1.3.0.tgz#a595214c7298db8339eeeee083e4d10bd8cb8dd9" integrity sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw== -ts-node@^8.3.0: - version "8.10.2" - resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.10.2.tgz#eee03764633b1234ddd37f8db9ec10b75ec7fb8d" - integrity sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA== +ts-node@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-9.0.0.tgz#e7699d2a110cc8c0d3b831715e417688683460b3" + integrity sha512-/TqB4SnererCDR/vb4S/QvSZvzQMJN8daAslg7MeaiHvD8rDZsSfXmNeNumyZZzMned72Xoq/isQljYSt8Ynfg== dependencies: arg "^4.1.0" diff "^4.0.1" @@ -2380,34 +2729,15 @@ ts-node@^8.3.0: source-map-support "^0.5.17" yn "3.1.1" -tslib@^1.8.0, tslib@^1.8.1: - version "1.13.0" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043" - integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q== +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslint@^5.18.0: - version "5.20.1" - resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.20.1.tgz#e401e8aeda0152bc44dd07e614034f3f80c67b7d" - integrity sha512-EcMxhzCFt8k+/UP5r8waCf/lzmeSyVlqxqMEDQE7rWYiQky8KpIBz1JAoYXfROHrPZ1XXd43q8yQnULOLiBRQg== - dependencies: - "@babel/code-frame" "^7.0.0" - builtin-modules "^1.1.1" - chalk "^2.3.0" - commander "^2.12.1" - diff "^4.0.1" - glob "^7.1.1" - js-yaml "^3.13.1" - minimatch "^3.0.4" - mkdirp "^0.5.1" - resolve "^1.3.2" - semver "^5.3.0" - tslib "^1.8.0" - tsutils "^2.29.0" - -tsutils@^2.29.0: - version "2.29.0" - resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" - integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== +tsutils@^3.17.1: + version "3.17.1" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759" + integrity sha512-kzeQ5B8H3w60nFY2g8cJIuH7JDpsALXySGtwGJ0p2LSjLgay3NdIpqq5SoOBe46bKDW2iq25irHCr8wjomUS2g== dependencies: tslib "^1.8.1" @@ -2423,11 +2753,23 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + 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.8.1: + 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.17, type-is@~1.6.18: version "1.6.18" resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" @@ -2436,10 +2778,10 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typescript@^3.9.7: - version "3.9.7" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" - integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== +typescript@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.2.tgz#6369ef22516fe5e10304aae5a5c4862db55380e9" + integrity sha512-thGloWsGH3SOxv1SoY7QojKi0tc+8FnOmiarEGMbd/lar7QOEd3hvlx3Fp5y6FlDUGl9L+pd4n2e+oToGMmhRQ== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" @@ -2447,20 +2789,13 @@ uc.micro@^1.0.1, uc.micro@^1.0.5: integrity sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA== universal-github-app-jwt@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.0.2.tgz#9a7305e44b2a0eb565d83d11682eebe5be8bde8b" - integrity sha512-bJ3hVBdPREry3vob+JBOjXkO76QAQkYTIJvQ62Ja7XBSrKv6v6gHaRBWADddvS0HiLF0Q6lCK1kg4ZJrj/Kl9g== + version "1.1.0" + resolved "https://registry.yarnpkg.com/universal-github-app-jwt/-/universal-github-app-jwt-1.1.0.tgz#0abaa876101cdf1d3e4c546be2768841c0c1b514" + integrity sha512-3b+ocAjjz4JTyqaOT+NNBd5BtTuvJTxWElIoeHSVelUV9J3Jp7avmQTdLKCaoqi/5Ox2o/q+VK19TJ233rVXVQ== dependencies: "@types/jsonwebtoken" "^8.3.3" jsonwebtoken "^8.5.1" -universal-user-agent@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-4.0.1.tgz#fd8d6cb773a679a709e967ef8288a31fcc03e557" - integrity sha512-LnST3ebHwVL2aNe4mejI9IQh2HfZ1RLo8Io2HugSif8ekzD1TlWpHpColOB/eh8JHMLkGH3Akqf040I+4ylNxg== - dependencies: - os-name "^3.1.0" - universal-user-agent@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/universal-user-agent/-/universal-user-agent-6.0.0.tgz#3381f8503b251c0d9cd21bc1de939ec9df5480ee" @@ -2472,9 +2807,9 @@ unpipe@1.0.0, unpipe@~1.0.0: integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= uri-js@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" - integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + version "4.4.0" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" + integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== dependencies: punycode "^2.1.0" @@ -2493,6 +2828,16 @@ 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.1: + version "8.3.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" + integrity sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg== + +v8-compile-cache@^2.0.3: + version "2.2.0" + resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.2.0.tgz#9471efa3ef9128d2f7c6a7ca39c4dd6b5055b132" + integrity sha512-gTpR5XQNKFwOd4clxfnhaqvfqMpqEwr4tOtCyz4MtYZX2JYhfr1JvBFKdS+7K/9rfpZR3VLX+YWBbKoxCgS43Q== + vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -2512,10 +2857,10 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= -which@1.3.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== +which@2.0.2, which@^2.0.1: + 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" @@ -2526,13 +2871,6 @@ wide-align@1.1.3: dependencies: string-width "^1.0.2 || 2" -windows-release@^3.1.0: - version "3.3.1" - resolved "https://registry.yarnpkg.com/windows-release/-/windows-release-3.3.1.tgz#cb4e80385f8550f709727287bf71035e209c4ace" - integrity sha512-Pngk/RDCaI/DkuHPlGTdIkDiTAnAkyMjoQMZqRsxydNl1qGXNIoZrB7RK8g53F2tEgQBMqQJHQdYZuQEEAu54A== - dependencies: - execa "^1.0.0" - winston-transport@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/winston-transport/-/winston-transport-4.4.0.tgz#17af518daa690d5b2ecccaa7acf7b20ca7925e59" @@ -2541,7 +2879,7 @@ winston-transport@^4.4.0: readable-stream "^2.3.7" triple-beam "^1.2.0" -winston@^3.2.1: +winston@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/winston/-/winston-3.3.3.tgz#ae6172042cafb29786afa3d09c8ff833ab7c9170" integrity sha512-oEXTISQnC8VlSAKf1KYSSd7J6IWuRPQqDdo8eoRNaYKLvwSb5+79Z3Yi1lrl6KDpU6/VWaxpakDAtb1oQ4n9aw== @@ -2556,6 +2894,16 @@ winston@^3.2.1: triple-beam "^1.3.0" winston-transport "^4.4.0" +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + +workerpool@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.0.2.tgz#e241b43d8d033f1beb52c7851069456039d1d438" + integrity sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q== + wrap-ansi@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" @@ -2570,22 +2918,24 @@ wrappy@1: resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= +write@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/write/-/write-1.0.3.tgz#0800e14523b923a387e415123c865616aae0f5c3" + integrity sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig== + dependencies: + mkdirp "^0.5.1" + y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== -yallist@^3.0.2: - version "3.1.1" - resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" - integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== - yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== -yaml@*, yaml@^1.6.0: +yaml@^1.10.0: version "1.10.0" resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.0.tgz#3b593add944876077d4d683fee01081bd9fff31e" integrity sha512-yr2icI4glYaNG+KWONODapy2/jDdMSDnrONSjblABjD9B4Z5LgiircSt8m8sRZFNi08kG9Sm0uSHtEmP3zaEGg== @@ -2598,16 +2948,17 @@ yargs-parser@13.1.2, yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" -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@13.3.2, yargs@^13.3.0: +yargs@13.3.2: version "13.3.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==