diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000000000000000000000000000000000000..256c63e4c59502f937824c1379ec7c32dc9ab63e --- /dev/null +++ b/.eslintrc @@ -0,0 +1,57 @@ +{ + "parser": "@typescript-eslint/parser", + "plugins": ["@typescript-eslint"], + "parserOptions": { + "ecmaVersion": 9, + "ecmaFeatures": { + "jsx": false + }, + "project": "tsconfig.json" + }, + "env": { + "node": true, + "jasmine": true + }, + "extends": ["plugin:@typescript-eslint/recommended"], + "rules": { + "ordered-imports": "off", + "no-trailing-spaces": "error", + "max-classes-per-file": ["warn", 1], + "object-literal-sort-keys": "off", + "@typescript-eslint/no-explicit-any": "error", + "@typescript-eslint/prefer-for-of": "error", + "@typescript-eslint/typedef": "warn", + "@typescript-eslint/no-floating-promises": "error", + "curly": "error", + "no-empty": "off", + "no-invalid-this": "error", + "@typescript-eslint/no-throw-literal": "warn", + "prefer-const": "error", + "indent": ["error", 4], + "max-lines": ["warn", 500], + "no-duplicate-imports": "error", + "@typescript-eslint/array-type": "error", + "@typescript-eslint/promise-function-async": "error", + "no-bitwise": "error", + "no-console": "error", + "no-debugger": "error", + "prefer-template": "error", + // Disable these as they were introduced by @typescript-eslint/recommended + "@typescript-eslint/no-use-before-define": "off", + "@typescript-eslint/no-inferrable-types": "off", + "@typescript-eslint/member-delimiter-style": "off", + "@typescript-eslint/no-unused-expressions": "off", + "@typescript-eslint/interface-name-prefix": "off" + }, + "overrides": [ + { + "files": [ + "test/**/*" + ], + "rules": { + "@typescript-eslint/no-empty-function": "off", + "@typescript-eslint/no-explicit-any": "off" + } + } + ] +} diff --git a/README.md b/README.md index a894a82bd5cabec05d02a70ab8a7c21e597c4b9a..13721918bcd467bbe6b9179a8535e25804d4ee9e 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ that implements the [AS API](https://matrix.org/docs/spec/application_service/r0 The bridge supports any version of Node.js >= v12.X, including all [current releases](https://nodejs.org/en/about/releases/). -### Setup the bridge +### Set up the bridge * Run ``npm install`` to grab the dependencies. `npm` may complain about peer dependencies, but you can safely ignore these. * Run ``npm run build`` to build the typescript into javascript. @@ -113,6 +113,23 @@ should show up in the network list on Element and other clients. [Howto](./docs/howto.md) +## End User Documentation + +### Bridging a Room + +You must get an authorization link from bridge owner. You must be a server admin or get +help from server admin on Discord side. + +* Invite the Matrix side bot to your room and wait for it to join. +* On Discord side use the authorization link to invite bot to Discord server. +* Find out a serverid and channelid for your server/channel you want to bridge. Search the web for instructions. +* In Matrix room give command ``!discord bridge ServerID ChannelID`` +* The bridge will ask for confirmation from the Discord server admins to complete the bridge. Once approved, you're all set. + +### Unbridging a Room + +* In Matrix room give command ``!discord unbridge`` + ## Features and Roadmap In a vague order of what is coming up next diff --git a/package.json b/package.json index 8f958309ba4ee74946c8e73d4eff743aad693370..27172919f2707b05e8f250a832fc416c8e26c7ae 100644 --- a/package.json +++ b/package.json @@ -5,8 +5,8 @@ "main": "discordas.js", "scripts": { "test": "mocha -r ts-node/register test/config.ts test/test_*.ts test/**/test_*.ts", - "lint": "tslint --project ./tsconfig.json -t stylish", - "coverage": "nyc mocha -r ts-node/register test/config.ts test/test_*.ts test/**/test_*.ts", + "lint": "eslint -c .eslintrc --max-warnings 200 src/**/*.ts test/**/*.ts", + "coverage": "tsc && nyc mocha build/test/config.js build/test", "build": "tsc", "postinstall": "npm run build", "start": "npm run-script build && node ./build/src/discordas.js -c config.yaml", @@ -57,6 +57,8 @@ }, "devDependencies": { "@istanbuljs/nyc-config-typescript": "^1.0.1", + "@typescript-eslint/eslint-plugin": "^2.14.0", + "@typescript-eslint/parser": "^2.14.0", "@types/better-sqlite3": "^5.4.1", "@types/chai": "^4.2.11", "@types/command-line-args": "^5.0.0", @@ -72,8 +74,8 @@ "proxyquire": "^1.7.11", "source-map-support": "^0.5.19", "ts-node": "^8.10.2", - "tslint": "^5.20.1", "typescript": "^3.9.5", - "why-is-node-running": "^2.2.0" + "why-is-node-running": "^2.2.0", + "eslint": "^7.4.0" } } diff --git a/src/clientfactory.ts b/src/clientfactory.ts index 5a150e2678a584f3e05db05d277d13fc11591b79..b8f949fc07d786322ab94e6aa71d6dfe91e4babe 100644 --- a/src/clientfactory.ts +++ b/src/clientfactory.ts @@ -123,17 +123,17 @@ export class DiscordClientFactory { } public bindMetricsToChannel(channel: TextChannel) { - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any const flexChan = channel as any; if (flexChan._xmet_send !== undefined) { return; } // Prefix the real functions with _xmet_ + // eslint-disable-next-line @typescript-eslint/camelcase flexChan._xmet_send = channel.send; - // tslint:disable-next-line:only-arrow-functions - channel.send = function() { + channel.send = (...rest) => { MetricPeg.get.remoteCall("channel.send"); - return flexChan._xmet_send.apply(channel, arguments); + return flexChan._xmet_send.apply(channel, rest); }; } } diff --git a/src/config.ts b/src/config.ts index 0d49c57983988b29aa97cb33a72be12132777d6d..5b21b766d886d660a115eab7769343acbabf98f9 100644 --- a/src/config.ts +++ b/src/config.ts @@ -35,7 +35,7 @@ export class DiscordBridgeConfig { * @param newConfig Config keys * @param configLayer Private parameter */ - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any public applyConfig(newConfig: {[key: string]: any}, configLayer: {[key: string]: any} = this) { Object.keys(newConfig).forEach((key) => { if (configLayer[key] instanceof Object && !(configLayer[key] instanceof Array)) { @@ -53,10 +53,10 @@ export class DiscordBridgeConfig { * @param configLayer private parameter: current layer of configuration to alter recursively */ public applyEnvironmentOverrides( - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any environment: {[key: string]: any}, path: string[] = [ENV_PREFIX], - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any configLayer: {[key: string]: any} = this, ) { Object.keys(configLayer).forEach((key) => { diff --git a/src/db/dbdataemoji.ts b/src/db/dbdataemoji.ts index 9b076b6c407c9fb41291a6a42d80111203623c7c..6e74bd56aaf37da404b0c231c366712ccea418be 100644 --- a/src/db/dbdataemoji.ts +++ b/src/db/dbdataemoji.ts @@ -39,9 +39,9 @@ export class DbEmoji implements IDbData { WHERE mxc_url = $mxc`; } const row = await store.db.Get(query, { - id: params.emoji_id, - mxc: params.mxc_url, - }); + id: params.emoji_id, + mxc: params.mxc_url, + }); this.Result = Boolean(row); // check if row exists if (this.Result && row) { this.EmojiId = row.emoji_id as string; @@ -60,12 +60,14 @@ export class DbEmoji implements IDbData { INSERT INTO emoji (emoji_id,name,animated,mxc_url,created_at,updated_at) VALUES ($emoji_id,$name,$animated,$mxc_url,$created_at,$updated_at);`, { - animated: Number(this.Animated), - created_at: this.CreatedAt, - emoji_id: this.EmojiId, - mxc_url: this.MxcUrl, - name: this.Name, - updated_at: this.UpdatedAt, + /* eslint-disable @typescript-eslint/camelcase */ + animated: Number(this.Animated), + created_at: this.CreatedAt, + emoji_id: this.EmojiId, + mxc_url: this.MxcUrl, + name: this.Name, + updated_at: this.UpdatedAt, + /* eslint-enable @typescript-eslint/camelcase */ }); } @@ -80,11 +82,13 @@ export class DbEmoji implements IDbData { updated_at = $updated_at WHERE emoji_id = $emoji_id`, { - animated: Number(this.Animated), - emoji_id: this.EmojiId, - mxc_url: this.MxcUrl, - name: this.Name, - updated_at: this.UpdatedAt, + /* eslint-disable @typescript-eslint/camelcase */ + animated: Number(this.Animated), + emoji_id: this.EmojiId, + mxc_url: this.MxcUrl, + name: this.Name, + updated_at: this.UpdatedAt, + /* eslint-enable @typescript-eslint/camelcase */ }); } diff --git a/src/db/dbdataevent.ts b/src/db/dbdataevent.ts index 46c8a9387548a5fde822980ba157307c0985d035..cfe5c3f0fd1e779a727619bcfeef28b98f550ddb 100644 --- a/src/db/dbdataevent.ts +++ b/src/db/dbdataevent.ts @@ -24,7 +24,7 @@ export class DbEvent implements IDbDataMany { public GuildId: string; public ChannelId: string; public Result: boolean; - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any private rows: any[]; get ResultCount(): number { @@ -33,21 +33,21 @@ export class DbEvent implements IDbDataMany { public async RunQuery(store: DiscordStore, params: ISqlCommandParameters): Promise<void> { this.rows = []; - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any let rowsM: any[] | null = null; if (params.matrix_id) { rowsM = await store.db.All(` SELECT * FROM event_store WHERE matrix_id = $id`, { - id: params.matrix_id, + id: params.matrix_id, }); } else if (params.discord_id) { rowsM = await store.db.All(` SELECT * FROM event_store WHERE discord_id = $id`, { - id: params.discord_id, + id: params.discord_id, }); } else { throw new Error("Unknown/incorrect id given as a param"); @@ -55,20 +55,24 @@ export class DbEvent implements IDbDataMany { for (const rowM of rowsM) { const row = { + /* eslint-disable @typescript-eslint/camelcase */ discord_id: rowM.discord_id, matrix_id: rowM.matrix_id, + /* eslint-enable @typescript-eslint/camelcase */ }; for (const rowD of await store.db.All(` SELECT * FROM discord_msg_store WHERE msg_id = $id`, { - id: rowM.discord_id, + id: rowM.discord_id, })) { - // tslint:disable-next-line no-any - const insertRow: any = Object.assign({}, row); - insertRow.guild_id = rowD.guild_id; - insertRow.channel_id = rowD.channel_id; - this.rows.push(insertRow); + this.rows.push({ + /* eslint-disable @typescript-eslint/camelcase */ + ...row, + guild_id: rowD.guild_id, + channel_id: rowD.channel_id, + /* eslint-enable @typescript-eslint/camelcase */ + }); } } this.Result = this.rows.length !== 0; @@ -91,15 +95,17 @@ export class DbEvent implements IDbDataMany { INSERT INTO event_store (matrix_id,discord_id) VALUES ($matrix_id,$discord_id);`, { - discord_id: this.DiscordId, - matrix_id: this.MatrixId, + /* eslint-disable @typescript-eslint/camelcase */ + discord_id: this.DiscordId, + matrix_id: this.MatrixId, + /* eslint-enable @typescript-eslint/camelcase */ }); // Check if the discord item exists? const msgExists = await store.db.Get(` SELECT * FROM discord_msg_store WHERE msg_id = $id`, { - id: this.DiscordId, + id: this.DiscordId, }) != null; if (msgExists) { return; @@ -108,9 +114,11 @@ export class DbEvent implements IDbDataMany { INSERT INTO discord_msg_store (msg_id, guild_id, channel_id) VALUES ($msg_id, $guild_id, $channel_id);`, { - channel_id: this.ChannelId, - guild_id: this.GuildId, - msg_id: this.DiscordId, + /* eslint-disable @typescript-eslint/camelcase */ + channel_id: this.ChannelId, + guild_id: this.GuildId, + msg_id: this.DiscordId, + /* eslint-enable @typescript-eslint/camelcase */ }); } @@ -123,13 +131,17 @@ export class DbEvent implements IDbDataMany { DELETE FROM event_store WHERE matrix_id = $matrix_id AND discord_id = $discord_id;`, { - discord_id: this.DiscordId, - matrix_id: this.MatrixId, + /* eslint-disable @typescript-eslint/camelcase */ + discord_id: this.DiscordId, + matrix_id: this.MatrixId, + /* eslint-enable @typescript-eslint/camelcase */ }); return store.db.Run(` DELETE FROM discord_msg_store WHERE msg_id = $discord_id;`, { - discord_id: this.DiscordId, + /* eslint-disable @typescript-eslint/camelcase */ + discord_id: this.DiscordId, + /* eslint-enable @typescript-eslint/camelcase */ }); } } diff --git a/src/db/dbdatainterface.ts b/src/db/dbdatainterface.ts index 043bec08ba887e8b927a3b35eea6a7be7cc110a7..2a66a6b3894faf0ad2a6abbae4b18118fddced01 100644 --- a/src/db/dbdatainterface.ts +++ b/src/db/dbdatainterface.ts @@ -18,7 +18,7 @@ import { DiscordStore } from "../store"; export interface IDbData { Result: boolean; - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any RunQuery(store: DiscordStore, params: any): Promise<void|Error>; Insert(store: DiscordStore): Promise<void|Error>; Update(store: DiscordStore): Promise<void|Error>; diff --git a/src/db/postgres.ts b/src/db/postgres.ts index a3fc00cee282dfbf2d843df8e13da584456064e7..e4503bfb35f0276102344bda1e3c424680b7a1d2 100644 --- a/src/db/postgres.ts +++ b/src/db/postgres.ts @@ -25,17 +25,18 @@ const pgp: pgPromise.IMain = pgPromise({ export class Postgres implements IDatabaseConnector { public static ParameterizeSql(sql: string): string { - return sql.replace(/\$((\w|\d|_)+)+/g, (k) => { + return sql.replace(/\$((\w|\d|_)+)+/g, (k: string) => { return `\${${k.substring("$".length)}}`; }); } - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any private db: pgPromise.IDatabase<any>; constructor(private connectionString: string) { } - public Open() { + + public Open(): void { // Hide username:password const logConnString = this.connectionString.substring( this.connectionString.indexOf("@") || 0, @@ -63,7 +64,7 @@ export class Postgres implements IDatabaseConnector { public async Run(sql: string, parameters?: ISqlCommandParameters): Promise<void> { log.silly("Run:", sql); - return this.db.oneOrNone(Postgres.ParameterizeSql(sql), parameters).then(() => {}); + await this.db.oneOrNone(Postgres.ParameterizeSql(sql), parameters); } public async Close(): Promise<void> { @@ -73,6 +74,5 @@ export class Postgres implements IDatabaseConnector { public async Exec(sql: string): Promise<void> { log.silly("Exec:", sql); await this.db.none(sql); - return; } } diff --git a/src/db/roomstore.ts b/src/db/roomstore.ts index a3068c8ee4d11134d2780880dfb7960054e7c7cc..e8e66f4df880b1b09241a7c2f5213c20a8e0c18a 100644 --- a/src/db/roomstore.ts +++ b/src/db/roomstore.ts @@ -52,7 +52,7 @@ export class RemoteStoreRoom { public data: IRemoteRoomDataLazy; constructor(public readonly roomId: string, data: IRemoteRoomDataLazy) { for (const k of ["discord_guild", "discord_channel", "discord_name", - "discord_topic", "discord_iconurl", "discord_iconurl_mxc", "discord_type"]) { + "discord_topic", "discord_iconurl", "discord_iconurl_mxc", "discord_type"]) { data[k] = typeof(data[k]) === "number" ? String(data[k]) : data[k] || null; } for (const k of ["update_name", "update_topic", "update_icon", "plumbed"]) { @@ -128,7 +128,7 @@ export class DbRoomStore { }; try { await this.db.Run(`INSERT INTO room_entries VALUES ($id, $matrix, $remote)`, values); - log.verbose("Created new entry " + entry.id); + log.verbose(`Created new entry ${entry.id}`); } catch (ex) { log.error("Failed to insert room entry", ex); throw Error("Failed to insert room entry"); @@ -189,7 +189,7 @@ export class DbRoomStore { {remoteId}, ); if (row) { - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any remote = new RemoteStoreRoom(remoteId, row as any); } } @@ -225,7 +225,7 @@ export class DbRoomStore { {rid: remoteId}, ); if (row) { - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any remote = new RemoteStoreRoom(remoteId, row as any); } } @@ -253,7 +253,7 @@ export class DbRoomStore { try { await this.db.Run(`INSERT INTO room_entries VALUES ($id, $matrix, $remote)`, values); - log.verbose("Created new entry " + values.id); + log.verbose(`Created new entry ${values.id}`); } catch (ex) { log.error("Failed to insert room entry", ex); throw Error("Failed to insert room entry"); @@ -277,7 +277,7 @@ export class DbRoomStore { SELECT * FROM remote_room_data INNER JOIN room_entries ON remote_room_data.room_id = room_entries.remote_id WHERE ${whereClaues}`; - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any return (await this.db.All(sql, data as any)).map((row) => { const id = row.id as string; const matrixId = row.matrix_id; @@ -285,7 +285,7 @@ export class DbRoomStore { return { id, matrix: matrixId ? new MatrixStoreRoom(matrixId as string) : null, - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any remote: matrixId ? new RemoteStoreRoom(remoteId as string, row as any) : null, }; }); @@ -321,6 +321,7 @@ export class DbRoomStore { ); const data = { + /* eslint-disable @typescript-eslint/camelcase */ discord_channel: room.data.discord_channel, discord_guild: room.data.discord_guild, discord_iconurl: room.data.discord_iconurl, @@ -332,12 +333,13 @@ export class DbRoomStore { update_icon: Number(room.data.update_icon || 0), update_name: Number(room.data.update_name || 0), update_topic: Number(room.data.update_topic || 0), + /* eslint-enable @typescript-eslint/camelcase */ } as IRemoteRoomData; if (!existingRow) { // Insert new data. await this.db.Run( - `INSERT INTO remote_room_data VALUES ( + `INSERT INTO remote_room_data VALUES ( $id, $discord_guild, $discord_channel, @@ -352,11 +354,11 @@ export class DbRoomStore { $plumbed ) `, - { - id: room.roomId, - // tslint:disable-next-line no-any - ...data as any, - }); + { + id: room.roomId, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ...data as any, + }); return; } @@ -365,8 +367,8 @@ export class DbRoomStore { // New keys Object.keys(room.data).filter( (k: string) => existingRow[k] === null).forEach((key) => { - const val = room.data[key]; - keysToUpdate[key] = typeof val === "boolean" ? Number(val) : val; + const val = room.data[key]; + keysToUpdate[key] = typeof val === "boolean" ? Number(val) : val; }); // Updated keys @@ -386,12 +388,12 @@ export class DbRoomStore { try { await this.db.Run(`UPDATE remote_room_data SET ${setStatement} WHERE room_id = $id`, - { - id: room.roomId, - // tslint:disable-next-line no-any - ...keysToUpdate as any, - }); - log.verbose("Upserted room " + room.roomId); + { + id: room.roomId, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ...keysToUpdate as any, + }); + log.verbose(`Upserted room ${ room.roomId}`); } catch (ex) { log.error("Failed to upsert room", ex); throw Error("Failed to upsert room"); diff --git a/src/db/userstore.ts b/src/db/userstore.ts index 7e84dc0a84faf4767a188349e11236ef34586d9c..f922b68a183326c327159452467a42b1b585df02 100644 --- a/src/db/userstore.ts +++ b/src/db/userstore.ts @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +/* eslint-disable max-classes-per-file */ import { IDatabaseConnector } from "./connector"; import { Log } from "../log"; @@ -81,9 +82,11 @@ export class DbUserStore { {remoteId}, ); if (nicks) { + /* eslint-disable @typescript-eslint/camelcase */ nicks.forEach(({nick, guild_id}) => { remoteUser.guildNicks.set(guild_id as string, nick as string); }); + /* eslint-enable @typescript-eslint/camelcase */ } this.remoteUserCache.set(remoteId, remoteUser); return remoteUser; @@ -98,35 +101,39 @@ export class DbUserStore { ); if (!existingData) { await this.db.Run( - `INSERT INTO remote_user_data VALUES ( - $remote_id, - $displayname, - $avatarurl, - $avatarurl_mxc - )`, - { - avatarurl: user.avatarurl, - avatarurl_mxc: user.avatarurlMxc, - displayname: user.displayname, - remote_id: user.id, - }); + `INSERT INTO remote_user_data VALUES ( + $remote_id, + $displayname, + $avatarurl, + $avatarurl_mxc + )`, + { + /* eslint-disable @typescript-eslint/camelcase */ + avatarurl: user.avatarurl, + avatarurl_mxc: user.avatarurlMxc, + displayname: user.displayname, + remote_id: user.id, + /* eslint-enable @typescript-eslint/camelcase */ + }); } else { await this.db.Run( -`UPDATE remote_user_data SET displayname = $displayname, + `UPDATE remote_user_data SET displayname = $displayname, avatarurl = $avatarurl, avatarurl_mxc = $avatarurl_mxc WHERE remote_id = $remote_id`, - { - avatarurl: user.avatarurl, - avatarurl_mxc: user.avatarurlMxc, - displayname: user.displayname, - remote_id: user.id, - }); + { + /* eslint-disable @typescript-eslint/camelcase */ + avatarurl: user.avatarurl, + avatarurl_mxc: user.avatarurlMxc, + displayname: user.displayname, + remote_id: user.id, + /* eslint-enable @typescript-eslint/camelcase */ + }); } const existingNicks = {}; (await this.db.All( "SELECT guild_id, nick FROM remote_user_guild_nicks WHERE remote_id = $remoteId", {remoteId: user.id}, - )).forEach(({guild_id, nick}) => existingNicks[guild_id as string] = nick); + )).forEach(({guild_id, nick}) => existingNicks[guild_id as string] = nick); // eslint-disable-line @typescript-eslint/camelcase for (const guildId of user.guildNicks.keys()) { const nick = user.guildNicks.get(guildId) || null; if (existingData) { @@ -134,28 +141,32 @@ avatarurl_mxc = $avatarurl_mxc WHERE remote_id = $remote_id`, return; } else if (existingNicks[guildId]) { await this.db.Run( -`UPDATE remote_user_guild_nicks SET nick = $nick + `UPDATE remote_user_guild_nicks SET nick = $nick WHERE remote_id = $remote_id AND guild_id = $guild_id`, - { - guild_id: guildId, - nick, - remote_id: user.id, - }); + { + /* eslint-disable @typescript-eslint/camelcase */ + guild_id: guildId, + nick, + remote_id: user.id, + /* eslint-enable @typescript-eslint/camelcase */ + }); return; } } await this.db.Run( - `INSERT INTO remote_user_guild_nicks VALUES ( + `INSERT INTO remote_user_guild_nicks VALUES ( $remote_id, $guild_id, $nick )`, - { - guild_id: guildId, - nick, - remote_id: user.id, - }); + { + /* eslint-disable @typescript-eslint/camelcase */ + guild_id: guildId, + nick, + remote_id: user.id, + /* eslint-enable @typescript-eslint/camelcase */ + }); } } diff --git a/src/discordas.ts b/src/discordas.ts index 44200705294b7517467e332ff9f812684ad0c41f..c8267cb4844dcbd9fc4f2d6e81e3ce75a2fbb035 100644 --- a/src/discordas.ts +++ b/src/discordas.ts @@ -39,11 +39,12 @@ const commandOptions = [ { name: "help", alias: "h", type: Boolean }, ]; -function generateRegistration(opts, registrationPath) { +function generateRegistration(opts, registrationPath: string): void { if (!opts.url) { throw Error("'url' not given in command line opts, cannot generate registration file"); } const reg = { + /* eslint-disable @typescript-eslint/camelcase */ as_token: uuid(), hs_token: uuid(), id: "discord-bridge", @@ -66,14 +67,15 @@ function generateRegistration(opts, registrationPath) { rate_limited: false, sender_localpart: "_discord_bot", url: opts.url, + /* eslint-enable @typescript-eslint/camelcase */ } as IAppserviceRegistration; fs.writeFileSync(registrationPath, yaml.safeDump(reg)); } -function setupLogging() { +function setupLogging(): void { const logMap = new Map<string, Log>(); - // tslint:disable-next-line:no-any - const logFunc = (level: string, module: string, args: any[]) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const logFunc = (level: string, module: string, args: any[]): void => { if (!Array.isArray(args)) { args = [args]; } @@ -81,7 +83,7 @@ function setupLogging() { // Spammy logs begon return; } - const mod = "bot-sdk" + module; + const mod = `bot-sdk${module}`; let logger = logMap.get(mod); if (!logger) { logger = new Log(mod); @@ -91,21 +93,21 @@ function setupLogging() { }; LogService.setLogger({ - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any debug: (mod: string, args: any[]) => logFunc("silly", mod, args), - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any error: (mod: string, args: any[]) => logFunc("error", mod, args), - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any info: (mod: string, args: any[]) => logFunc("info", mod, args), - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any warn: (mod: string, args: any[]) => logFunc("warn", mod, args), }); } -async function run() { +async function run(): Promise<void> { const opts = cliArgs(commandOptions); if (opts.help) { - /* tslint:disable:no-console */ + // eslint-disable-next-line no-console console.log(usage([ { content: "The matrix appservice for discord", @@ -187,7 +189,7 @@ async function run() { }); if (config.bridge.disablePortalBridging !== true) { - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any appservice.on("query.room", async (roomAlias: string, createRoom: (opts: any) => Promise<void>) => { try { const createRoomOpts = await roomhandler.OnAliasQuery(roomAlias); diff --git a/src/log.ts b/src/log.ts index 9eb99981753227b80a915a4d90aedb6c3abc63fc..085b7b223634139d70d020bfb9dee8ce71a4d67a 100644 --- a/src/log.ts +++ b/src/log.ts @@ -24,21 +24,21 @@ const FORMAT_FUNC = format.printf((info) => { }); export class Log { - public static get level() { + public static get level(): string { return this.logger.level; } - public static set level(level) { + public static set level(level: string) { this.logger.level = level; } - public static Configure(config: DiscordBridgeConfigLogging) { + public static Configure(config: DiscordBridgeConfigLogging): void { // Merge defaults. Log.config = Object.assign(new DiscordBridgeConfigLogging(), config); Log.setupLogger(); } - public static ForceSilent() { + public static ForceSilent(): void { new Log("Log").warn("Log set to silent"); Log.logger.silent = true; } @@ -50,7 +50,7 @@ export class Log { return ["silly", "verbose", "info", "http", "warn", "error", "silent"].includes(level); } - private static setupLogger() { + private static setupLogger(): void { if (Log.logger) { Log.logger.close(); } @@ -103,41 +103,40 @@ export class Log { maxSize: config.maxSize, }; - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any return new (transports as any).DailyRotateFile(opts); } - public warning = this.warn; - constructor(private module: string) { } - // tslint:disable-next-line no-any - public error(...msg: any[]) { + public error(...msg: unknown[]): void { this.log("error", msg); } - // tslint:disable-next-line no-any - public warn(...msg: any[]) { + public warn(...msg: unknown[]): void { this.log("warn", msg); } - // tslint:disable-next-line no-any - public info(...msg: any[]) { + public warning(...msg: unknown[]): void { + this.warn(...msg); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public info(...msg: unknown[]): void { this.log("info", msg); } - // tslint:disable-next-line no-any - public verbose(...msg: any[]) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public verbose(...msg: unknown[]): void { this.log("verbose", msg); } - // tslint:disable-next-line no-any - public silly(...msg: any[]) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + public silly(...msg: unknown[]): void { this.log("silly", msg); } - // tslint:disable-next-line no-any - private log(level: string, msg: any[]) { + private log(level: string, msg: unknown[]): void { if (!Log.logger) { // We've not configured the logger yet, so create a basic one. Log.config = new DiscordBridgeConfigLogging(); diff --git a/src/matrixcommandhandler.ts b/src/matrixcommandhandler.ts index da9d97fad47dd1b7e4f066e0cb037d1e54a9e21c..536b2b7002374ad6ebbf93d9c3d72773df1f8baa 100644 --- a/src/matrixcommandhandler.ts +++ b/src/matrixcommandhandler.ts @@ -26,11 +26,9 @@ import { IRoomStoreEntry } from "./db/roomstore"; import * as markdown from "marked"; const log = new Log("MatrixCommandHandler"); -/* tslint:disable:no-magic-numbers */ const PROVISIONING_DEFAULT_POWER_LEVEL = 50; const PROVISIONING_DEFAULT_USER_POWER_LEVEL = 0; const ROOM_CACHE_MAXAGE_MS = 15 * 60 * 1000; -/* tslint:enable:no-magic-numbers */ export class MatrixCommandHandler { private botJoinedRooms: Set<string> = new Set(); // roomids @@ -59,7 +57,7 @@ export class MatrixCommandHandler { const actions: ICommandActions = { bridge: { description: "Bridges this room to a Discord channel", - // tslint:disable prefer-template + /* eslint-disable prefer-template */ help: "How to bridge a Discord guild:\n" + "1. Invite the bot to your Discord guild using this link: " + Util.GetBotLink(this.config) + "\n" + "2. Invite me to the matrix room you'd like to bridge\n" + @@ -69,7 +67,7 @@ export class MatrixCommandHandler { " Note: The Guild ID and Channel ID can be retrieved from the URL in your web browser.\n" + " The URL is formatted as https://discordapp.com/channels/GUILD_ID/CHANNEL_ID\n" + "5. Enjoy your new bridge!", - // tslint:enable prefer-template + /* eslint-enable prefer-template */ params: ["guildId", "channelId"], permission: { cat: "events", @@ -142,7 +140,7 @@ export class MatrixCommandHandler { await this.provisioner.UnbridgeChannel(res.channel, event.room_id); return "This room has been unbridged"; } catch (err) { - log.error("Error while unbridging room " + event.room_id); + log.error(`Error while unbridging room ${event.room_id}`); log.error(err); return "There was an error unbridging this room. " + "Please try again later or contact the bridge operator."; @@ -197,10 +195,12 @@ export class MatrixCommandHandler { const reply = await Util.ParseCommand("!discord", event.content!.body!, actions, parameters, permissionCheck); const formattedReply = markdown(reply); await this.bridge.botClient.sendMessage(event.room_id, { + /* eslint-disable @typescript-eslint/camelcase */ body: reply, format: "org.matrix.custom.html", formatted_body: formattedReply, msgtype: "m.notice", + /* eslint-enable @typescript-eslint/camelcase */ }); } diff --git a/src/matrixroomhandler.ts b/src/matrixroomhandler.ts index dfadeec7292866091b2f58cc95ebd6434730d67c..6689fa7372c0f6818143d206f458ec229a42197b 100644 --- a/src/matrixroomhandler.ts +++ b/src/matrixroomhandler.ts @@ -25,7 +25,6 @@ import { DbRoomStore, MatrixStoreRoom, RemoteStoreRoom } from "./db/roomstore"; import { Appservice, Intent, IApplicationServiceProtocol } from "matrix-bot-sdk"; const ICON_URL = "https://matrix.org/_matrix/media/r0/download/matrix.org/mlxoESwIsTbJrfXyAAogrNxA"; -/* tslint:disable:no-magic-numbers */ const HTTP_UNSUPPORTED = 501; const ROOM_NAME_PARTS = 2; const PROVISIONING_DEFAULT_POWER_LEVEL = 50; @@ -42,7 +41,6 @@ const JOIN_ROOM_SCHEDULE = [ 300000, // 5 minutes 900000, // 15 minutes ]; -/* tslint:enable:no-magic-numbers */ export class MatrixRoomHandler { private botUserId: string; @@ -60,13 +58,14 @@ export class MatrixRoomHandler { this.tpGetProtocol(protocol) .then(cb) .catch((err) => log.warn("Failed to get protocol", err)); - }); + } + ); - // tslint:disable-next-line:no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any this.bridge.on("thirdparty.location.remote", (protocol: string, fields: any, cb: (response: any) => void) => { this.tpGetLocation(protocol, fields) - .then(cb) - .catch((err) => log.warn("Failed to get remote locations", err)); + .then(cb) + .catch((err) => log.warn("Failed to get remote locations", err)); }); // These are not supported. @@ -81,7 +80,7 @@ export class MatrixRoomHandler { }); } - public async OnAliasQueried(alias: string, roomId: string) { + public async OnAliasQueried(alias: string, roomId: string): Promise<void> { log.verbose(`Got OnAliasQueried for ${alias} ${roomId}`); let channel: Discord.GuildChannel; try { @@ -119,9 +118,9 @@ export class MatrixRoomHandler { let delay = this.config.limits.roomGhostJoinDelay; for (const member of (channel as Discord.TextChannel).members.array()) { if (member.id === this.discord.GetBotId()) { - continue; + continue; } - promiseList.push((async () => { + promiseList.push((async (): Promise<void> => { await Util.DelayedPromise(delay); log.info(`UserSyncing ${member.id}`); try { @@ -139,7 +138,7 @@ export class MatrixRoomHandler { await Promise.all(promiseList); } - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any public async OnAliasQuery(alias: string): Promise<any> { const aliasLocalpart = alias.substring("#".length, alias.indexOf(":")); log.info("Got request for #", aliasLocalpart); @@ -161,6 +160,7 @@ export class MatrixRoomHandler { const instances = {}; for (const guild of this.discord.GetGuilds()) { instances[guild.name] = { + /* eslint-disable @typescript-eslint/camelcase */ bot_user_id: this.botUserId, desc: guild.name, fields: { @@ -168,9 +168,11 @@ export class MatrixRoomHandler { }, icon: guild.iconURL || ICON_URL, network_id: guild.id, + /* eslint-enable @typescript-eslint/camelcase */ }; } return { + /* eslint-disable @typescript-eslint/camelcase */ field_types: { // guild_name: { // regexp: "\S.{0,98}\S", @@ -201,10 +203,11 @@ export class MatrixRoomHandler { instances, location_fields: ["guild_id", "channel_name"], user_fields: ["username", "discriminator"], + /* eslint-enable @typescript-eslint/camelcase */ }; } - // tslint:disable-next-line no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any public async tpGetLocation(protocol: string, fields: any): Promise<IThirdPartyLookup[]> { log.info("Got location request ", protocol, fields); const chans = this.discord.ThirdpartySearchForChannels(fields.guild_id, fields.channel_name); @@ -213,7 +216,7 @@ export class MatrixRoomHandler { private async joinRoom(intent: Intent, roomIdOrAlias: string, member?: Discord.GuildMember): Promise<void> { let currentSchedule = JOIN_ROOM_SCHEDULE[0]; - const doJoin = async () => { + const doJoin = async (): Promise<void> => { await Util.DelayedPromise(currentSchedule); if (member) { await this.discord.UserSyncroniser.JoinRoom(member, roomIdOrAlias); @@ -221,7 +224,7 @@ export class MatrixRoomHandler { await intent.joinRoom(roomIdOrAlias); } }; - const errorHandler = async (err) => { + const errorHandler = async (err): Promise<void> => { log.error(`Error joining room ${roomIdOrAlias} as ${intent.userId}`); log.error(err); const idx = JOIN_ROOM_SCHEDULE.indexOf(currentSchedule); @@ -245,17 +248,23 @@ export class MatrixRoomHandler { } } - private async createMatrixRoom(channel: Discord.TextChannel, - alias: string, aliasLocalpart: string) { + private async createMatrixRoom( + channel: Discord.TextChannel, + alias: string, + aliasLocalpart: string + ) { const remote = new RemoteStoreRoom(`discord_${channel.guild.id}_${channel.id}`, { + /* eslint-disable @typescript-eslint/camelcase */ discord_channel: channel.id, discord_guild: channel.guild.id, discord_type: "text", update_icon: 1, update_name: 1, update_topic: 1, + /* eslint-enable @typescript-eslint/camelcase */ }); const creationOpts = { + /* eslint-disable @typescript-eslint/camelcase */ initial_state: [ { content: { @@ -267,6 +276,7 @@ export class MatrixRoomHandler { ], room_alias_name: aliasLocalpart, visibility: this.config.room.defaultVisibility, + /* eslint-enable @typescript-eslint/camelcase */ }; // We need to tempoarily store this until we know the room_id. await this.roomStore.linkRooms( diff --git a/src/metrics.ts b/src/metrics.ts index 52f4028c0fc8983add64d80b427e9d96ab2320f2..f11513b89d1c9678aafe4c717536e4c8013ada49 100644 --- a/src/metrics.ts +++ b/src/metrics.ts @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +/* eslint-disable max-classes-per-file, @typescript-eslint/no-empty-function */ import { Gauge, Counter, Histogram, default as promClient } from "prom-client"; import { Log } from "./log"; @@ -72,11 +73,9 @@ export class PrometheusBridgeMetrics implements IBridgeMetrics { // TODO: Bind this for every user. this.httpServer = http.createServer((req, res) => { if (req.method !== "GET" || req.url !== "/metrics") { - // tslint:disable-next-line:no-magic-numbers res.writeHead(404, "Not found"); res.end(); } - // tslint:disable-next-line:no-magic-numbers res.writeHead(200, "OK", {"Content-Type": promClient.register.contentType}); res.write(promClient.register.metrics()); res.end(); diff --git a/src/store.ts b/src/store.ts index c7574cb81dabb3db147dd77596144cf5d9d841cb..88cdc87a358c0d39fcc6110beaa5645561bda6bb 100644 --- a/src/store.ts +++ b/src/store.ts @@ -249,7 +249,7 @@ export class DiscordStore implements IAppserviceStorageProvider { } } - // tslint:disable-next-line no-any callable-types + // eslint-disable-next-line @typescript-eslint/no-explicit-any callable-types public async Get<T extends IDbData>(dbType: {new(): T; }, params: any): Promise<T|null> { const dType = new dbType(); log.silly(`get <${dType.constructor.name} with params ${params}>`); diff --git a/src/structures/timedcache.ts b/src/structures/timedcache.ts index 93424af9d488d493439bd4294dc969297f79eeee..06b2c1288ee4174bbfa7a4c07c443f8e72f3e92b 100644 --- a/src/structures/timedcache.ts +++ b/src/structures/timedcache.ts @@ -1,3 +1,6 @@ +import { Log } from "../log"; +const log = new Log("Timedcache"); + interface ITimedValue<V> { value: V; ts: number; @@ -20,7 +23,10 @@ export class TimedCache<K, V> implements Map<K, V> { public forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void|Promise<void>): void { for (const item of this) { - callbackfn(item[1], item[0], this); + const potentialPromise = callbackfn(item[1], item[0], this); + if (potentialPromise) { + potentialPromise.catch(log.warn); + } } } @@ -73,7 +79,7 @@ export class TimedCache<K, V> implements Map<K, V> { } if (item.done) { // Typscript doesn't like us returning undefined for value, which is dumb. - // tslint:disable-next-line: no-any + // eslint-disable-next-line @typescript-eslint/no-explicit-any return {done: true, value: undefined} as any as IteratorResult<[K, V]>; } return {done: false, value: [item.value[0], filteredValue]} as IteratorResult<[K, V]>; diff --git a/test/db/test_roomstore.ts b/test/db/test_roomstore.ts index 273ff7057dc260ed26c3f6fa0b352f9b364019a7..f9b0b0fe08c4820578070eb616ebfb64cd28416f 100644 --- a/test/db/test_roomstore.ts +++ b/test/db/test_roomstore.ts @@ -13,6 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ +/* eslint-disable @typescript-eslint/camelcase */ import { expect } from "chai"; import { DiscordStore, CURRENT_SCHEMA } from "../../src/store"; diff --git a/test/mocks/appservicemock.ts b/test/mocks/appservicemock.ts index 5aaf9ca2e873416efaaea1aea49e688d36a91dde..4de03ee482d1eb6f56606cb805693af62dc7a4e7 100644 --- a/test/mocks/appservicemock.ts +++ b/test/mocks/appservicemock.ts @@ -240,7 +240,7 @@ class MatrixClientMock extends AppserviceMockBase { public async uploadContent(data: Buffer, contentType: string, filename: string = "noname") { this.funcCalled("uploadContent", data, contentType, filename); - return "mxc://" + filename; + return `mxc://${filename}`; } public mxcToHttp(mxcUrl: string) { diff --git a/test/test_channelsyncroniser.ts b/test/test_channelsyncroniser.ts index f75d6d2040b164e9dbdc87b7b256990e01d15f8b..a98045bf1747a187f0cb367f403bd64a93ae69f5 100644 --- a/test/test_channelsyncroniser.ts +++ b/test/test_channelsyncroniser.ts @@ -214,9 +214,7 @@ describe("ChannelSyncroniser", () => { const {channelSync} = CreateChannelSync(testStore); const chans = await channelSync.GetRoomIdsFromChannel(chan as any); - /* tslint:disable:no-magic-numbers */ expect(chans.length).equals(2); - /* tslint:enable:no-magic-numbers */ expect(chans[0]).equals("!1:localhost"); expect(chans[1]).equals("!2:localhost"); }); diff --git a/test/test_discordcommandhandler.ts b/test/test_discordcommandhandler.ts index f2e0c7b3800318bb9cd2c79f8576e9c8ae566c3a..d29ee9b09a9f157e953c283451786626d2b48e9e 100644 --- a/test/test_discordcommandhandler.ts +++ b/test/test_discordcommandhandler.ts @@ -39,12 +39,12 @@ function createCH(opts: any = {}) { const discord = { ChannelSyncroniser: cs, Provisioner: { - HasPendingRequest: (chan) => true, + HasPendingRequest: (chan): boolean => true, MarkApproved: async (chan, member, approved) => { MARKED = approved ? 1 : 0; return approved; }, - UnbridgeChannel: () => { + UnbridgeChannel: (): void => { ROOMSUNBRIDGED++; }, }, @@ -52,7 +52,7 @@ function createCH(opts: any = {}) { const discordCommandHndlr = (Proxyquire("../src/discordcommandhandler", { "./util": { Util: { - GetMxidFromName: () => { + GetMxidFromName: (): string => { return "@123456:localhost"; }, ParseCommand: Util.ParseCommand, @@ -69,7 +69,7 @@ describe("DiscordCommandHandler", () => { const guild = new MockGuild("456", [channel]); channel.guild = guild; const member: any = new MockMember("123456", "blah"); - member.hasPermission = () => { + member.hasPermission = (): boolean => { return true; }; const message = { @@ -86,7 +86,7 @@ describe("DiscordCommandHandler", () => { const guild = new MockGuild("456", [channel, (new MockChannel("456"))]); channel.guild = guild; const member: any = new MockMember("123456", "blah"); - member.hasPermission = () => { + member.hasPermission = (): boolean => { return true; }; const message = { @@ -95,7 +95,6 @@ describe("DiscordCommandHandler", () => { member, }; await handler.Process(message); - // tslint:disable-next-line:no-magic-numbers expect(bridge.botIntent.underlyingClient.wasCalled("kickUser")).to.equal(2); }); it("will deny permission", async () => { @@ -104,7 +103,7 @@ describe("DiscordCommandHandler", () => { const guild = new MockGuild("456", [channel]); channel.guild = guild; const member: any = new MockMember("123456", "blah"); - member.hasPermission = () => { + member.hasPermission = (): boolean => { return false; }; const message = { @@ -121,7 +120,7 @@ describe("DiscordCommandHandler", () => { const guild = new MockGuild("456", [channel]); channel.guild = guild; const member: any = new MockMember("123456", "blah"); - member.hasPermission = () => { + member.hasPermission = (): boolean => { return true; }; const message = { @@ -138,7 +137,7 @@ describe("DiscordCommandHandler", () => { const guild = new MockGuild("456", [channel]); channel.guild = guild; const member: any = new MockMember("123456", "blah"); - member.hasPermission = () => { + member.hasPermission = (): boolean => { return true; }; const message = { @@ -150,12 +149,12 @@ describe("DiscordCommandHandler", () => { expect(bridge.botIntent.underlyingClient.wasCalled("unbanUser")).to.equal(1); }); it("handles !matrix approve", async () => { - const {handler, bridge} = createCH(); + const {handler} = createCH(); const channel = new MockChannel("123"); const guild = new MockGuild("456", [channel]); channel.guild = guild; const member: any = new MockMember("123456", "blah"); - member.hasPermission = () => { + member.hasPermission = (): boolean => { return true; }; const message = { @@ -172,7 +171,7 @@ describe("DiscordCommandHandler", () => { const guild = new MockGuild("456", [channel]); channel.guild = guild; const member: any = new MockMember("123456", "blah"); - member.hasPermission = () => { + member.hasPermission = (): boolean => { return true; }; const message = { @@ -189,7 +188,7 @@ describe("DiscordCommandHandler", () => { const guild = new MockGuild("456", [channel]); channel.guild = guild; const member: any = new MockMember("123456", "blah"); - member.hasPermission = () => { + member.hasPermission = (): boolean => { return true; }; const message = { diff --git a/test/test_log.ts b/test/test_log.ts index ca9b044a81cedd23ca4e91042c3e4be8c7a9aeeb..b3ad9d11dc3aa0470a56cce55ef9bb1cbf3a4911 100644 --- a/test/test_log.ts +++ b/test/test_log.ts @@ -26,7 +26,7 @@ let loggedMessages: any[] = []; const WinstonMock = { createLogger: (format, transports) => { return createdLogger = { - close: () => { }, + close: (): void => { }, format, log: (type, ...msg) => { loggedMessages = loggedMessages.concat(msg); diff --git a/tools/addRoomsToDirectory.ts b/tools/addRoomsToDirectory.ts index 520a24774ddccb814c9c8451923e365cb6ca1828..6b06ac7b9324bd9d3fe3a2fde04edcc98b250db7 100644 --- a/tools/addRoomsToDirectory.ts +++ b/tools/addRoomsToDirectory.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* tslint:disable:no-console */ +/* eslint-disable no-console */ /** * Allows you to become an admin for a room the bot is in control of. */ @@ -53,30 +53,32 @@ const optionDefinitions = [ const options = args(optionDefinitions); if (options.help) { - /* tslint:disable:no-console */ + /* eslint-disable no-console */ console.log(usage([ - { - content: "A tool to set all the bridged rooms to visible in the directory.", - header: "Add rooms to directory", - }, - { - header: "Options", - optionList: optionDefinitions, - }, + { + content: "A tool to set all the bridged rooms to visible in the directory.", + header: "Add rooms to directory", + }, + { + header: "Options", + optionList: optionDefinitions, + }, ])); process.exit(0); } const {store, appservice} = ToolsHelper.getToolDependencies(options.config, options.registration); -async function run() { +async function run(): Promise<void> { try { await store!.init(); } catch (e) { log.error(`Failed to load database`, e); } let rooms = await store!.roomStore.getEntriesByRemoteRoomData({ + /* eslint-disable @typescript-eslint/camelcase */ discord_type: "text", + /* eslint-disable @typescript-eslint/camelcase */ }); rooms = rooms.filter((r) => r.remote && r.remote.get("plumbed") !== true ); log.info(`Got ${rooms.length} rooms to set`); diff --git a/tools/addbot.ts b/tools/addbot.ts index d505fddd9045036e4822aa37bf62889509803ec8..6fd4517f351edf4585b274d0a1ed8784b3a3b84f 100644 --- a/tools/addbot.ts +++ b/tools/addbot.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* tslint:disable:no-bitwise no-console no-var-requires */ +/* eslint-disable no-bitwise, no-console */ /** * Generates a URL you can use to authorize a bot with a guild. */ @@ -26,42 +26,42 @@ import { Util } from "../src/util"; import { DiscordBridgeConfig } from "../src/config"; const optionDefinitions = [ - { - alias: "h", - description: "Display this usage guide.", - name: "help", - type: Boolean, - }, - { - alias: "c", - defaultValue: "config.yaml", - description: "The AS config file.", - name: "config", - type: String, - typeLabel: "<config.yaml>", - }, + { + alias: "h", + description: "Display this usage guide.", + name: "help", + type: Boolean, + }, + { + alias: "c", + defaultValue: "config.yaml", + description: "The AS config file.", + name: "config", + type: String, + typeLabel: "<config.yaml>", + }, ]; const options = args(optionDefinitions); if (options.help) { - /* tslint:disable:no-console */ - console.log(usage([ - { - content: "A tool to obtain the Discord bot invitation URL.", - header: "Add bot", - }, - { - header: "Options", - optionList: optionDefinitions, - }, - ])); - process.exit(0); + // eslint-disable-next-line no-console + console.log(usage([ + { + content: "A tool to obtain the Discord bot invitation URL.", + header: "Add bot", + }, + { + header: "Options", + optionList: optionDefinitions, + }, + ])); + process.exit(0); } const yamlConfig = yaml.safeLoad(fs.readFileSync(options.config, "utf8")); if (yamlConfig === null || typeof yamlConfig !== "object") { - throw Error("You have an error in your discord config."); + throw Error("You have an error in your discord config."); } const url = Util.GetBotLink(yamlConfig as DiscordBridgeConfig); console.log(`Go to ${url} to invite the bot into a guild.`); diff --git a/tools/adminme.ts b/tools/adminme.ts index 1504d0ec5788c686a6e052f5c0bbaa99fbe14416..06e756da26241b9f5a589d5c66b76a44178041c8 100644 --- a/tools/adminme.ts +++ b/tools/adminme.ts @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -/* tslint:disable:no-console */ +/* eslint-disable no-console */ /** * Allows you to become an admin for a room that the bot is in control of. */ @@ -71,7 +71,7 @@ const optionDefinitions = [ const options = args(optionDefinitions); if (options.help) { - /* tslint:disable:no-console */ + /* eslint-disable no-console */ console.log(usage([ { content: "A tool to give a user a power level in a bot user controlled room.", diff --git a/tools/chanfix.ts b/tools/chanfix.ts index 9b293e891b6457d3a08a1adc179abc7530963cf3..5c186c61419a99a0e5889b90925969f147fc8c99 100644 --- a/tools/chanfix.ts +++ b/tools/chanfix.ts @@ -51,7 +51,7 @@ const optionDefinitions = [ const options = args(optionDefinitions); if (options.help) { - /* tslint:disable:no-console */ + /* eslint-disable no-console */ console.log(usage([ { content: "A tool to fix channels of rooms already bridged " + diff --git a/tools/ghostfix.ts b/tools/ghostfix.ts index 88dee4380a129063472c55036eafeaa0d2042251..d5f6b40683e27d6910b6f24ffa68a6670dbfc12a 100644 --- a/tools/ghostfix.ts +++ b/tools/ghostfix.ts @@ -24,7 +24,6 @@ import { ToolsHelper } from "./toolshelper"; const log = new Log("GhostFix"); // Note: The schedule must not have duplicate values to avoid problems in positioning. -/* tslint:disable:no-magic-numbers */ // Disabled because it complains about the values in the array const JOIN_ROOM_SCHEDULE = [ 0, // Right away 1000, // 1 second @@ -32,7 +31,6 @@ const JOIN_ROOM_SCHEDULE = [ 300000, // 5 minutes 900000, // 15 minutes ]; -/* tslint:enable:no-magic-numbers */ const optionDefinitions = [ { @@ -62,17 +60,17 @@ const optionDefinitions = [ const options = args(optionDefinitions); if (options.help) { - /* tslint:disable:no-console */ + /* eslint-disable no-console */ console.log(usage([ - { - content: "A tool to fix usernames of ghosts already in " + - "matrix rooms, to make sure they represent the correct discord usernames.", - header: "Fix usernames of joined ghosts", - }, - { - header: "Options", - optionList: optionDefinitions, - }, + { + content: "A tool to fix usernames of ghosts already in " + + "matrix rooms, to make sure they represent the correct discord usernames.", + header: "Fix usernames of joined ghosts", + }, + { + header: "Options", + optionList: optionDefinitions, + }, ])); process.exit(0); } @@ -132,4 +130,4 @@ async function run() { process.exit(0); } -run(); // tslint:disable-line no-floating-promises +run(); // eslint-disable no-floating-promises diff --git a/tools/userClientTools.ts b/tools/userClientTools.ts index a6d923f7899075f7ebb8eba544735d94f2ac87fa..a9591018ac5d4904ecf2d8ff4ad7142633df91ad 100644 --- a/tools/userClientTools.ts +++ b/tools/userClientTools.ts @@ -57,7 +57,7 @@ const optionDefinitions = [ const options = args(optionDefinitions); if (options.help || (options.add && options.remove) || !(options.add || options.remove)) { - /* tslint:disable:no-console */ + /* eslint-disable no-console */ console.log(usage([ { content: "A tool to give a user a power level in a bot user controlled room.", diff --git a/tsconfig.json b/tsconfig.json index e57e4513c483a95d650c220c37987a8829a33ef0..19323e419200383ab52c0675579a455fbe48050e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -13,6 +13,7 @@ "compileOnSave": true, "include": [ "src/**/*", + "test/**/*", "tools/**/*", ] } diff --git a/tslint.json b/tslint.json deleted file mode 100644 index 9b0ff6f8d641ed7cb9ae37cc0c24343e655e4306..0000000000000000000000000000000000000000 --- a/tslint.json +++ /dev/null @@ -1,38 +0,0 @@ -{ - "extends": "tslint:recommended", - "rules": { - "ordered-imports": false, - "no-trailing-whitespace": "error", - "max-classes-per-file": { - "severity": "warning" - }, - "object-literal-sort-keys": "off", - "no-any": true, - "arrow-return-shorthand": true, - "prefer-for-of": true, - "typedef": { - "severity": "warning" - }, - "await-promise": [true], - "curly": true, - "no-empty": false, - "no-invalid-this": true, - "no-string-throw": { - "severity": "warning" - }, - "no-unused-expression": true, - "prefer-const": true, - "indent": [true, "spaces", 4], - "max-file-line-count": { - "severity": "warning", - "options": [500] - }, - "no-duplicate-imports": true, - "array-type": [true, "array"], - "promise-function-async": true, - "no-bitwise": true, - "no-debugger": true, - "no-floating-promises": true, - "prefer-template": [true, "allow-single-concat"] - } -} diff --git a/yarn.lock b/yarn.lock index 138ce0e20135a001e4a73d009768e1f2ccf1f31e..d2cb11abd4fdb0e9a775917685a885e5ef7e9c79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -200,6 +200,22 @@ combined-stream "^1.0.8" mime-types "^2.1.12" +"@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" + "@istanbuljs/load-nyc-config@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" @@ -277,6 +293,11 @@ dependencies: "@types/node" "*" +"@types/eslint-visitor-keys@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#1ee30d79544ca84d68d4b3cdb0af4f205663dd2d" + integrity sha512-OCutwjDZ4aFS6PB1UZ988C4YgwlBHJd6wCeQqaLdmadZ/7e+w79+hbMUFC1QXDNCmdyoRfAFdm0RypzwR+Qpag== + "@types/express-serve-static-core@*": version "4.17.14" resolved "https://registry.yarnpkg.com/@types/express-serve-static-core/-/express-serve-static-core-4.17.14.tgz#cabf91debeeb3cb04b798e2cff908864e89b6106" @@ -321,6 +342,11 @@ resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.5.tgz#136d5e6a57a931e1cce6f9d8126aa98a9c92a6bb" integrity sha512-JCcp6J0GV66Y4ZMDAQCXot4xprYB+Zfd3meK9+INSJeVZwJmHAW30BBEEkPzXswMXuiyReUGOP3GxrADc9wPww== +"@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/keyv@*": version "3.1.1" resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.1.tgz#e45a45324fca9dab716ab1230ee249c9fb52cfa7" @@ -391,6 +417,49 @@ "@types/mime" "*" "@types/node" "*" +"@typescript-eslint/eslint-plugin@^2.14.0": + version "2.34.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9" + integrity sha512-4zY3Z88rEE99+CNvTbXSyovv2z9PNOVffTWD2W8QF5s2prBQtwN2zadqERcrHpcR7O/+KMI3fcTAmUUhK/iQcQ== + dependencies: + "@typescript-eslint/experimental-utils" "2.34.0" + functional-red-black-tree "^1.0.1" + regexpp "^3.0.0" + tsutils "^3.17.1" + +"@typescript-eslint/experimental-utils@2.34.0": + version "2.34.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-2.34.0.tgz#d3524b644cdb40eebceca67f8cf3e4cc9c8f980f" + integrity sha512-eS6FTkq+wuMJ+sgtuNTtcqavWXqsflWcfBnlYhg/nS4aZ1leewkXGbvBhaapn1q6qf4M71bsR1tez5JTRMuqwA== + dependencies: + "@types/json-schema" "^7.0.3" + "@typescript-eslint/typescript-estree" "2.34.0" + eslint-scope "^5.0.0" + eslint-utils "^2.0.0" + +"@typescript-eslint/parser@^2.14.0": + version "2.34.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-2.34.0.tgz#50252630ca319685420e9a39ca05fe185a256bc8" + integrity sha512-03ilO0ucSD0EPTw2X4PntSIRFtDPWjrVq7C3/Z3VQHRC7+13YB55rcJI3Jt+YgeHbjUdJPcPa7b23rXCBokuyA== + dependencies: + "@types/eslint-visitor-keys" "^1.0.0" + "@typescript-eslint/experimental-utils" "2.34.0" + "@typescript-eslint/typescript-estree" "2.34.0" + eslint-visitor-keys "^1.1.0" + +"@typescript-eslint/typescript-estree@2.34.0": + version "2.34.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-2.34.0.tgz#14aeb6353b39ef0732cc7f1b8285294937cf37d5" + integrity sha512-OMAr+nJWKdlVM9LOqCqh3pQQPwxHAN7Du8DR6dmwCrAmxtiXQnhHJ6tBNtf+cggqfo51SG/FCwnKhXCIM7hnVg== + dependencies: + debug "^4.1.1" + eslint-visitor-keys "^1.1.0" + glob "^7.1.6" + is-glob "^4.0.1" + lodash "^4.17.15" + semver "^7.3.2" + tsutils "^3.17.1" + "@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" @@ -411,6 +480,16 @@ accepts@~1.3.7: mime-types "~2.1.24" negotiator "0.6.2" +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== + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -419,7 +498,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.12.3: +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== @@ -429,7 +508,7 @@ ajv@^6.12.3: json-schema-traverse "^0.4.1" uri-js "^4.2.2" -ansi-colors@4.1.1: +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== @@ -550,6 +629,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" @@ -702,11 +786,6 @@ buffer@^5.5.0: base64-js "^1.3.1" ieee754 "^1.1.13" -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" @@ -740,6 +819,11 @@ caching-transform@^4.0.0: package-hash "^4.0.0" write-file-atomic "^3.0.0" +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, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" @@ -767,7 +851,7 @@ chai@^4.2.0: pathval "^1.1.0" type-detect "^4.0.5" -chalk@^2.0.0, 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== @@ -932,11 +1016,6 @@ command-line-usage@^6.1.0: table-layout "^1.0.0" typical "^5.2.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== - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -986,7 +1065,7 @@ 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@^7.0.0: +cross-spawn@^7.0.0, 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== @@ -1021,6 +1100,13 @@ debug@4.2.0, debug@^4.1.0, debug@^4.1.1: dependencies: ms "2.1.2" +debug@^4.0.1: + version "4.3.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.1.tgz#f0d229c505e0c6d8c49ac553d1b13dc183f6b2ee" + integrity sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ== + dependencies: + ms "2.1.2" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1057,6 +1143,11 @@ deep-extend@^0.6.0, deep-extend@~0.6.0: resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== +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= + default-require-extensions@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.0.tgz#e03f93aac9b2b6443fc52e5e4a37b3ad9ad8df96" @@ -1112,6 +1203,13 @@ diff@4.0.2, diff@^4.0.1: node-emoji "^1.10.0" simple-markdown "^0.7.2" +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" @@ -1182,6 +1280,13 @@ end-of-stream@^1.1.0, end-of-stream@^1.4.1: dependencies: once "^1.4.0" +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: + 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" @@ -1207,11 +1312,117 @@ escape-string-regexp@^1.0.5: resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +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.4.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" @@ -1293,6 +1504,11 @@ fast-json-stable-stringify@^2.0.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" @@ -1303,6 +1519,13 @@ fecha@^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" + file-stream-rotator@^0.5.7: version "0.5.7" resolved "https://registry.yarnpkg.com/file-stream-rotator/-/file-stream-rotator-0.5.7.tgz#868a2e5966f7640a17dd86eda0e4467c089f6286" @@ -1382,11 +1605,25 @@ find-up@^4.0.0, find-up@^4.1.0: locate-path "^5.0.0" path-exists "^4.0.0" +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: + 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" @@ -1456,6 +1693,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +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= + gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" @@ -1509,7 +1751,7 @@ github-from-package@0.0.0: resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4= -glob-parent@~5.1.0: +glob-parent@^5.0.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== @@ -1521,7 +1763,7 @@ glob-to-regexp@^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.6, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: +glob@7.1.6, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.1.6" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== @@ -1538,6 +1780,13 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +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" + got@^11.6.0: version "11.8.0" resolved "https://registry.yarnpkg.com/got/-/got-11.8.0.tgz#be0920c3586b07fd94add3b5b27cb28f49e6545f" @@ -1702,6 +1951,19 @@ ieee754@^1.1.13: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +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== + +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" @@ -1781,7 +2043,7 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== -is-glob@^4.0.1, is-glob@~4.0.1: +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== @@ -1937,6 +2199,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" @@ -1971,6 +2238,14 @@ kuler@^2.0.0: resolved "https://registry.yarnpkg.com/kuler/-/kuler-2.0.0.tgz#e2c570a3800388fb44407e851531c1d670b061b3" integrity sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A== +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" + locate-path@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" @@ -2008,7 +2283,7 @@ lodash.toarray@^4.4.0: resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= -lodash@4, lodash@^4.17.15, lodash@^4.17.19: +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== @@ -2275,6 +2550,11 @@ napi-build-utils@^1.0.1: resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806" integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg== +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" @@ -2429,6 +2709,18 @@ one-time@^1.0.0: dependencies: fn.name "1.x.x" +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: + 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-cancelable@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.0.0.tgz#4a3740f5bdaf5ed5d7c3e34882c6fb5d6b266a6e" @@ -2516,6 +2808,13 @@ packet-reader@1.0.0: resolved "https://registry.yarnpkg.com/packet-reader/-/packet-reader-1.0.0.tgz#9238e5480dedabacfe1fe3f2771063f164157d74" integrity sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ== +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" @@ -2701,6 +3000,11 @@ prebuild-install@^5.3.3: tunnel-agent "^0.6.0" which-pm-runs "^1.0.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== + prism-media@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/prism-media/-/prism-media-1.2.2.tgz#4f1c841f248b67d325a24b4e6b1a491b8f50a24f" @@ -2718,6 +3022,11 @@ process-on-spawn@^1.0.0: dependencies: fromentries "^1.2.0" +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== + prom-client@^12.0.0: version "12.0.0" resolved "https://registry.yarnpkg.com/prom-client/-/prom-client-12.0.0.tgz#9689379b19bd3f6ab88a9866124db9da3d76c6ed" @@ -2841,6 +3150,11 @@ reduce-flatten@^2.0.0: resolved "https://registry.yarnpkg.com/reduce-flatten/-/reduce-flatten-2.0.0.tgz#734fd84e65f375d7ca4465c69798c25c9d10ae27" integrity sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w== +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== + release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" @@ -2906,6 +3220,11 @@ resolve-alpn@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-alpn/-/resolve-alpn-1.0.0.tgz#745ad60b3d6aff4b4a48e01b8c0bdc70959e0e8c" integrity sha512-rTuiIEqFmGxne4IovivKSDzld2lWW9QCjqv80SYjPgf+gS35eaCAjaP54CCwGAwBtnCsvNLYtqxe1Nw+i6JEmA== +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve-from@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" @@ -2931,6 +3250,13 @@ responselike@^2.0.0: dependencies: lowercase-keys "^2.0.0" +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: + glob "^7.1.3" + rimraf@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -2970,7 +3296,7 @@ semver-closest@^0.1.0: dependencies: semver "^5.4.1" -semver@^5.3.0, semver@^5.4.1: +semver@^5.4.1: version "5.7.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== @@ -2980,6 +3306,11 @@ semver@^6.0.0, semver@^6.3.0: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +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" @@ -3081,6 +3412,15 @@ simple-swizzle@^0.2.2: dependencies: is-arrayish "^0.3.1" +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, source-map-support@^0.5.19: version "0.5.19" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.19.tgz#a98b62f86dcaf4f67399648c085291ab9e8fed61" @@ -3252,7 +3592,7 @@ strip-bom@^4.0.0: resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== -strip-json-comments@3.1.1: +strip-json-comments@3.1.1, strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== @@ -3293,6 +3633,16 @@ table-layout@^1.0.0: typical "^5.2.0" wordwrapjs "^4.0.0" +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: + ajv "^6.10.2" + lodash "^4.17.14" + slice-ansi "^2.1.0" + string-width "^3.0.0" + tar-fs@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.0.tgz#d1cdd121ab465ee0eb9ccde2d35049d3f3daf0d5" @@ -3348,6 +3698,11 @@ text-hex@1.0.x: 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-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -3389,34 +3744,15 @@ ts-node@^8.10.2: source-map-support "^0.5.17" yn "3.1.1" -tslib@^1.8.0, tslib@^1.8.1: +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.20.1: - 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" @@ -3437,12 +3773,19 @@ tweetnacl@^1.0.3: resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.3.tgz#ac0af71680458d8a6378d0d0d050ab1407d35596" integrity sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw== +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.0: +type-fest@^0.8.0, 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== @@ -3518,6 +3861,11 @@ uuid@^3.3.2, uuid@^3.3.3: resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== +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== + uuid@^8.3.1: version "8.3.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.1.tgz#2ba2e6ca000da60fce5a196954ab241131e05a31" @@ -3602,6 +3950,11 @@ 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== + wordwrapjs@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/wordwrapjs/-/wordwrapjs-4.0.0.tgz#9aa9394155993476e831ba8e59fb5795ebde6800" @@ -3648,6 +4001,13 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +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" + ws@^7.3.1: version "7.3.1" resolved "https://registry.yarnpkg.com/ws/-/ws-7.3.1.tgz#d0547bf67f7ce4f12a72dfe31262c68d7dc551c8"