12.106.0あっぷだて

This commit is contained in:
nullnyat
2022-02-11 18:10:12 +09:00
parent dd47d50679
commit 8402a9b665
52 changed files with 965 additions and 271 deletions

View File

@ -0,0 +1,64 @@
const RE2 = require('re2');
const { MigrationInterface, QueryRunner } = require("typeorm");
module.exports = class convertHardMutes1644010796173 {
name = 'convertHardMutes1644010796173'
async up(queryRunner) {
let entries = await queryRunner.query(`SELECT "userId", "mutedWords" FROM "user_profile"`);
for(let i = 0; i < entries.length; i++) {
let words = entries[i].mutedWords
.map(line => {
const regexp = line.join(" ").match(/^\/(.+)\/(.*)$/);
if (regexp) {
// convert regexp's
try {
new RE2(regexp[1], regexp[2]);
return `/${regexp[1]}/${regexp[2]}`;
} catch (err) {
// invalid regex, ignore it
return [];
}
} else {
// remove empty segments
return line.filter(x => x !== '');
}
})
// remove empty lines
.filter(x => !(Array.isArray(x) && x.length === 0));
await queryRunner.connection.createQueryBuilder()
.update('user_profile')
.set({
mutedWords: words
})
.where('userId = :id', { id: entries[i].userId })
.execute();
}
}
async down(queryRunner) {
let entries = await queryRunner.query(`SELECT "userId", "mutedWords" FROM "user_profile"`);
for(let i = 0; i < entries.length; i++) {
let words = entries[i].mutedWords
.map(line => {
if (Array.isArray(line)) {
return line;
} else {
// do not split regex at spaces again
return [line];
}
})
// remove empty lines
.filter(x => !(Array.isArray(x) && x.length === 0));
await queryRunner.connection.createQueryBuilder()
.update('user_profile')
.set({
mutedWords: words
})
.where('userId = :id', { id: entries[i].userId })
.execute();
}
}
}

View File

