From bdf0fcdbcbe1fd965c41e58edab6d1068bcfd276 Mon Sep 17 00:00:00 2001 From: Max Leiter Date: Mon, 2 May 2022 23:16:34 -0700 Subject: [PATCH] client, some tests, eslint --- .eslintrc.cjs | 13 ++- .npmignore | 6 +- babel.config.cjs | 1 + client/js/autocompletion.ts | 12 ++- client/js/store.ts | 4 +- client/tsconfig.json | 10 ++- eslint.tsconfig.json | 4 + package.json | 10 ++- src/helper.ts | 1 + src/models/msg.ts | 2 +- src/plugins/sts.ts | 5 +- src/server.ts | 12 ++- src/tsconfig.json | 6 +- src/types/helper.d.ts | 2 +- src/types/models/channel.d.ts | 3 +- src/types/models/message.d.ts | 1 + src/types/models/network.d.ts | 2 +- src/types/server.d.ts | 2 +- test/commands/mode.ts | 16 ++-- test/fixtures/env.ts | 14 ++-- test/models/chan.ts | 9 +- test/{server.js => server.ts} | 26 +++--- test/util.js | 67 --------------- test/util.ts | 73 +++++++++++++++++ tsconfig.base.json | 2 +- webpack.config.ts | 3 +- yarn.lock | 149 +++++++++++++++++++++++++++++----- 27 files changed, 307 insertions(+), 148 deletions(-) create mode 100644 eslint.tsconfig.json rename test/{server.js => server.ts} (89%) delete mode 100644 test/util.js create mode 100644 test/util.ts diff --git a/.eslintrc.cjs b/.eslintrc.cjs index ca48b1ad..2f332e74 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -2,13 +2,24 @@ module.exports = { root: true, parserOptions: { ecmaVersion: 2022, + parser: "@typescript-eslint/parser", + // project: ["./eslint.tsconfig.json"], + // extraFileExtensions: [".vue", ".cjs"], }, + parser: "@typescript-eslint/parser", + plugins: ["vue", "@typescript-eslint"], env: { es6: true, browser: true, mocha: true, node: true, }, + extends: [ + "eslint:recommended", + "plugin:vue/recommended", + "plugin:@typescript-eslint/recommended", + "prettier", + ], rules: { "block-scoped-var": "error", curly: ["error", "all"], @@ -74,6 +85,4 @@ module.exports = { "vue/v-slot-style": ["error", "longform"], "vue/multi-word-component-names": "off", }, - plugins: ["vue"], - extends: ["eslint:recommended", "plugin:vue/recommended", "prettier"], }; diff --git a/.npmignore b/.npmignore index e902f20a..db605e9b 100644 --- a/.npmignore +++ b/.npmignore @@ -9,9 +9,9 @@ # Ignore client folder as it's being built into public/ folder # except for the specified files which are used by the server client/** -!client/js/constants.js -!client/js/helpers/ircmessageparser/findLinks.js -!client/js/helpers/ircmessageparser/cleanIrcMessage.js +!client/js/constants.ts +!client/js/helpers/ircmessageparser/findLinks.ts +!client/js/helpers/ircmessageparser/cleanIrcMessage.ts !client/index.html.tpl public/js/bundle.vendor.js.map diff --git a/babel.config.cjs b/babel.config.cjs index d3f5c72f..db037bf6 100644 --- a/babel.config.cjs +++ b/babel.config.cjs @@ -1,3 +1,4 @@ module.exports = { presets: [["@babel/env", "babel-preset-typescript-vue"]], + targets: "> 0.25%, not dead", }; diff --git a/client/js/autocompletion.ts b/client/js/autocompletion.ts index f362a749..ad04d530 100644 --- a/client/js/autocompletion.ts +++ b/client/js/autocompletion.ts @@ -1,6 +1,6 @@ "use strict"; -const constants = require("./constants"); +import constants from "./constants"; import Mousetrap from "mousetrap"; import {Textcomplete} from "@textcomplete/core/dist/Textcomplete"; @@ -17,7 +17,7 @@ const emojiSearchTerms = Object.keys(emojiMap); const emojiStrategy = { id: "emoji", match: /(^|\s):([-+\w:?]{2,}):?$/, - search(term, callback) { + search(term: string, callback: (matches) => void) { // Trim colon from the matched term, // as we are unable to get a clean string from match regex term = term.replace(/:$/, ""); @@ -267,7 +267,7 @@ function replaceNick(original, position = 1) { return original + store.state.settings.nickPostfix; } -function fuzzyGrep(term, array) { +function fuzzyGrep(term: string, array: Array) { const results = fuzzy.filter(term, array, { pre: "", post: "", @@ -276,6 +276,10 @@ function fuzzyGrep(term, array) { } function rawNicks() { + if (!store.state.activeChannel) { + return []; + } + if (store.state.activeChannel.channel.users.length > 0) { const users = store.state.activeChannel.channel.users.slice(); @@ -294,7 +298,7 @@ function rawNicks() { return [me]; } -function completeNicks(word, isFuzzy) { +function completeNicks(word: string, isFuzzy: boolean) { const users = rawNicks(); word = word.toLowerCase(); diff --git a/client/js/store.ts b/client/js/store.ts index 7002ad08..6041ce09 100644 --- a/client/js/store.ts +++ b/client/js/store.ts @@ -21,10 +21,10 @@ function detectDesktopNotificationState() { export type State = { appLoaded: boolean; - activeChannel: { + activeChannel?: { network: Network; channel: Channel; - } | null; + }; currentUserVisibleError: string | null; desktopNotificationState: "granted" | "blocked" | "nohttps" | "unsupported"; isAutoCompleting: boolean; diff --git a/client/tsconfig.json b/client/tsconfig.json index bf98b833..cef82603 100644 --- a/client/tsconfig.json +++ b/client/tsconfig.json @@ -1,13 +1,19 @@ { "extends": "../tsconfig.base.json", - "include": ["./**/*"], - "files": ["../src/types/models/channel.d.ts"], + "include": ["./**/*", "../src/models/*"], + "files": [ + "../src/types/models/channel.d.ts", + "js/helpers/simplemap.json", + "js/helpers/fullnamemap.json", + "../package.json" + ], "compilerOptions": { // https://v2.vuejs.org/v2/guide/typescript.html?redirect=true#Recommended-Configuration "target": "ES5", "strict": true, "lib": ["ES2020", "dom"], "sourceMap": false, + "resolveJsonModule": true, "baseUrl": "./", "jsx": "preserve" } diff --git a/eslint.tsconfig.json b/eslint.tsconfig.json new file mode 100644 index 00000000..ab8230fd --- /dev/null +++ b/eslint.tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.base.json", + "include": ["src/**/*.ts", "client/**/*.ts", "test/**/*.ts", "scripts/**/*.{ts,js}"] +} diff --git a/package.json b/package.json index 6e1507bb..63d7d032 100644 --- a/package.json +++ b/package.json @@ -76,9 +76,11 @@ "@babel/preset-env": "7.17.10", "@babel/preset-typescript": "7.16.7", "@fortawesome/fontawesome-free": "5.15.4", + "@istanbuljs/nyc-config-typescript": "1.0.2", "@textcomplete/core": "0.1.11", "@textcomplete/textarea": "0.1.10", "@types/bcryptjs": "2.4.2", + "@types/chai": "4.3.1", "@types/content-disposition": "0.5.4", "@types/express": "4.17.13", "@types/is-utf8": "0.2.0", @@ -86,19 +88,22 @@ "@types/linkify-it": "3.0.2", "@types/lodash": "4.14.182", "@types/mime-types": "2.1.1", + "@types/mocha": "9.1.1", "@types/mousetrap": "1.6.9", "@types/node": "17.0.31", "@types/read": "0.0.29", "@types/semver": "7.3.9", + "@types/sinon": "10.0.11", "@types/sqlite3": "3.1.8", "@types/ua-parser-js": "0.7.36", "@types/uuid": "8.3.4", "@types/web-push": "3.3.2", "@types/ws": "8.5.3", + "@typescript-eslint/eslint-plugin": "5.22.0", + "@typescript-eslint/parser": "5.22.0", "@vue/runtime-dom": "3.2.33", "@vue/server-test-utils": "1.3.0", "@vue/test-utils": "1.3.0", - "babel-eslint": "10.1.0", "babel-loader": "8.2.5", "babel-plugin-istanbul": "6.1.1", "babel-preset-typescript-vue": "1.1.1", @@ -156,8 +161,5 @@ }, "resolutions": { "sortablejs": "1.15.0" - }, - "babel": { - "targets": "> 0.25%, not dead" } } diff --git a/src/helper.ts b/src/helper.ts index 28b7d072..9356ef21 100644 --- a/src/helper.ts +++ b/src/helper.ts @@ -8,6 +8,7 @@ import fs from "fs"; import net from "net"; import bcrypt from "bcryptjs"; import crypto from "crypto"; +import {Hostmask} from "./types/helper"; const Helper = { expandHome, diff --git a/src/models/msg.ts b/src/models/msg.ts index 58fa7e28..cba07644 100644 --- a/src/models/msg.ts +++ b/src/models/msg.ts @@ -39,7 +39,7 @@ class Msg { statusmsgGroup!: string; params!: string[]; - constructor(attr: Partial) { + constructor(attr?: Partial) { // Some properties need to be copied in the Msg object instead of referenced if (attr) { ["from", "target"].forEach((prop) => { diff --git a/src/plugins/sts.ts b/src/plugins/sts.ts index 21d2f8e2..684f08a7 100644 --- a/src/plugins/sts.ts +++ b/src/plugins/sts.ts @@ -8,9 +8,10 @@ import Config from "../config"; import type {PolicyMap, PolicyOption} from "types/plugins/sts"; class STSPolicies { - private stsFile: string; + stsFile: string; + refresh: _.DebouncedFunc; + private policies: PolicyMap; - private refresh: _.DebouncedFunc; constructor() { this.stsFile = path.join(Config.getHomePath(), "sts-policies.json"); diff --git a/src/server.ts b/src/server.ts index 09d1d2a6..bfbcb3c9 100644 --- a/src/server.ts +++ b/src/server.ts @@ -24,7 +24,6 @@ import themes from "./plugins/packages/themes"; themes.loadLocalThemes(); import packages from "./plugins/packages/index"; -import Chan from "./models/chan"; import { ClientConfiguration, Defaults, @@ -33,6 +32,7 @@ import { } from "./types/config"; import {Server as wsServer} from "ws"; +import {ServerOptions} from "types/server"; // A random number that will force clients to reload the page if it differs const serverHash = Math.floor(Date.now() * Math.random()); @@ -367,7 +367,13 @@ function indexRequest(req, res) { ); } -function initializeClient(socket, client, token, lastMessage, openChannel) { +function initializeClient( + socket: Socket, + client: Client, + token: string, + lastMessage: number, + openChannel: number +) { socket.off("auth:perform", performAuthentication); socket.emit("auth:success"); @@ -445,7 +451,7 @@ function initializeClient(socket, client, token, lastMessage, openChannel) { return; } - network.edit(client, data); + (network as NetworkWithIrcFramework).edit(client, data); }); socket.on("history:clear", (data) => { diff --git a/src/tsconfig.json b/src/tsconfig.json index cd73e46f..4969be76 100644 --- a/src/tsconfig.json +++ b/src/tsconfig.json @@ -3,12 +3,14 @@ "files": [ "../package.json", "../client/js/constants.ts", - "../client/js/helpers/ircmessageparser/findLinks.ts" + "../client/js/helpers/ircmessageparser/findLinks.ts", + "../client/js/helpers/ircmessageparser/cleanIrcMessage.ts" ], "include": ["**/*"], "compilerOptions": { "types": ["node"], "baseUrl": ".", "noImplicitAny": false - } + }, + "references": [{"path": "../"}] } diff --git a/src/types/helper.d.ts b/src/types/helper.d.ts index 1f06e080..3277803d 100644 --- a/src/types/helper.d.ts +++ b/src/types/helper.d.ts @@ -1,4 +1,4 @@ -type Hostmask = { +export type Hostmask = { nick: string; ident: string; hostname: string; diff --git a/src/types/models/channel.d.ts b/src/types/models/channel.d.ts index 29ae0a61..373aa7ac 100644 --- a/src/types/models/channel.d.ts +++ b/src/types/models/channel.d.ts @@ -1,4 +1,5 @@ -import Chan from "models/chan"; +import Chan from "../../models/chan"; + declare global { export type Channel = Chan; diff --git a/src/types/models/message.d.ts b/src/types/models/message.d.ts index b1435198..e31bb8ea 100644 --- a/src/types/models/message.d.ts +++ b/src/types/models/message.d.ts @@ -8,6 +8,7 @@ declare global { }; type MessagePreview = { + shown: boolean; link: string; }; diff --git a/src/types/models/network.d.ts b/src/types/models/network.d.ts index c2fcfd44..22e12f04 100644 --- a/src/types/models/network.d.ts +++ b/src/types/models/network.d.ts @@ -1,4 +1,4 @@ -import NetworkClass from "models/network"; +import NetworkClass from "../../models/network"; import {Client as IRCClient} from "irc-framework"; import {WebIRC} from "../config"; declare global { diff --git a/src/types/server.d.ts b/src/types/server.d.ts index 04fd03c0..56c70838 100644 --- a/src/types/server.d.ts +++ b/src/types/server.d.ts @@ -1,3 +1,3 @@ -type ServerOptions = { +export type ServerOptions = { dev: boolean; }; diff --git a/test/commands/mode.ts b/test/commands/mode.ts index 9072ca5e..199700f6 100644 --- a/test/commands/mode.ts +++ b/test/commands/mode.ts @@ -1,9 +1,9 @@ "use strict"; -const expect = require("chai").expect; +import {expect} from "chai"; -const Chan = require("../../src/models/chan"); -const ModeCommand = require("../../src/plugins/inputs/mode"); +import Chan from "../../src/models/chan"; +import ModeCommand from "../../src/plugins/inputs/mode"; describe("Commands", function () { describe("/mode", function () { @@ -22,18 +22,18 @@ describe("Commands", function () { nick: "xPaw", irc: { network: { - supports(type) { + supports(type: string) { if (type.toUpperCase() === "MODES") { return "4"; } }, }, - raw(...args) { + raw(...args: string[]) { testableNetwork.firstCommand = testableNetwork.lastCommand; testableNetwork.lastCommand = args.join(" "); }, }, - }; + } as any; const testableNetworkNoSupports = Object.assign({}, testableNetwork, { irc: { @@ -42,7 +42,7 @@ describe("Commands", function () { return null; }, }, - raw(...args) { + raw(...args: string[]) { testableNetworkNoSupports.firstCommand = testableNetworkNoSupports.lastCommand; testableNetworkNoSupports.lastCommand = args.join(" "); }, @@ -50,7 +50,7 @@ describe("Commands", function () { }); it("should not mess with the given target", function () { - const test = function (expected, args) { + const test = function (expected: string, args: string[]) { ModeCommand.input(testableNetwork, channel, "mode", Array.from(args)); expect(testableNetwork.lastCommand).to.equal(expected); diff --git a/test/fixtures/env.ts b/test/fixtures/env.ts index dcdb1a25..18c2dbc3 100644 --- a/test/fixtures/env.ts +++ b/test/fixtures/env.ts @@ -1,13 +1,17 @@ "use strict"; -const fs = require("fs"); +import fs from "fs"; -const home = require("path").join(__dirname, ".thelounge"); -require("../../src/config").setHome(home); +import * as path from "path"; +const home = path.join(__dirname, ".thelounge"); -const STSPolicies = require("../../src/plugins/sts"); // Must be imported *after* setHome +import config from "../../src/config"; +config.setHome(home); -exports.mochaGlobalTeardown = async function () { +import STSPolicies from "../../src/plugins/sts"; // Must be imported *after* setHome +const mochaGlobalTeardown = async function () { STSPolicies.refresh.cancel(); // Cancel debounced function, so it does not write later fs.unlinkSync(STSPolicies.stsFile); }; + +export default mochaGlobalTeardown; diff --git a/test/models/chan.ts b/test/models/chan.ts index c62e87cb..963dd3db 100644 --- a/test/models/chan.ts +++ b/test/models/chan.ts @@ -1,10 +1,9 @@ "use strict"; +import {expect} from "chai"; -const expect = require("chai").expect; -const Chan = require("../../src/models/chan"); -const Msg = require("../../src/models/msg"); -const User = require("../../src/models/user"); - +import Chan from "../../src/models/chan"; +import Msg from "../../src/models/msg"; +import User from "../../src/models/user"; describe("Chan", function () { const network = { network: { diff --git a/test/server.js b/test/server.ts similarity index 89% rename from test/server.js rename to test/server.ts index 28b2304f..653dbde9 100644 --- a/test/server.js +++ b/test/server.ts @@ -1,25 +1,27 @@ "use strict"; -const log = require("../src/log"); -const Config = require("../src/config"); -const expect = require("chai").expect; -const stub = require("sinon").stub; -const got = require("got"); -const io = require("socket.io-client"); -const util = require("./util"); -const changelog = require("../src/plugins/changelog"); +import log from "../src/log"; +import Config from "../src/config"; +import {expect} from "chai"; +import {stub} from "sinon"; +import got from "got"; +import io from "socket.io-client"; +import util from "./util"; +import changelog from "../src/plugins/changelog"; +import Client from "../src/client"; +import Server from "../src/Server"; describe("Server", function () { // Increase timeout due to unpredictable I/O on CI services this.timeout(util.isRunningOnCI() ? 25000 : 5000); - let server; + let server: any; - before(function () { + before(async function () { stub(log, "info"); stub(changelog, "checkForUpdates"); - server = require("../src/server")(); + server = Server(); }); after(function (done) { @@ -51,7 +53,7 @@ describe("Server", function () { describe("WebSockets", function () { this.slow(300); - let client; + let client: Client; beforeEach(() => { client = io(webURL, { diff --git a/test/util.js b/test/util.js deleted file mode 100644 index c33f32a9..00000000 --- a/test/util.js +++ /dev/null @@ -1,67 +0,0 @@ -"use strict"; - -const EventEmitter = require("events").EventEmitter; -const util = require("util"); -const _ = require("lodash"); -const express = require("express"); -const Network = require("../src/models/network"); -const Chan = require("../src/models/chan"); - -function MockClient() { - this.config = { - browser: {}, - }; -} - -util.inherits(MockClient, EventEmitter); - -MockClient.prototype.createMessage = function (opts) { - const message = _.extend( - { - text: "dummy message", - nick: "test-user", - target: "#test-channel", - previews: [], - }, - opts - ); - - return message; -}; - -function sanitizeLog(callback) { - return function (...args) { - // Concats and removes ANSI colors. See https://stackoverflow.com/a/29497680 - const stdout = args - .join(" ") - .replace( - /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, - "" - ); - - callback(stdout + "\n"); - }; -} - -module.exports = { - createClient() { - return new MockClient(); - }, - createNetwork() { - return new Network({ - host: "example.com", - channels: [ - new Chan({ - name: "#test-channel", - }), - ], - }); - }, - createWebserver() { - return express(); - }, - sanitizeLog, - isRunningOnCI() { - return process.env.CI || process.env.GITHUB_ACTIONS; - }, -}; diff --git a/test/util.ts b/test/util.ts new file mode 100644 index 00000000..0cf86e10 --- /dev/null +++ b/test/util.ts @@ -0,0 +1,73 @@ +"use strict"; + +import util from "util"; +import _ from "lodash"; +import express from "express"; +import Network from "../src/models/network"; +import Chan from "../src/models/chan"; +import {EventEmitter} from "events"; + +class MockClient extends EventEmitter { + config: { + browser: any; + }; + + constructor() { + super(); + + this.config = { + browser: {}, + }; + } + + createMessage(opts: any) { + const message = _.extend( + { + text: "dummy message", + nick: "test-user", + target: "#test-channel", + previews: [], + }, + opts + ); + + return message; + } +} + +function sanitizeLog(callback: (log: string) => void) { + return function (...args: string[]) { + // Concats and removes ANSI colors. See https://stackoverflow.com/a/29497680 + const stdout = args + .join(" ") + .replace( + /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g, + "" + ); + + callback(stdout + "\n"); + }; +} + +export default { + createClient() { + return new MockClient(); + }, + createNetwork() { + return new Network({ + host: "example.com", + channels: [ + new Chan({ + name: "#test-channel", + }), + ], + }); + }, + createWebserver() { + return express(); + }, + sanitizeLog, + isRunningOnCI() { + return process.env.CI || process.env.GITHUB_ACTIONS; + }, +}; diff --git a/tsconfig.base.json b/tsconfig.base.json index c24da132..f55a65ee 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -19,5 +19,5 @@ // "skipLibCheck": true, "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ }, - "files": ["./package.json", "./src/index.d.ts"] + "files": ["./package.json", "./src/**/*.d.ts"] } diff --git a/webpack.config.ts b/webpack.config.ts index 25f4f142..df0864f0 100644 --- a/webpack.config.ts +++ b/webpack.config.ts @@ -36,11 +36,12 @@ const config: webpack.Configuration = { compilerOptions: { preserveWhitespace: false, }, + appendTsSuffixTo: [/\.vue$/], }, }, }, { - test: /\.{js,ts,d.ts}$/, + test: /\.{js,ts}$/, include: [path.resolve(__dirname, "client/")], exclude: path.resolve(__dirname, "node_modules"), use: { diff --git a/yarn.lock b/yarn.lock index 05241c3c..1266c563 100644 --- a/yarn.lock +++ b/yarn.lock @@ -311,7 +311,7 @@ chalk "^2.0.0" js-tokens "^4.0.0" -"@babel/parser@^7.1.6", "@babel/parser@^7.13.16", "@babel/parser@^7.17.10", "@babel/parser@^7.7.0": +"@babel/parser@^7.1.6", "@babel/parser@^7.13.16", "@babel/parser@^7.17.10": version "7.17.10" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.17.10.tgz#873b16db82a8909e0fbd7f115772f4b739f6ce78" integrity sha512-n2Q6i+fnJqzOaq2VkdXxy2TCPCWQZHiCo0XqmrCvDWcZQKRyZzYi4Z0yxlBuN0w+r2ZHmre+Q087DSrw3pbJDQ== @@ -996,7 +996,7 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/traverse@^7.17.10", "@babel/traverse@^7.7.0": +"@babel/traverse@^7.17.10": version "7.17.10" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.17.10.tgz#1ee1a5ac39f4eac844e6cf855b35520e5eb6f8b5" integrity sha512-VmbrTHQteIdUUQNTb+zE12SHS/xQVIShmBPhlNP12hD5poF2pbITW1Z4172d03HegaQWhLffdkRJYtAzp0AGcw== @@ -1020,7 +1020,7 @@ "@babel/helper-validator-identifier" "^7.16.7" to-fast-properties "^2.0.0" -"@babel/types@^7.17.10", "@babel/types@^7.7.0": +"@babel/types@^7.17.10": version "7.17.10" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.17.10.tgz#d35d7b4467e439fcf06d195f8100e0fea7fc82c4" integrity sha512-9O26jG0mBYfGkUYCYZRnBwbVLd1UZOICEr2Em6InB6jVfsAv1GKgwXHmrSg+WFWDmeKTA6vyTZiN8tCSM5Oo3A== @@ -1161,6 +1161,13 @@ js-yaml "^3.13.1" resolve-from "^5.0.0" +"@istanbuljs/nyc-config-typescript@1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@istanbuljs/nyc-config-typescript/-/nyc-config-typescript-1.0.2.tgz#1f5235b28540a07219ae0dd42014912a0b19cf89" + integrity sha512-iKGIyMoyJuFnJRSVTZ78POIRvNnwZaWIf8vG4ZS3rQq58MMDrqEX2nnzx0R28V2X8JvmKYiqY9FP2hlJsm8A0w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + "@istanbuljs/schema@^0.1.2": version "0.1.3" resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" @@ -1395,6 +1402,11 @@ "@types/node" "*" "@types/responselike" "*" +"@types/chai@4.3.1": + version "4.3.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.1.tgz#e2c6e73e0bdeb2521d00756d099218e9f5d90a04" + integrity sha512-/zPMqDkzSZ8t3VtxOa4KPq7uzzW978M9Tvh+j7GHKuo6k6GTLxPJ4J5gE5cjfJ26pnXst0N5Hax8Sr0T2Mi9zQ== + "@types/cheerio@^0.22.10": version "0.22.31" resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.31.tgz#b8538100653d6bb1b08a1e46dec75b4f2a5d5eb6" @@ -1545,6 +1557,11 @@ resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.2.tgz#ee771e2ba4b3dc5b372935d549fd9617bf345b8c" integrity sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ== +"@types/mocha@9.1.1": + version "9.1.1" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-9.1.1.tgz#e7c4f1001eefa4b8afbd1eee27a237fee3bf29c4" + integrity sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw== + "@types/mousetrap@1.6.9": version "1.6.9" resolved "https://registry.yarnpkg.com/@types/mousetrap/-/mousetrap-1.6.9.tgz#f1ef9adbd1eac3466f21b6988b1c82c633a45340" @@ -1605,6 +1622,18 @@ "@types/mime" "^1" "@types/node" "*" +"@types/sinon@10.0.11": + version "10.0.11" + resolved "https://registry.yarnpkg.com/@types/sinon/-/sinon-10.0.11.tgz#8245827b05d3fc57a6601bd35aee1f7ad330fc42" + integrity sha512-dmZsHlBsKUtBpHriNjlK0ndlvEh8dcb9uV9Afsbt89QIyydpC7NcR+nWlAhASfy3GHnxTl4FX/aKE7XZUt/B4g== + dependencies: + "@types/sinonjs__fake-timers" "*" + +"@types/sinonjs__fake-timers@*": + version "8.1.2" + resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.2.tgz#bf2e02a3dbd4aecaf95942ecd99b7402e03fad5e" + integrity sha512-9GcLXF0/v3t80caGs5p2rRfkB+a8VBGLJZVih6CNFkx8IZ994wiKKLSRs9nuFwk1HevWs/1mnUmkApGrSGsShA== + "@types/sqlite3@3.1.8": version "3.1.8" resolved "https://registry.yarnpkg.com/@types/sqlite3/-/sqlite3-3.1.8.tgz#e64310c5841fc01c1a8795d960d951e4cf940296" @@ -1636,6 +1665,86 @@ dependencies: "@types/node" "*" +"@typescript-eslint/eslint-plugin@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.22.0.tgz#7b52a0de2e664044f28b36419210aea4ab619e2a" + integrity sha512-YCiy5PUzpAeOPGQ7VSGDEY2NeYUV1B0swde2e0HzokRsHBYjSdF6DZ51OuRZxVPHx0032lXGLvOMls91D8FXlg== + dependencies: + "@typescript-eslint/scope-manager" "5.22.0" + "@typescript-eslint/type-utils" "5.22.0" + "@typescript-eslint/utils" "5.22.0" + debug "^4.3.2" + functional-red-black-tree "^1.0.1" + ignore "^5.1.8" + regexpp "^3.2.0" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/parser@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.22.0.tgz#7bedf8784ef0d5d60567c5ba4ce162460e70c178" + integrity sha512-piwC4krUpRDqPaPbFaycN70KCP87+PC5WZmrWs+DlVOxxmF+zI6b6hETv7Quy4s9wbkV16ikMeZgXsvzwI3icQ== + dependencies: + "@typescript-eslint/scope-manager" "5.22.0" + "@typescript-eslint/types" "5.22.0" + "@typescript-eslint/typescript-estree" "5.22.0" + debug "^4.3.2" + +"@typescript-eslint/scope-manager@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.22.0.tgz#590865f244ebe6e46dc3e9cab7976fc2afa8af24" + integrity sha512-yA9G5NJgV5esANJCO0oF15MkBO20mIskbZ8ijfmlKIvQKg0ynVKfHZ15/nhAJN5m8Jn3X5qkwriQCiUntC9AbA== + dependencies: + "@typescript-eslint/types" "5.22.0" + "@typescript-eslint/visitor-keys" "5.22.0" + +"@typescript-eslint/type-utils@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.22.0.tgz#0c0e93b34210e334fbe1bcb7250c470f4a537c19" + integrity sha512-iqfLZIsZhK2OEJ4cQ01xOq3NaCuG5FQRKyHicA3xhZxMgaxQazLUHbH/B2k9y5i7l3+o+B5ND9Mf1AWETeMISA== + dependencies: + "@typescript-eslint/utils" "5.22.0" + debug "^4.3.2" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.22.0.tgz#50a4266e457a5d4c4b87ac31903b28b06b2c3ed0" + integrity sha512-T7owcXW4l0v7NTijmjGWwWf/1JqdlWiBzPqzAWhobxft0SiEvMJB56QXmeCQjrPuM8zEfGUKyPQr/L8+cFUBLw== + +"@typescript-eslint/typescript-estree@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.22.0.tgz#e2116fd644c3e2fda7f4395158cddd38c0c6df97" + integrity sha512-EyBEQxvNjg80yinGE2xdhpDYm41so/1kOItl0qrjIiJ1kX/L/L8WWGmJg8ni6eG3DwqmOzDqOhe6763bF92nOw== + dependencies: + "@typescript-eslint/types" "5.22.0" + "@typescript-eslint/visitor-keys" "5.22.0" + debug "^4.3.2" + globby "^11.0.4" + is-glob "^4.0.3" + semver "^7.3.5" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.22.0.tgz#1f2c4897e2cf7e44443c848a13c60407861babd8" + integrity sha512-HodsGb037iobrWSUMS7QH6Hl1kppikjA1ELiJlNSTYf/UdMEwzgj0WIp+lBNb6WZ3zTwb0tEz51j0Wee3iJ3wQ== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.22.0" + "@typescript-eslint/types" "5.22.0" + "@typescript-eslint/typescript-estree" "5.22.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.22.0": + version "5.22.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.22.0.tgz#f49c0ce406944ffa331a1cfabeed451ea4d0909c" + integrity sha512-DbgTqn2Dv5RFWluG88tn0pP6Ex0ROF+dpDO1TNNZdRtLjUr6bdznjA6f/qNqJLjd2PgguAES2Zgxh/JzwzETDg== + dependencies: + "@typescript-eslint/types" "5.22.0" + eslint-visitor-keys "^3.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" @@ -2190,18 +2299,6 @@ babel-core@^7.0.0-bridge.0: resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece" integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg== -babel-eslint@10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/babel-eslint/-/babel-eslint-10.1.0.tgz#6968e568a910b78fb3779cdd8b6ac2f479943232" - integrity sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg== - dependencies: - "@babel/code-frame" "^7.0.0" - "@babel/parser" "^7.7.0" - "@babel/traverse" "^7.7.0" - "@babel/types" "^7.7.0" - eslint-visitor-keys "^1.0.0" - resolve "^1.12.0" - babel-loader@8.2.5: version "8.2.5" resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.2.5.tgz#d45f585e654d5a5d90f5350a779d7647c5ed512e" @@ -3567,7 +3664,7 @@ eslint-utils@^3.0.0: dependencies: eslint-visitor-keys "^2.0.0" -eslint-visitor-keys@^1.0.0, eslint-visitor-keys@^1.1.0, eslint-visitor-keys@^1.3.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== @@ -3577,7 +3674,7 @@ eslint-visitor-keys@^2.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== -eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0, eslint-visitor-keys@^3.3.0: +eslint-visitor-keys@^3.0.0, eslint-visitor-keys@^3.1.0, eslint-visitor-keys@^3.2.0, eslint-visitor-keys@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== @@ -4266,7 +4363,7 @@ globals@^13.6.0, globals@^13.9.0: dependencies: type-fest "^0.20.2" -globby@^11.1.0: +globby@^11.0.4, globby@^11.1.0: version "11.1.0" resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== @@ -4579,7 +4676,7 @@ ignore@^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, ignore@^5.1.9, ignore@^5.2.0: +ignore@^5.1.4, ignore@^5.1.8, ignore@^5.1.9, ignore@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== @@ -7462,7 +7559,7 @@ resolve-url@^0.2.1: resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= -resolve@^1.1.7, resolve@^1.10.0, resolve@^1.12.0, resolve@^1.14.2, resolve@^1.2.0, resolve@^1.9.0: +resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.2.0, resolve@^1.9.0: version "1.22.0" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.0.tgz#5e0b8c67c15df57a89bdbabe603a002f21731198" integrity sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw== @@ -8501,6 +8598,11 @@ tsconfig-paths@3.14.1, tsconfig-paths@^3.9.0: minimist "^1.2.6" strip-bom "^3.0.0" +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== + tslib@^2.0.1: version "2.4.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.4.0.tgz#7cecaa7f073ce680a05847aa77be941098f36dc3" @@ -8511,6 +8613,13 @@ tslib@^2.2.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" integrity sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw== +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + 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"