@ -0,0 +1,31 @@
const { MigrationInterface, QueryRunner } = require("typeorm");
module.exports = class chartV151644481657998 {
name = 'chartV151644481657998'
async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___instance_total"`);
await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___instance_inc"`);
await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___instance_dec"`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___instance_total"`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___instance_inc"`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___instance_dec"`);
await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___sub" smallint NOT NULL DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___pub" smallint NOT NULL DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___sub" smallint NOT NULL DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___pub" smallint NOT NULL DEFAULT '0'`);
}
async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___pub"`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" DROP COLUMN "___sub"`);
await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___pub"`);
await queryRunner.query(`ALTER TABLE "__chart__federation" DROP COLUMN "___sub"`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___instance_dec" smallint NOT NULL DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___instance_inc" smallint NOT NULL DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE "__chart_day__federation" ADD "___instance_total" integer NOT NULL DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___instance_dec" smallint NOT NULL DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___instance_inc" smallint NOT NULL DEFAULT '0'`);
await queryRunner.query(`ALTER TABLE "__chart__federation" ADD "___instance_total" integer NOT NULL DEFAULT '0'`);
}
}

View File

@ -0,0 +1,15 @@
const { MigrationInterface, QueryRunner } = require("typeorm");
module.exports = class followingIndexes1644551208096 {
name = 'followingIndexes1644551208096'
async up(queryRunner) {
await queryRunner.query(`CREATE INDEX "IDX_4ccd2239268ebbd1b35e318754" ON "following" ("followerHost") `);
await queryRunner.query(`CREATE INDEX "IDX_fcdafee716dfe9c3b5fde90f30" ON "following" ("followeeHost") `);
}
async down(queryRunner) {
await queryRunner.query(`DROP INDEX "public"."IDX_fcdafee716dfe9c3b5fde90f30"`);
await queryRunner.query(`DROP INDEX "public"."IDX_4ccd2239268ebbd1b35e318754"`);
}
}

View File

@ -123,7 +123,7 @@
"ms": "3.0.0-canary.1",
"multer": "1.4.4",
"nested-property": "4.0.0",
"node-fetch": "2.6.1",
"node-fetch": "2.6.7",
"nodemailer": "6.7.2",
"os-utils": "0.0.14",
"parse5": "6.0.1",

View File

@ -11,26 +11,31 @@ type UserLike = {
id: User['id'];
};
export async function checkWordMute(note: NoteLike, me: UserLike | null | undefined, mutedWords: string[][]): Promise<boolean> {
export async function checkWordMute(note: NoteLike, me: UserLike | null | undefined, mutedWords: Array<string | string[]>): Promise<boolean> {
// 自分自身
if (me && (note.userId === me.id)) return false;
const words = mutedWords
// Clean up
.map(xs => xs.filter(x => x !== ''))
.filter(xs => xs.length > 0);
if (words.length > 0) {
if (mutedWords.length > 0) {
if (note.text == null) return false;
const matched = words.some(and =>
and.every(keyword => {
const regexp = keyword.match(/^\/(.+)\/(.*)$/);
if (regexp) {
const matched = mutedWords.some(filter => {
if (Array.isArray(filter)) {
return filter.every(keyword => note.text!.includes(keyword));
} else {
// represents RegExp
const regexp = filter.match(/^\/(.+)\/(.*)$/);
// This should never happen due to input sanitisation.
if (!regexp) return false;
try {
return new RE2(regexp[1], regexp[2]).test(note.text!);
} catch (err) {
// This should never happen due to input sanitisation.
return false;
}
return note.text!.includes(keyword);
}));
}
});
if (matched) return true;
}

View File

@ -41,6 +41,7 @@ export class Following {
public follower: User | null;
//#region Denormalized fields
@Index()
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]',
@ -59,6 +60,7 @@ export class Following {
})
public followerSharedInbox: string | null;
@Index()
@Column('varchar', {
length: 128, nullable: true,
comment: '[Denormalized]',

View File

@ -258,6 +258,11 @@ export default function() {
processDb(dbQueue);
processObjectStorage(objectStorageQueue);
systemQueue.add('tickCharts', {
}, {
repeat: { cron: '55 * * * *' },
});
systemQueue.add('resyncCharts', {
}, {
repeat: { cron: '0 0 * * *' },

View File

@ -1,8 +1,10 @@
import * as Bull from 'bull';
import { tickCharts } from './tick-charts';
import { resyncCharts } from './resync-charts';
import { cleanCharts } from './clean-charts';
const jobs = {
tickCharts,
resyncCharts,
cleanCharts,
} as Record<string, Bull.ProcessCallbackFunction<Record<string, unknown>> | Bull.ProcessPromiseFunction<Record<string, unknown>>>;

View File

@ -0,0 +1,28 @@
import * as Bull from 'bull';
import { queueLogger } from '../../logger';
import { activeUsersChart, driveChart, federationChart, hashtagChart, instanceChart, notesChart, perUserDriveChart, perUserFollowingChart, perUserNotesChart, perUserReactionsChart, usersChart, apRequestChart } from '@/services/chart/index';
const logger = queueLogger.createSubLogger('tick-charts');
export async function tickCharts(job: Bull.Job<Record<string, unknown>>, done: any): Promise<void> {
logger.info(`Tick charts...`);
await Promise.all([
federationChart.tick(false),
notesChart.tick(false),
usersChart.tick(false),
activeUsersChart.tick(false),
instanceChart.tick(false),
perUserNotesChart.tick(false),
driveChart.tick(false),
perUserReactionsChart.tick(false),
hashtagChart.tick(false),
perUserFollowingChart.tick(false),
perUserDriveChart.tick(false),
apRequestChart.tick(false),
]);
logger.succ(`All charts successfully ticked.`);
done();
}

View File

@ -1,22 +0,0 @@
import define from '../../define';
import { driveChart, notesChart, usersChart } from '@/services/chart/index';
import { insertModerationLog } from '@/services/insert-moderation-log';
export const meta = {
tags: ['admin'],
requireCredential: true,
requireModerator: true,
} as const;
// eslint-disable-next-line import/no-default-export
export default define(meta, async (ps, me) => {
insertModerationLog(me, 'chartResync');
driveChart.resync();
notesChart.resync();
usersChart.resync();
// TODO: ユーザーごとのチャートもキューに入れて更新する
// TODO: インスタンスごとのチャートもキューに入れて更新する
});

View File

@ -1,3 +1,4 @@
const RE2 = require('re2');
import $ from 'cafy';
import * as mfm from 'mfm-js';
import { ID } from '@/misc/cafy-id';
@ -117,7 +118,7 @@ export const meta = {
},
mutedWords: {
validator: $.optional.arr($.arr($.str)),
validator: $.optional.arr($.either($.arr($.str.min(1)).min(1), $.str)),
},
mutedInstances: {
@ -163,6 +164,12 @@ export const meta = {
code: 'NO_SUCH_PAGE',
id: '8e01b590-7eb9-431b-a239-860e086c408e',
},
invalidRegexp: {
message: 'Invalid Regular Expression.',
code: 'INVALID_REGEXP',
id: '0d786918-10df-41cd-8f33-8dec7d9a89a5',
}
},
res: {
@ -191,6 +198,18 @@ export default define(meta, async (ps, _user, token) => {
if (ps.avatarId !== undefined) updates.avatarId = ps.avatarId;
if (ps.bannerId !== undefined) updates.bannerId = ps.bannerId;
if (ps.mutedWords !== undefined) {
// validate regular expression syntax
ps.mutedWords.filter(x => !Array.isArray(x)).forEach(x => {
const regexp = x.match(/^\/(.+)\/(.*)$/);
if (!regexp) throw new ApiError(meta.errors.invalidRegexp);
try {
new RE2(regexp[1], regexp[2]);
} catch (err) {
throw new ApiError(meta.errors.invalidRegexp);
}
});
profileUpdates.mutedWords = ps.mutedWords;
profileUpdates.enableWordMute = ps.mutedWords.length > 0;
}

View File

@ -18,7 +18,12 @@ export default class ActiveUsersChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}

View File

@ -12,7 +12,12 @@ export default class ApRequestChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}

View File

@ -15,7 +15,12 @@ export default class DriveChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}

View File

@ -3,12 +3,11 @@ import Chart from '../../core';
export const name = 'federation';
export const schema = {
'instance.total': { accumulate: true },
'instance.inc': { range: 'small' },
'instance.dec': { range: 'small' },
'deliveredInstances': { uniqueIncrement: true, range: 'small' },
'inboxInstances': { uniqueIncrement: true, range: 'small' },
'stalled': { uniqueIncrement: true, range: 'small' },
'sub': { accumulate: true, range: 'small' },
'pub': { accumulate: true, range: 'small' },
} as const;
export const entity = Chart.schemaToEntity(name, schema);

View File

@ -1,6 +1,6 @@
import autobind from 'autobind-decorator';
import Chart, { KVs } from '../core';
import { Instances } from '@/models/index';
import { Followings } from '@/models/index';
import { name, schema } from './entities/federation';
/**
@ -13,23 +13,30 @@ export default class FederationChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
const [total] = await Promise.all([
Instances.count({}),
]);
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
return {
'instance.total': total,
};
}
@autobind
public async update(isAdditional: boolean): Promise<void> {
await this.commit({
'instance.total': isAdditional ? 1 : -1,
'instance.inc': isAdditional ? 1 : 0,
'instance.dec': isAdditional ? 0 : 1,
});
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
const [sub, pub] = await Promise.all([
Followings.createQueryBuilder('following')
.select('COUNT(DISTINCT following.followeeHost)')
.where('following.followeeHost IS NOT NULL')
.getRawOne()
.then(x => parseInt(x.count, 10)),
Followings.createQueryBuilder('following')
.select('COUNT(DISTINCT following.followerHost)')
.where('following.followerHost IS NOT NULL')
.getRawOne()
.then(x => parseInt(x.count, 10)),
]);
return {
'sub': sub,
'pub': pub,
};
}
@autobind

View File

@ -14,7 +14,12 @@ export default class HashtagChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}

View File

@ -16,7 +16,7 @@ export default class InstanceChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(group: string): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
const [
notesCount,
usersCount,
@ -42,6 +42,11 @@ export default class InstanceChart extends Chart<typeof schema> {
};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
public async requestReceived(host: string): Promise<void> {
await this.commit({

View File

@ -15,7 +15,7 @@ export default class NotesChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
const [localCount, remoteCount] = await Promise.all([
Notes.count({ userHost: null }),
Notes.count({ userHost: Not(IsNull()) }),
@ -27,6 +27,11 @@ export default class NotesChart extends Chart<typeof schema> {
};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
public async update(note: Note, isAdditional: boolean): Promise<void> {
const prefix = note.userHost === null ? 'local' : 'remote';

View File

@ -14,7 +14,7 @@ export default class PerUserDriveChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(group: string): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
const [count, size] = await Promise.all([
DriveFiles.count({ userId: group }),
DriveFiles.calcDriveUsageOf(group),
@ -26,6 +26,11 @@ export default class PerUserDriveChart extends Chart<typeof schema> {
};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
public async update(file: DriveFile, isAdditional: boolean): Promise<void> {
const fileSizeKb = file.size / 1000;

View File

@ -15,7 +15,7 @@ export default class PerUserFollowingChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(group: string): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
const [
localFollowingsCount,
localFollowersCount,
@ -36,6 +36,11 @@ export default class PerUserFollowingChart extends Chart<typeof schema> {
};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
public async update(follower: { id: User['id']; host: User['host']; }, followee: { id: User['id']; host: User['host']; }, isFollow: boolean): Promise<void> {
const prefixFollower = Users.isLocalUser(follower) ? 'local' : 'remote';

View File

@ -15,7 +15,7 @@ export default class PerUserNotesChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(group: string): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
const [count] = await Promise.all([
Notes.count({ userId: group }),
]);
@ -25,6 +25,11 @@ export default class PerUserNotesChart extends Chart<typeof schema> {
};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
public async update(user: { id: User['id'] }, note: Note, isAdditional: boolean): Promise<void> {
await this.commit({

View File

@ -15,7 +15,12 @@ export default class PerUserReactionsChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(group: string): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}

View File

@ -14,12 +14,17 @@ export default class TestGroupedChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(group: string): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(group: string): Promise<Partial<KVs<typeof schema>>> {
return {
'foo.total': this.total[group],
};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
public async increment(group: string): Promise<void> {
if (this.total[group] == null) this.total[group] = 0;

View File

@ -12,7 +12,12 @@ export default class TestIntersectionChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}

View File

@ -12,7 +12,12 @@ export default class TestUniqueChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}

View File

@ -14,12 +14,17 @@ export default class TestChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
return {
'foo.total': this.total,
};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
public async increment(): Promise<void> {
this.total++;

View File

@ -15,7 +15,7 @@ export default class UsersChart extends Chart<typeof schema> {
}
@autobind
protected async queryCurrentState(): Promise<Partial<KVs<typeof schema>>> {
protected async tickMajor(): Promise<Partial<KVs<typeof schema>>> {
const [localCount, remoteCount] = await Promise.all([
Users.count({ host: null }),
Users.count({ host: Not(IsNull()) }),
@ -27,6 +27,11 @@ export default class UsersChart extends Chart<typeof schema> {
};
}
@autobind
protected async tickMinor(): Promise<Partial<KVs<typeof schema>>> {
return {};
}
@autobind
public async update(user: { id: User['id'], host: User['host'] }, isAdditional: boolean): Promise<void> {
const prefix = Users.isLocalUser(user) ? 'local' : 'remote';

View File

@ -81,7 +81,15 @@ export default abstract class Chart<T extends Schema> {
protected repositoryForHour: Repository<RawRecord<T>>;
protected repositoryForDay: Repository<RawRecord<T>>;
protected abstract queryCurrentState(group: string | null): Promise<Partial<KVs<T>>>;
/**
* 1日に一回程度実行されれば良いような計算処理を入れる(主にCASCADE削除などアプリケーション側で感知できない変動によるズレの修正用)
*/
protected abstract tickMajor(group: string | null): Promise<Partial<KVs<T>>>;
/**
* 少なくとも最小スパン内に1回は実行されて欲しい計算処理を入れる
*/
protected abstract tickMinor(group: string | null): Promise<Partial<KVs<T>>>;
@autobind
private static convertSchemaToColumnDefinitions(schema: Schema): Record<string, { type: string; array?: boolean; default?: any; }> {
@ -445,8 +453,8 @@ export default abstract class Chart<T extends Schema> {
}
@autobind
public async resync(group: string | null = null): Promise<void> {
const data = await this.queryCurrentState(group);
public async tick(major: boolean, group: string | null = null): Promise<void> {
const data = major ? await this.tickMajor(group) : await this.tickMinor(group);
const columns = {} as Record<string, number>;
for (const [k, v] of Object.entries(data)) {
@ -480,6 +488,11 @@ export default abstract class Chart<T extends Schema> {
update(logHour, logDay));
}
@autobind
public resync(group: string | null = null): Promise<void> {
return this.tick(true, group);
}
@autobind
public async clean(): Promise<void> {
const current = dateUTC(Chart.getCurrentDate());

View File

@ -1,6 +1,5 @@
import { Instance } from '@/models/entities/instance';
import { Instances } from '@/models/index';
import { federationChart } from '@/services/chart/index';
import { genId } from '@/misc/gen-id';
import { toPuny } from '@/misc/convert-host';
import { Cache } from '@/misc/cache';
@ -23,8 +22,6 @@ export async function registerOrFetchInstanceDoc(host: string): Promise<Instance
lastCommunicatedAt: new Date(),
}).then(x => Instances.findOneOrFail(x.identifiers[0]));
federationChart.update(true);
cache.set(host, i);
return i;
} else {

View File

@ -3134,9 +3134,9 @@ github-from-package@0.0.0:
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
glob-parent@^5.1.0, glob-parent@~5.1.0:
version "5.1.1"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==
version "5.1.2"
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==
dependencies:
is-glob "^4.0.1"
@ -3741,14 +3741,7 @@ is-generator-function@^1.0.7:
resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.7.tgz#d2132e529bb0000a7f80794d4bdf5cd5e5813522"
integrity sha512-YZc5EwyO4f2kWCax7oegfuSr9mFz1ZvieNYBEjmukLxgXfBUbxAWGVF7GZf0zidYtoBl3WvC07YK0wT76a+Rtw==
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc"
integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==
dependencies:
is-extglob "^2.1.1"
is-glob@^4.0.3:
is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1:
version "4.0.3"
resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084"
integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==
@ -4643,17 +4636,10 @@ minipass-sized@^1.0.3:
dependencies:
minipass "^3.0.0"
minipass@^3.0.0:
version "3.1.1"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5"
integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w==
dependencies:
yallist "^4.0.0"
minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.3.tgz#7d42ff1f39635482e15f9cdb53184deebd5815fd"
integrity sha512-Mgd2GdMVzY+x3IJ+oHnVM+KG3lA5c8tnabyJKmHSaG2kAGpudxuOf8ToDkhumF7UzME7DecbQE9uOZhNm7PuJg==
minipass@^3.0.0, minipass@^3.1.0, minipass@^3.1.1, minipass@^3.1.3:
version "3.1.6"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.6.tgz#3b8150aa688a711a1521af5e8779c1d3bb4f45ee"
integrity sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==
dependencies:
yallist "^4.0.0"
@ -4882,10 +4868,12 @@ node-fetch@*:
fetch-blob "^3.1.4"
formdata-polyfill "^4.0.10"
node-fetch@2.6.1, node-fetch@^2.6.1:
version "2.6.1"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
integrity sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==
node-fetch@2.6.7, node-fetch@^2.6.1:
version "2.6.7"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad"
integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==
dependencies:
whatwg-url "^5.0.0"
node-fetch@3.0.0-beta.9:
version "3.0.0-beta.9"
@ -4959,9 +4947,9 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
normalize-url@^4.1.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129"
integrity sha512-2s47yzUxdexf1OhyRi4Em83iQk0aPvwTddtFz4hnSSw9dCEsLEGf6SwIO8ss/19S9iBb5sJaOuTvTGDeZI00BQ==
version "4.5.1"
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.1.tgz#0dd90cf1288ee1d1313b87081c9a5932ee48518a"
integrity sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==
npm-run-path@^5.0.1:
version "5.0.1"
@ -5293,9 +5281,9 @@ path-key@^4.0.0:
integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
path-parse@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c"
integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
path-to-regexp@^6.1.0:
version "6.1.0"
@ -6169,20 +6157,11 @@ signal-exit@^3.0.5:
integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
simple-concat@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6"
integrity sha1-c0TLuLbib7J9ZrL8hvn21Zl1IcY=
version "1.0.1"
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
simple-get@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.0.tgz#73fa628278d21de83dadd5512d2cc1f4872bd675"
integrity sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==
dependencies:
decompress-response "^6.0.0"
once "^1.3.1"
simple-concat "^1.0.0"
simple-get@^4.0.1:
simple-get@^4.0.0, simple-get@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543"
integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==
@ -6542,19 +6521,7 @@ tar-stream@^2.1.4, tar-stream@^2.2.0:
inherits "^2.0.3"
readable-stream "^3.1.1"
tar@^6.0.2:
version "6.0.5"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.0.5.tgz#bde815086e10b39f1dcd298e89d596e1535e200f"
integrity sha512-0b4HOimQHj9nXNEAA7zWwMM91Zhhba3pspja6sQbgTpynOJf+bkjBnfybNYzbpLbnwXnbyB4LOREvlyXLkCHSg==
dependencies:
chownr "^2.0.0"
fs-minipass "^2.0.0"
minipass "^3.0.0"
minizlib "^2.1.1"
mkdirp "^1.0.3"
yallist "^4.0.0"
tar@^6.1.2:
tar@^6.0.2, tar@^6.1.2:
version "6.1.11"
resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.11.tgz#6760a38f003afa1b2ffd0ffe9e9abbd0eab3d621"
integrity sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==
@ -6653,6 +6620,11 @@ tr46@^3.0.0:
dependencies:
punycode "^2.1.1"
tr46@~0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=
trace-redirect@1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/trace-redirect/-/trace-redirect-1.0.6.tgz#ac629b5bf8247d30dde5a35fe9811b811075b504"
@ -6998,6 +6970,11 @@ web-streams-polyfill@^3.0.3:
resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.2.0.tgz#a6b74026b38e4885869fb5c589e90b95ccfc7965"
integrity sha512-EqPmREeOzttaLRm5HS7io98goBgZ7IVz79aDvqjD0kYXLtFZTc0T/U6wHTPKyIjb+MdN7DFIIX6hgdBEpWmfPA==
webidl-conversions@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=
webidl-conversions@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
@ -7035,6 +7012,14 @@ whatwg-url@^10.0.0:
tr46 "^3.0.0"
webidl-conversions "^7.0.0"
whatwg-url@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"
integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0=
dependencies:
tr46 "~0.0.3"
webidl-conversions "^3.0.0"
which-boxed-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6"