From d429f810a9ea3fda9efed2ff51483d25a288ecc9 Mon Sep 17 00:00:00 2001 From: Ebise Lutica <7106976+EbiseLutica@users.noreply.github.com> Date: Thu, 13 Apr 2023 00:31:22 +0900 Subject: [PATCH 001/246] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41353c346b..df2265727d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ ## 13.11.2 +### Note +- 13.11.0または13.11.1から13.11.2以降にアップデートする場合、Redisのカスタム絵文字のキャッシュを削除する必要があります(https://github.com/misskey-dev/misskey/issues/10502#issuecomment-1502790755 参照) + ### General - チャンネルの検索用ページの追加 From 2eaa3e256ff7310bd63197aafe7e72fa207e347b Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 31 May 2024 20:42:02 +0900 Subject: [PATCH 002/246] Update README.md for Sentry --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 24013a7bd8..92e8fef639 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,10 @@ ## Thanks +Sentry + +Thanks to [Sentry](https://sentry.io/) for providing the error tracking platform that helps us catch unexpected errors. + Chromatic Thanks to [Chromatic](https://www.chromatic.com/) for providing the visual testing platform that helps us review UI changes and catch visual regressions. From ecf7945fe8e4554c0db248512fbc51a41cfaf2c9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 31 May 2024 12:25:00 +0000 Subject: [PATCH 003/246] [skip ci] Update CHANGELOG.md (prepend template) --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f78ba677d..9d4ef23d27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +## Unreleased + +### General +- + +### Client +- + +### Server +- + + ## 2024.5.0 ### Note From 2b8056a8525e1b38536aa0406ba9446a88b365b9 Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Sat, 1 Jun 2024 11:16:44 +0900 Subject: [PATCH 004/246] fix(backend): use insertOne insteadof insert/findOneOrFail combination (#13908) * fix(backend): use insertOne insteadof insert/findOneOrFail combination * fix: typo * fix(backend): inherit mainAlias? * refactor(backend): use extend * fix(backend): invalid entityTarget * fix(backend): fake where * chore: debug * chore: debug * test: log * fix(backend): column names * fix(backend): remove dummy from * revert: log * fix(backend): position * fix(backend): automatic aliasing * chore(backend): alias * chore(backend): remove from * fix(backend): type * fix(backend): avoid pure name * test(backend): fix type * chore(backend): use cte * fix(backend): avoid useless alias * fix(backend): fix typo * fix(backend): __disambiguation__ * fix(backend): quote * chore(backend): t * chore(backend): accessible * chore(backend): concrete returning * fix(backend): quote * chore: log more * chore: log metadata * chore(backend): use raw * fix(backend): returning column name * fix(backend): transform * build(backend): wanna logging * build(backend): transform empty * build(backend): build alias * build(backend): restore name * chore: return entity * fix: test case * test(backend): 204 * chore(backend): log sql * chore(backend): assert user joined * fix(backend): typo * chore(backend): log long sql * chore(backend): log join * chore(backend): log join depth null * chore(backend): joinAttributes * chore(backend): override createJoinExpression * chore: join log * fix(backend): escape * test(backend): log log * chore(backend): join gonna success? * chore(backend): relations * chore(backend): undefined * chore(backend): target * chore(backend): remove log * chore(backend): log chart update * chore(backend): log columns * chore(backend): check hasMetadata * chore(backend): unshift id when not included * chore(backend): missing select * chore(backend): remove debug code --- .../backend/src/core/AnnouncementService.ts | 4 +- .../src/core/AvatarDecorationService.ts | 4 +- packages/backend/src/core/ClipService.ts | 4 +- .../backend/src/core/CustomEmojiService.ts | 4 +- packages/backend/src/core/DriveService.ts | 6 +- .../src/core/FederatedInstanceService.ts | 4 +- packages/backend/src/core/RelayService.ts | 4 +- packages/backend/src/core/ReversiService.ts | 7 +- packages/backend/src/core/RoleService.ts | 8 +- .../backend/src/core/UserFollowingService.ts | 4 +- .../core/activitypub/models/ApNoteService.ts | 4 +- packages/backend/src/core/chart/core.ts | 23 +- .../backend/src/models/RepositoryModule.ts | 136 ++++++------ packages/backend/src/models/_.ts | 205 ++++++++++++------ .../ImportAntennasProcessorService.ts | 4 +- .../ImportUserListsProcessorService.ts | 4 +- .../backend/src/server/api/SigninService.ts | 4 +- .../src/server/api/SignupApiService.ts | 4 +- .../server/api/endpoints/admin/ad/create.ts | 4 +- .../api/endpoints/admin/invite/create.ts | 4 +- .../server/api/endpoints/antennas/create.ts | 4 +- .../src/server/api/endpoints/app/create.ts | 4 +- .../api/endpoints/auth/session/generate.ts | 4 +- .../server/api/endpoints/channels/create.ts | 4 +- .../api/endpoints/drive/folders/create.ts | 4 +- .../src/server/api/endpoints/flash/create.ts | 4 +- .../api/endpoints/gallery/posts/create.ts | 4 +- .../server/api/endpoints/i/webhooks/create.ts | 4 +- .../src/server/api/endpoints/invite/create.ts | 4 +- .../server/api/endpoints/notes/polls/vote.ts | 4 +- .../src/server/api/endpoints/pages/create.ts | 4 +- .../users/lists/create-from-public.ts | 4 +- .../api/endpoints/users/lists/create.ts | 4 +- .../api/endpoints/users/report-abuse.ts | 4 +- packages/backend/test/e2e/move.ts | 4 +- packages/backend/test/e2e/reversi-game.ts | 33 +++ 36 files changed, 319 insertions(+), 215 deletions(-) create mode 100644 packages/backend/test/e2e/reversi-game.ts diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts index 9b60df2cae..40a9db01c0 100644 --- a/packages/backend/src/core/AnnouncementService.ts +++ b/packages/backend/src/core/AnnouncementService.ts @@ -67,7 +67,7 @@ export class AnnouncementService { @bindThis public async create(values: Partial, moderator?: MiUser): Promise<{ raw: MiAnnouncement; packed: Packed<'Announcement'> }> { - const announcement = await this.announcementsRepository.insert({ + const announcement = await this.announcementsRepository.insertOne({ id: this.idService.gen(), updatedAt: null, title: values.title, @@ -79,7 +79,7 @@ export class AnnouncementService { silence: values.silence, needConfirmationToRead: values.needConfirmationToRead, userId: values.userId, - }).then(x => this.announcementsRepository.findOneByOrFail(x.identifiers[0])); + }); const packed = await this.announcementEntityService.pack(announcement); diff --git a/packages/backend/src/core/AvatarDecorationService.ts b/packages/backend/src/core/AvatarDecorationService.ts index 21e31d79a4..8b54bbe012 100644 --- a/packages/backend/src/core/AvatarDecorationService.ts +++ b/packages/backend/src/core/AvatarDecorationService.ts @@ -55,10 +55,10 @@ export class AvatarDecorationService implements OnApplicationShutdown { @bindThis public async create(options: Partial, moderator?: MiUser): Promise { - const created = await this.avatarDecorationsRepository.insert({ + const created = await this.avatarDecorationsRepository.insertOne({ id: this.idService.gen(), ...options, - }).then(x => this.avatarDecorationsRepository.findOneByOrFail(x.identifiers[0])); + }); this.globalEventService.publishInternalEvent('avatarDecorationCreated', created); diff --git a/packages/backend/src/core/ClipService.ts b/packages/backend/src/core/ClipService.ts index bb8be26ce6..9fd1ebad87 100644 --- a/packages/backend/src/core/ClipService.ts +++ b/packages/backend/src/core/ClipService.ts @@ -45,13 +45,13 @@ export class ClipService { throw new ClipService.TooManyClipsError(); } - const clip = await this.clipsRepository.insert({ + const clip = await this.clipsRepository.insertOne({ id: this.idService.gen(), userId: me.id, name: name, isPublic: isPublic, description: description, - }).then(x => this.clipsRepository.findOneByOrFail(x.identifiers[0])); + }); return clip; } diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index b1feca7fb4..7e11b9cdca 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -68,7 +68,7 @@ export class CustomEmojiService implements OnApplicationShutdown { localOnly: boolean; roleIdsThatCanBeUsedThisEmojiAsReaction: MiRole['id'][]; }, moderator?: MiUser): Promise { - const emoji = await this.emojisRepository.insert({ + const emoji = await this.emojisRepository.insertOne({ id: this.idService.gen(), updatedAt: new Date(), name: data.name, @@ -82,7 +82,7 @@ export class CustomEmojiService implements OnApplicationShutdown { isSensitive: data.isSensitive, localOnly: data.localOnly, roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction, - }).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0])); + }); if (data.host == null) { this.localEmojisCache.refresh(); diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index 26cf532c70..37c5d1adf7 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -220,7 +220,7 @@ export class DriveService { file.size = size; file.storedInternal = false; - return await this.driveFilesRepository.insert(file).then(x => this.driveFilesRepository.findOneByOrFail(x.identifiers[0])); + return await this.driveFilesRepository.insertOne(file); } else { // use internal storage const accessKey = randomUUID(); const thumbnailAccessKey = 'thumbnail-' + randomUUID(); @@ -254,7 +254,7 @@ export class DriveService { file.md5 = hash; file.size = size; - return await this.driveFilesRepository.insert(file).then(x => this.driveFilesRepository.findOneByOrFail(x.identifiers[0])); + return await this.driveFilesRepository.insertOne(file); } } @@ -615,7 +615,7 @@ export class DriveService { file.type = info.type.mime; file.storedInternal = false; - file = await this.driveFilesRepository.insert(file).then(x => this.driveFilesRepository.findOneByOrFail(x.identifiers[0])); + file = await this.driveFilesRepository.insertOne(file); } catch (err) { // duplicate key error (when already registered) if (isDuplicateKeyValueError(err)) { diff --git a/packages/backend/src/core/FederatedInstanceService.ts b/packages/backend/src/core/FederatedInstanceService.ts index 66db2067d9..6799f2c5bb 100644 --- a/packages/backend/src/core/FederatedInstanceService.ts +++ b/packages/backend/src/core/FederatedInstanceService.ts @@ -55,11 +55,11 @@ export class FederatedInstanceService implements OnApplicationShutdown { const index = await this.instancesRepository.findOneBy({ host }); if (index == null) { - const i = await this.instancesRepository.insert({ + const i = await this.instancesRepository.insertOne({ id: this.idService.gen(), host, firstRetrievedAt: new Date(), - }).then(x => this.instancesRepository.findOneByOrFail(x.identifiers[0])); + }); this.federatedInstanceCache.set(host, i); return i; diff --git a/packages/backend/src/core/RelayService.ts b/packages/backend/src/core/RelayService.ts index e9dc9b57af..8dd3d64f5b 100644 --- a/packages/backend/src/core/RelayService.ts +++ b/packages/backend/src/core/RelayService.ts @@ -53,11 +53,11 @@ export class RelayService { @bindThis public async addRelay(inbox: string): Promise { - const relay = await this.relaysRepository.insert({ + const relay = await this.relaysRepository.insertOne({ id: this.idService.gen(), inbox, status: 'requesting', - }).then(x => this.relaysRepository.findOneByOrFail(x.identifiers[0])); + }); const relayActor = await this.getRelayActor(); const follow = await this.apRendererService.renderFollowRelay(relay, relayActor); diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts index 439bc08845..7f939b99c7 100644 --- a/packages/backend/src/core/ReversiService.ts +++ b/packages/backend/src/core/ReversiService.ts @@ -281,7 +281,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit { @bindThis private async matched(parentId: MiUser['id'], childId: MiUser['id'], options: { noIrregularRules: boolean; }): Promise { - const game = await this.reversiGamesRepository.insert({ + const game = await this.reversiGamesRepository.insertOne({ id: this.idService.gen(), user1Id: parentId, user2Id: childId, @@ -294,10 +294,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit { bw: 'random', isLlotheo: false, noIrregularRules: options.noIrregularRules, - }).then(x => this.reversiGamesRepository.findOneOrFail({ - where: { id: x.identifiers[0].id }, - relations: ['user1', 'user2'], - })); + }, { relations: ['user1', 'user2'] }); this.cacheGame(game); const packed = await this.reversiGameEntityService.packDetail(game); diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index 70c537f9ab..d6eea70297 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -471,12 +471,12 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { } } - const created = await this.roleAssignmentsRepository.insert({ + const created = await this.roleAssignmentsRepository.insertOne({ id: this.idService.gen(now), expiresAt: expiresAt, roleId: roleId, userId: userId, - }).then(x => this.roleAssignmentsRepository.findOneByOrFail(x.identifiers[0])); + }); this.rolesRepository.update(roleId, { lastUsedAt: new Date(), @@ -558,7 +558,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { @bindThis public async create(values: Partial, moderator?: MiUser): Promise { const date = new Date(); - const created = await this.rolesRepository.insert({ + const created = await this.rolesRepository.insertOne({ id: this.idService.gen(date.getTime()), updatedAt: date, lastUsedAt: date, @@ -576,7 +576,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { canEditMembersByModerator: values.canEditMembersByModerator, displayOrder: values.displayOrder, policies: values.policies, - }).then(x => this.rolesRepository.findOneByOrFail(x.identifiers[0])); + }); this.globalEventService.publishInternalEvent('roleCreated', created); diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index deeecdeb1f..406ea04031 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -517,7 +517,7 @@ export class UserFollowingService implements OnModuleInit { followerId: follower.id, }); - const followRequest = await this.followRequestsRepository.insert({ + const followRequest = await this.followRequestsRepository.insertOne({ id: this.idService.gen(), followerId: follower.id, followeeId: followee.id, @@ -531,7 +531,7 @@ export class UserFollowingService implements OnModuleInit { followeeHost: followee.host, followeeInbox: this.userEntityService.isRemoteUser(followee) ? followee.inbox : undefined, followeeSharedInbox: this.userEntityService.isRemoteUser(followee) ? followee.sharedInbox : undefined, - }).then(x => this.followRequestsRepository.findOneByOrFail(x.identifiers[0])); + }); // Publish receiveRequest event if (this.userEntityService.isLocalUser(followee)) { diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index e6dff067f3..c6e6b3a1e8 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -407,7 +407,7 @@ export class ApNoteService { this.logger.info(`register emoji host=${host}, name=${name}`); - return await this.emojisRepository.insert({ + return await this.emojisRepository.insertOne({ id: this.idService.gen(), host, name, @@ -416,7 +416,7 @@ export class ApNoteService { publicUrl: tag.icon.url, updatedAt: new Date(), aliases: [], - }).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0])); + }); })); } } diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts index f10e30ef10..af5485a46e 100644 --- a/packages/backend/src/core/chart/core.ts +++ b/packages/backend/src/core/chart/core.ts @@ -14,7 +14,8 @@ import { EntitySchema, LessThan, Between } from 'typeorm'; import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/misc/prelude/time.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; -import type { Repository, DataSource } from 'typeorm'; +import { MiRepository, miRepository } from '@/models/_.js'; +import type { DataSource, Repository } from 'typeorm'; const COLUMN_PREFIX = '___' as const; const UNIQUE_TEMP_COLUMN_PREFIX = 'unique_temp___' as const; @@ -145,10 +146,10 @@ export default abstract class Chart { group: string | null; }[] = []; // ↓にしたいけどfindOneとかで型エラーになる - //private repositoryForHour: Repository>; - //private repositoryForDay: Repository>; - private repositoryForHour: Repository<{ id: number; group?: string | null; date: number; }>; - private repositoryForDay: Repository<{ id: number; group?: string | null; date: number; }>; + //private repositoryForHour: Repository> & MiRepository>; + //private repositoryForDay: Repository> & MiRepository>; + private repositoryForHour: Repository<{ id: number; group?: string | null; date: number; }> & MiRepository<{ id: number; group?: string | null; date: number; }>; + private repositoryForDay: Repository<{ id: number; group?: string | null; date: number; }> & MiRepository<{ id: number; group?: string | null; date: number; }>; /** * 1日に一回程度実行されれば良いような計算処理を入れる(主にCASCADE削除などアプリケーション側で感知できない変動によるズレの修正用) @@ -211,6 +212,10 @@ export default abstract class Chart { } { const createEntity = (span: 'hour' | 'day'): EntitySchema => new EntitySchema({ name: + span === 'hour' ? `ChartX${name}` : + span === 'day' ? `ChartDayX${name}` : + new Error('not happen') as never, + tableName: span === 'hour' ? `__chart__${camelToSnake(name)}` : span === 'day' ? `__chart_day__${camelToSnake(name)}` : new Error('not happen') as never, @@ -271,8 +276,8 @@ export default abstract class Chart { this.logger = logger; const { hour, day } = Chart.schemaToEntity(name, schema, grouped); - this.repositoryForHour = db.getRepository<{ id: number; group?: string | null; date: number; }>(hour); - this.repositoryForDay = db.getRepository<{ id: number; group?: string | null; date: number; }>(day); + this.repositoryForHour = db.getRepository<{ id: number; group?: string | null; date: number; }>(hour).extend(miRepository as MiRepository<{ id: number; group?: string | null; date: number; }>); + this.repositoryForDay = db.getRepository<{ id: number; group?: string | null; date: number; }>(day).extend(miRepository as MiRepository<{ id: number; group?: string | null; date: number; }>); } @bindThis @@ -387,11 +392,11 @@ export default abstract class Chart { } // 新規ログ挿入 - log = await repository.insert({ + log = await repository.insertOne({ date: date, ...(group ? { group: group } : {}), ...columns, - }).then(x => repository.findOneByOrFail(x.identifiers[0])) as RawRecord; + }) as RawRecord; this.logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): New commit created`); diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index bd447570dd..d3062d6b36 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -5,409 +5,409 @@ import { Module } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import { MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook, MiBubbleGameRecord, MiReversiGame } from './_.js'; +import { MiRepository, MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook, MiBubbleGameRecord, MiReversiGame, miRepository } from './_.js'; import type { DataSource } from 'typeorm'; import type { Provider } from '@nestjs/common'; const $usersRepository: Provider = { provide: DI.usersRepository, - useFactory: (db: DataSource) => db.getRepository(MiUser), + useFactory: (db: DataSource) => db.getRepository(MiUser).extend(miRepository as MiRepository), inject: [DI.db], }; const $notesRepository: Provider = { provide: DI.notesRepository, - useFactory: (db: DataSource) => db.getRepository(MiNote), + useFactory: (db: DataSource) => db.getRepository(MiNote).extend(miRepository as MiRepository), inject: [DI.db], }; const $announcementsRepository: Provider = { provide: DI.announcementsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAnnouncement), + useFactory: (db: DataSource) => db.getRepository(MiAnnouncement).extend(miRepository as MiRepository), inject: [DI.db], }; const $announcementReadsRepository: Provider = { provide: DI.announcementReadsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAnnouncementRead), + useFactory: (db: DataSource) => db.getRepository(MiAnnouncementRead).extend(miRepository as MiRepository), inject: [DI.db], }; const $appsRepository: Provider = { provide: DI.appsRepository, - useFactory: (db: DataSource) => db.getRepository(MiApp), + useFactory: (db: DataSource) => db.getRepository(MiApp).extend(miRepository as MiRepository), inject: [DI.db], }; const $avatarDecorationsRepository: Provider = { provide: DI.avatarDecorationsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAvatarDecoration), + useFactory: (db: DataSource) => db.getRepository(MiAvatarDecoration).extend(miRepository as MiRepository), inject: [DI.db], }; const $noteFavoritesRepository: Provider = { provide: DI.noteFavoritesRepository, - useFactory: (db: DataSource) => db.getRepository(MiNoteFavorite), + useFactory: (db: DataSource) => db.getRepository(MiNoteFavorite).extend(miRepository as MiRepository), inject: [DI.db], }; const $noteThreadMutingsRepository: Provider = { provide: DI.noteThreadMutingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiNoteThreadMuting), + useFactory: (db: DataSource) => db.getRepository(MiNoteThreadMuting).extend(miRepository as MiRepository), inject: [DI.db], }; const $noteReactionsRepository: Provider = { provide: DI.noteReactionsRepository, - useFactory: (db: DataSource) => db.getRepository(MiNoteReaction), + useFactory: (db: DataSource) => db.getRepository(MiNoteReaction).extend(miRepository as MiRepository), inject: [DI.db], }; const $noteUnreadsRepository: Provider = { provide: DI.noteUnreadsRepository, - useFactory: (db: DataSource) => db.getRepository(MiNoteUnread), + useFactory: (db: DataSource) => db.getRepository(MiNoteUnread).extend(miRepository as MiRepository), inject: [DI.db], }; const $pollsRepository: Provider = { provide: DI.pollsRepository, - useFactory: (db: DataSource) => db.getRepository(MiPoll), + useFactory: (db: DataSource) => db.getRepository(MiPoll).extend(miRepository as MiRepository), inject: [DI.db], }; const $pollVotesRepository: Provider = { provide: DI.pollVotesRepository, - useFactory: (db: DataSource) => db.getRepository(MiPollVote), + useFactory: (db: DataSource) => db.getRepository(MiPollVote).extend(miRepository as MiRepository), inject: [DI.db], }; const $userProfilesRepository: Provider = { provide: DI.userProfilesRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserProfile), + useFactory: (db: DataSource) => db.getRepository(MiUserProfile).extend(miRepository as MiRepository), inject: [DI.db], }; const $userKeypairsRepository: Provider = { provide: DI.userKeypairsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserKeypair), + useFactory: (db: DataSource) => db.getRepository(MiUserKeypair).extend(miRepository as MiRepository), inject: [DI.db], }; const $userPendingsRepository: Provider = { provide: DI.userPendingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserPending), + useFactory: (db: DataSource) => db.getRepository(MiUserPending).extend(miRepository as MiRepository), inject: [DI.db], }; const $userSecurityKeysRepository: Provider = { provide: DI.userSecurityKeysRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserSecurityKey), + useFactory: (db: DataSource) => db.getRepository(MiUserSecurityKey).extend(miRepository as MiRepository), inject: [DI.db], }; const $userPublickeysRepository: Provider = { provide: DI.userPublickeysRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserPublickey), + useFactory: (db: DataSource) => db.getRepository(MiUserPublickey).extend(miRepository as MiRepository), inject: [DI.db], }; const $userListsRepository: Provider = { provide: DI.userListsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserList), + useFactory: (db: DataSource) => db.getRepository(MiUserList).extend(miRepository as MiRepository), inject: [DI.db], }; const $userListFavoritesRepository: Provider = { provide: DI.userListFavoritesRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserListFavorite), + useFactory: (db: DataSource) => db.getRepository(MiUserListFavorite).extend(miRepository as MiRepository), inject: [DI.db], }; const $userListMembershipsRepository: Provider = { provide: DI.userListMembershipsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserListMembership), + useFactory: (db: DataSource) => db.getRepository(MiUserListMembership).extend(miRepository as MiRepository), inject: [DI.db], }; const $userNotePiningsRepository: Provider = { provide: DI.userNotePiningsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserNotePining), + useFactory: (db: DataSource) => db.getRepository(MiUserNotePining).extend(miRepository as MiRepository), inject: [DI.db], }; const $userIpsRepository: Provider = { provide: DI.userIpsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserIp), + useFactory: (db: DataSource) => db.getRepository(MiUserIp).extend(miRepository as MiRepository), inject: [DI.db], }; const $usedUsernamesRepository: Provider = { provide: DI.usedUsernamesRepository, - useFactory: (db: DataSource) => db.getRepository(MiUsedUsername), + useFactory: (db: DataSource) => db.getRepository(MiUsedUsername).extend(miRepository as MiRepository), inject: [DI.db], }; const $followingsRepository: Provider = { provide: DI.followingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiFollowing), + useFactory: (db: DataSource) => db.getRepository(MiFollowing).extend(miRepository as MiRepository), inject: [DI.db], }; const $followRequestsRepository: Provider = { provide: DI.followRequestsRepository, - useFactory: (db: DataSource) => db.getRepository(MiFollowRequest), + useFactory: (db: DataSource) => db.getRepository(MiFollowRequest).extend(miRepository as MiRepository), inject: [DI.db], }; const $instancesRepository: Provider = { provide: DI.instancesRepository, - useFactory: (db: DataSource) => db.getRepository(MiInstance), + useFactory: (db: DataSource) => db.getRepository(MiInstance).extend(miRepository as MiRepository), inject: [DI.db], }; const $emojisRepository: Provider = { provide: DI.emojisRepository, - useFactory: (db: DataSource) => db.getRepository(MiEmoji), + useFactory: (db: DataSource) => db.getRepository(MiEmoji).extend(miRepository as MiRepository), inject: [DI.db], }; const $driveFilesRepository: Provider = { provide: DI.driveFilesRepository, - useFactory: (db: DataSource) => db.getRepository(MiDriveFile), + useFactory: (db: DataSource) => db.getRepository(MiDriveFile).extend(miRepository as MiRepository), inject: [DI.db], }; const $driveFoldersRepository: Provider = { provide: DI.driveFoldersRepository, - useFactory: (db: DataSource) => db.getRepository(MiDriveFolder), + useFactory: (db: DataSource) => db.getRepository(MiDriveFolder).extend(miRepository as MiRepository), inject: [DI.db], }; const $metasRepository: Provider = { provide: DI.metasRepository, - useFactory: (db: DataSource) => db.getRepository(MiMeta), + useFactory: (db: DataSource) => db.getRepository(MiMeta).extend(miRepository as MiRepository), inject: [DI.db], }; const $mutingsRepository: Provider = { provide: DI.mutingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiMuting), + useFactory: (db: DataSource) => db.getRepository(MiMuting).extend(miRepository as MiRepository), inject: [DI.db], }; const $renoteMutingsRepository: Provider = { provide: DI.renoteMutingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRenoteMuting), + useFactory: (db: DataSource) => db.getRepository(MiRenoteMuting).extend(miRepository as MiRepository), inject: [DI.db], }; const $blockingsRepository: Provider = { provide: DI.blockingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiBlocking), + useFactory: (db: DataSource) => db.getRepository(MiBlocking).extend(miRepository as MiRepository), inject: [DI.db], }; const $swSubscriptionsRepository: Provider = { provide: DI.swSubscriptionsRepository, - useFactory: (db: DataSource) => db.getRepository(MiSwSubscription), + useFactory: (db: DataSource) => db.getRepository(MiSwSubscription).extend(miRepository as MiRepository), inject: [DI.db], }; const $hashtagsRepository: Provider = { provide: DI.hashtagsRepository, - useFactory: (db: DataSource) => db.getRepository(MiHashtag), + useFactory: (db: DataSource) => db.getRepository(MiHashtag).extend(miRepository as MiRepository), inject: [DI.db], }; const $abuseUserReportsRepository: Provider = { provide: DI.abuseUserReportsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAbuseUserReport), + useFactory: (db: DataSource) => db.getRepository(MiAbuseUserReport).extend(miRepository as MiRepository), inject: [DI.db], }; const $registrationTicketsRepository: Provider = { provide: DI.registrationTicketsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRegistrationTicket), + useFactory: (db: DataSource) => db.getRepository(MiRegistrationTicket).extend(miRepository as MiRepository), inject: [DI.db], }; const $authSessionsRepository: Provider = { provide: DI.authSessionsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAuthSession), + useFactory: (db: DataSource) => db.getRepository(MiAuthSession).extend(miRepository as MiRepository), inject: [DI.db], }; const $accessTokensRepository: Provider = { provide: DI.accessTokensRepository, - useFactory: (db: DataSource) => db.getRepository(MiAccessToken), + useFactory: (db: DataSource) => db.getRepository(MiAccessToken).extend(miRepository as MiRepository), inject: [DI.db], }; const $signinsRepository: Provider = { provide: DI.signinsRepository, - useFactory: (db: DataSource) => db.getRepository(MiSignin), + useFactory: (db: DataSource) => db.getRepository(MiSignin).extend(miRepository as MiRepository), inject: [DI.db], }; const $pagesRepository: Provider = { provide: DI.pagesRepository, - useFactory: (db: DataSource) => db.getRepository(MiPage), + useFactory: (db: DataSource) => db.getRepository(MiPage).extend(miRepository as MiRepository), inject: [DI.db], }; const $pageLikesRepository: Provider = { provide: DI.pageLikesRepository, - useFactory: (db: DataSource) => db.getRepository(MiPageLike), + useFactory: (db: DataSource) => db.getRepository(MiPageLike).extend(miRepository as MiRepository), inject: [DI.db], }; const $galleryPostsRepository: Provider = { provide: DI.galleryPostsRepository, - useFactory: (db: DataSource) => db.getRepository(MiGalleryPost), + useFactory: (db: DataSource) => db.getRepository(MiGalleryPost).extend(miRepository as MiRepository), inject: [DI.db], }; const $galleryLikesRepository: Provider = { provide: DI.galleryLikesRepository, - useFactory: (db: DataSource) => db.getRepository(MiGalleryLike), + useFactory: (db: DataSource) => db.getRepository(MiGalleryLike).extend(miRepository as MiRepository), inject: [DI.db], }; const $moderationLogsRepository: Provider = { provide: DI.moderationLogsRepository, - useFactory: (db: DataSource) => db.getRepository(MiModerationLog), + useFactory: (db: DataSource) => db.getRepository(MiModerationLog).extend(miRepository as MiRepository), inject: [DI.db], }; const $clipsRepository: Provider = { provide: DI.clipsRepository, - useFactory: (db: DataSource) => db.getRepository(MiClip), + useFactory: (db: DataSource) => db.getRepository(MiClip).extend(miRepository as MiRepository), inject: [DI.db], }; const $clipNotesRepository: Provider = { provide: DI.clipNotesRepository, - useFactory: (db: DataSource) => db.getRepository(MiClipNote), + useFactory: (db: DataSource) => db.getRepository(MiClipNote).extend(miRepository as MiRepository), inject: [DI.db], }; const $clipFavoritesRepository: Provider = { provide: DI.clipFavoritesRepository, - useFactory: (db: DataSource) => db.getRepository(MiClipFavorite), + useFactory: (db: DataSource) => db.getRepository(MiClipFavorite).extend(miRepository as MiRepository), inject: [DI.db], }; const $antennasRepository: Provider = { provide: DI.antennasRepository, - useFactory: (db: DataSource) => db.getRepository(MiAntenna), + useFactory: (db: DataSource) => db.getRepository(MiAntenna).extend(miRepository as MiRepository), inject: [DI.db], }; const $promoNotesRepository: Provider = { provide: DI.promoNotesRepository, - useFactory: (db: DataSource) => db.getRepository(MiPromoNote), + useFactory: (db: DataSource) => db.getRepository(MiPromoNote).extend(miRepository as MiRepository), inject: [DI.db], }; const $promoReadsRepository: Provider = { provide: DI.promoReadsRepository, - useFactory: (db: DataSource) => db.getRepository(MiPromoRead), + useFactory: (db: DataSource) => db.getRepository(MiPromoRead).extend(miRepository as MiRepository), inject: [DI.db], }; const $relaysRepository: Provider = { provide: DI.relaysRepository, - useFactory: (db: DataSource) => db.getRepository(MiRelay), + useFactory: (db: DataSource) => db.getRepository(MiRelay).extend(miRepository as MiRepository), inject: [DI.db], }; const $channelsRepository: Provider = { provide: DI.channelsRepository, - useFactory: (db: DataSource) => db.getRepository(MiChannel), + useFactory: (db: DataSource) => db.getRepository(MiChannel).extend(miRepository as MiRepository), inject: [DI.db], }; const $channelFollowingsRepository: Provider = { provide: DI.channelFollowingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiChannelFollowing), + useFactory: (db: DataSource) => db.getRepository(MiChannelFollowing).extend(miRepository as MiRepository), inject: [DI.db], }; const $channelFavoritesRepository: Provider = { provide: DI.channelFavoritesRepository, - useFactory: (db: DataSource) => db.getRepository(MiChannelFavorite), + useFactory: (db: DataSource) => db.getRepository(MiChannelFavorite).extend(miRepository as MiRepository), inject: [DI.db], }; const $registryItemsRepository: Provider = { provide: DI.registryItemsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRegistryItem), + useFactory: (db: DataSource) => db.getRepository(MiRegistryItem).extend(miRepository as MiRepository), inject: [DI.db], }; const $webhooksRepository: Provider = { provide: DI.webhooksRepository, - useFactory: (db: DataSource) => db.getRepository(MiWebhook), + useFactory: (db: DataSource) => db.getRepository(MiWebhook).extend(miRepository as MiRepository), inject: [DI.db], }; const $adsRepository: Provider = { provide: DI.adsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAd), + useFactory: (db: DataSource) => db.getRepository(MiAd).extend(miRepository as MiRepository), inject: [DI.db], }; const $passwordResetRequestsRepository: Provider = { provide: DI.passwordResetRequestsRepository, - useFactory: (db: DataSource) => db.getRepository(MiPasswordResetRequest), + useFactory: (db: DataSource) => db.getRepository(MiPasswordResetRequest).extend(miRepository as MiRepository), inject: [DI.db], }; const $retentionAggregationsRepository: Provider = { provide: DI.retentionAggregationsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRetentionAggregation), + useFactory: (db: DataSource) => db.getRepository(MiRetentionAggregation).extend(miRepository as MiRepository), inject: [DI.db], }; const $flashsRepository: Provider = { provide: DI.flashsRepository, - useFactory: (db: DataSource) => db.getRepository(MiFlash), + useFactory: (db: DataSource) => db.getRepository(MiFlash).extend(miRepository as MiRepository), inject: [DI.db], }; const $flashLikesRepository: Provider = { provide: DI.flashLikesRepository, - useFactory: (db: DataSource) => db.getRepository(MiFlashLike), + useFactory: (db: DataSource) => db.getRepository(MiFlashLike).extend(miRepository as MiRepository), inject: [DI.db], }; const $rolesRepository: Provider = { provide: DI.rolesRepository, - useFactory: (db: DataSource) => db.getRepository(MiRole), + useFactory: (db: DataSource) => db.getRepository(MiRole).extend(miRepository as MiRepository), inject: [DI.db], }; const $roleAssignmentsRepository: Provider = { provide: DI.roleAssignmentsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRoleAssignment), + useFactory: (db: DataSource) => db.getRepository(MiRoleAssignment).extend(miRepository as MiRepository), inject: [DI.db], }; const $userMemosRepository: Provider = { provide: DI.userMemosRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserMemo), + useFactory: (db: DataSource) => db.getRepository(MiUserMemo).extend(miRepository as MiRepository), inject: [DI.db], }; const $bubbleGameRecordsRepository: Provider = { provide: DI.bubbleGameRecordsRepository, - useFactory: (db: DataSource) => db.getRepository(MiBubbleGameRecord), + useFactory: (db: DataSource) => db.getRepository(MiBubbleGameRecord).extend(miRepository as MiRepository), inject: [DI.db], }; const $reversiGamesRepository: Provider = { provide: DI.reversiGamesRepository, - useFactory: (db: DataSource) => db.getRepository(MiReversiGame), + useFactory: (db: DataSource) => db.getRepository(MiReversiGame).extend(miRepository as MiRepository), inject: [DI.db], }; diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 43d42d80dd..2e6a41586e 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -3,6 +3,13 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository, SelectQueryBuilder, TypeORMError } from 'typeorm'; +import { DriverUtils } from 'typeorm/driver/DriverUtils.js'; +import { RelationCountLoader } from 'typeorm/query-builder/relation-count/RelationCountLoader.js'; +import { RelationIdLoader } from 'typeorm/query-builder/relation-id/RelationIdLoader.js'; +import { RawSqlResultsToEntityTransformer } from 'typeorm/query-builder/transformer/RawSqlResultsToEntityTransformer.js'; +import { ObjectUtils } from 'typeorm/util/ObjectUtils.js'; +import { OrmUtils } from 'typeorm/util/OrmUtils.js'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; @@ -70,8 +77,70 @@ import { MiFlashLike } from '@/models/FlashLike.js'; import { MiUserListFavorite } from '@/models/UserListFavorite.js'; import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js'; import { MiReversiGame } from '@/models/ReversiGame.js'; +import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; -import type { Repository } from 'typeorm'; +export interface MiRepository { + createTableColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; + createTableColumnNamesWithPrimaryKey(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; + insertOne(this: Repository & MiRepository, entity: QueryDeepPartialEntity, findOptions?: Pick, 'relations'>): Promise; + selectAliasColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder, builder: SelectQueryBuilder): void; +} + +export const miRepository = { + createTableColumnNames(queryBuilder) { + // @ts-expect-error -- protected + const insertedColumns = queryBuilder.getInsertedColumns(); + if (insertedColumns.length) { + return insertedColumns.map(column => column.databaseName); + } + if (!queryBuilder.expressionMap.mainAlias?.hasMetadata && !queryBuilder.expressionMap.insertColumns.length) { + // @ts-expect-error -- protected + const valueSets = queryBuilder.getValueSets(); + if (valueSets.length === 1) { + return Object.keys(valueSets[0]); + } + } + return queryBuilder.expressionMap.insertColumns; + }, + createTableColumnNamesWithPrimaryKey(queryBuilder) { + const columnNames = this.createTableColumnNames(queryBuilder); + if (!columnNames.includes('id')) { + columnNames.unshift('id'); + } + return columnNames; + }, + async insertOne(entity, findOptions?) { + const queryBuilder = this.createQueryBuilder().insert().values(entity); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const mainAlias = queryBuilder.expressionMap.mainAlias!; + const name = mainAlias.name; + mainAlias.name = 't'; + const columnNames = this.createTableColumnNamesWithPrimaryKey(queryBuilder); + queryBuilder.returning(columnNames.reduce((a, c) => `${a}, ${queryBuilder.escape(c)}`, '').slice(2)); + const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + builder.expressionMap.mainAlias!.tablePath = 'cte'; + this.selectAliasColumnNames(queryBuilder, builder); + if (findOptions) { + builder.setFindOptions(findOptions); + } + const raw = await builder.execute(); + mainAlias.name = name; + const relationId = await new RelationIdLoader(builder.connection, this.queryRunner, builder.expressionMap.relationIdAttributes).load(raw); + const relationCount = await new RelationCountLoader(builder.connection, this.queryRunner, builder.expressionMap.relationCountAttributes).load(raw); + const result = new RawSqlResultsToEntityTransformer(builder.expressionMap, builder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, mainAlias); + return result[0]; + }, + selectAliasColumnNames(queryBuilder, builder) { + let selectOrAddSelect = (selection: string, selectionAliasName?: string) => { + selectOrAddSelect = (selection, selectionAliasName) => builder.addSelect(selection, selectionAliasName); + return builder.select(selection, selectionAliasName); + }; + for (const columnName of this.createTableColumnNamesWithPrimaryKey(queryBuilder)) { + selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`); + } + }, +} satisfies MiRepository; export { MiAbuseUserReport, @@ -143,70 +212,70 @@ export { MiReversiGame, }; -export type AbuseUserReportsRepository = Repository; -export type AccessTokensRepository = Repository; -export type AdsRepository = Repository; -export type AnnouncementsRepository = Repository; -export type AnnouncementReadsRepository = Repository; -export type AntennasRepository = Repository; -export type AppsRepository = Repository; -export type AvatarDecorationsRepository = Repository; -export type AuthSessionsRepository = Repository; -export type BlockingsRepository = Repository; -export type ChannelFollowingsRepository = Repository; -export type ChannelFavoritesRepository = Repository; -export type ClipsRepository = Repository; -export type ClipNotesRepository = Repository; -export type ClipFavoritesRepository = Repository; -export type DriveFilesRepository = Repository; -export type DriveFoldersRepository = Repository; -export type EmojisRepository = Repository; -export type FollowingsRepository = Repository; -export type FollowRequestsRepository = Repository; -export type GalleryLikesRepository = Repository; -export type GalleryPostsRepository = Repository; -export type HashtagsRepository = Repository; -export type InstancesRepository = Repository; -export type MetasRepository = Repository; -export type ModerationLogsRepository = Repository; -export type MutingsRepository = Repository; -export type RenoteMutingsRepository = Repository; -export type NotesRepository = Repository; -export type NoteFavoritesRepository = Repository; -export type NoteReactionsRepository = Repository; -export type NoteThreadMutingsRepository = Repository; -export type NoteUnreadsRepository = Repository; -export type PagesRepository = Repository; -export type PageLikesRepository = Repository; -export type PasswordResetRequestsRepository = Repository; -export type PollsRepository = Repository; -export type PollVotesRepository = Repository; -export type PromoNotesRepository = Repository; -export type PromoReadsRepository = Repository; -export type RegistrationTicketsRepository = Repository; -export type RegistryItemsRepository = Repository; -export type RelaysRepository = Repository; -export type SigninsRepository = Repository; -export type SwSubscriptionsRepository = Repository; -export type UsedUsernamesRepository = Repository; -export type UsersRepository = Repository; -export type UserIpsRepository = Repository; -export type UserKeypairsRepository = Repository; -export type UserListsRepository = Repository; -export type UserListFavoritesRepository = Repository; -export type UserListMembershipsRepository = Repository; -export type UserNotePiningsRepository = Repository; -export type UserPendingsRepository = Repository; -export type UserProfilesRepository = Repository; -export type UserPublickeysRepository = Repository; -export type UserSecurityKeysRepository = Repository; -export type WebhooksRepository = Repository; -export type ChannelsRepository = Repository; -export type RetentionAggregationsRepository = Repository; -export type RolesRepository = Repository; -export type RoleAssignmentsRepository = Repository; -export type FlashsRepository = Repository; -export type FlashLikesRepository = Repository; -export type UserMemoRepository = Repository; -export type BubbleGameRecordsRepository = Repository; -export type ReversiGamesRepository = Repository; +export type AbuseUserReportsRepository = Repository & MiRepository; +export type AccessTokensRepository = Repository & MiRepository; +export type AdsRepository = Repository & MiRepository; +export type AnnouncementsRepository = Repository & MiRepository; +export type AnnouncementReadsRepository = Repository & MiRepository; +export type AntennasRepository = Repository & MiRepository; +export type AppsRepository = Repository & MiRepository; +export type AvatarDecorationsRepository = Repository & MiRepository; +export type AuthSessionsRepository = Repository & MiRepository; +export type BlockingsRepository = Repository & MiRepository; +export type ChannelFollowingsRepository = Repository & MiRepository; +export type ChannelFavoritesRepository = Repository & MiRepository; +export type ClipsRepository = Repository & MiRepository; +export type ClipNotesRepository = Repository & MiRepository; +export type ClipFavoritesRepository = Repository & MiRepository; +export type DriveFilesRepository = Repository & MiRepository; +export type DriveFoldersRepository = Repository & MiRepository; +export type EmojisRepository = Repository & MiRepository; +export type FollowingsRepository = Repository & MiRepository; +export type FollowRequestsRepository = Repository & MiRepository; +export type GalleryLikesRepository = Repository & MiRepository; +export type GalleryPostsRepository = Repository & MiRepository; +export type HashtagsRepository = Repository & MiRepository; +export type InstancesRepository = Repository & MiRepository; +export type MetasRepository = Repository & MiRepository; +export type ModerationLogsRepository = Repository & MiRepository; +export type MutingsRepository = Repository & MiRepository; +export type RenoteMutingsRepository = Repository & MiRepository; +export type NotesRepository = Repository & MiRepository; +export type NoteFavoritesRepository = Repository & MiRepository; +export type NoteReactionsRepository = Repository & MiRepository; +export type NoteThreadMutingsRepository = Repository & MiRepository; +export type NoteUnreadsRepository = Repository & MiRepository; +export type PagesRepository = Repository & MiRepository; +export type PageLikesRepository = Repository & MiRepository; +export type PasswordResetRequestsRepository = Repository & MiRepository; +export type PollsRepository = Repository & MiRepository; +export type PollVotesRepository = Repository & MiRepository; +export type PromoNotesRepository = Repository & MiRepository; +export type PromoReadsRepository = Repository & MiRepository; +export type RegistrationTicketsRepository = Repository & MiRepository; +export type RegistryItemsRepository = Repository & MiRepository; +export type RelaysRepository = Repository & MiRepository; +export type SigninsRepository = Repository & MiRepository; +export type SwSubscriptionsRepository = Repository & MiRepository; +export type UsedUsernamesRepository = Repository & MiRepository; +export type UsersRepository = Repository & MiRepository; +export type UserIpsRepository = Repository & MiRepository; +export type UserKeypairsRepository = Repository & MiRepository; +export type UserListsRepository = Repository & MiRepository; +export type UserListFavoritesRepository = Repository & MiRepository; +export type UserListMembershipsRepository = Repository & MiRepository; +export type UserNotePiningsRepository = Repository & MiRepository; +export type UserPendingsRepository = Repository & MiRepository; +export type UserProfilesRepository = Repository & MiRepository; +export type UserPublickeysRepository = Repository & MiRepository; +export type UserSecurityKeysRepository = Repository & MiRepository; +export type WebhooksRepository = Repository & MiRepository; +export type ChannelsRepository = Repository & MiRepository; +export type RetentionAggregationsRepository = Repository & MiRepository; +export type RolesRepository = Repository & MiRepository; +export type RoleAssignmentsRepository = Repository & MiRepository; +export type FlashsRepository = Repository & MiRepository; +export type FlashLikesRepository = Repository & MiRepository; +export type UserMemoRepository = Repository & MiRepository; +export type BubbleGameRecordsRepository = Repository & MiRepository; +export type ReversiGamesRepository = Repository & MiRepository; diff --git a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts index e5b7c5ac52..9c033b73e2 100644 --- a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts @@ -76,7 +76,7 @@ export class ImportAntennasProcessorService { this.logger.warn('Validation Failed'); continue; } - const result = await this.antennasRepository.insert({ + const result = await this.antennasRepository.insertOne({ id: this.idService.gen(now.getTime()), lastUsedAt: now, userId: job.data.user.id, @@ -91,7 +91,7 @@ export class ImportAntennasProcessorService { excludeBots: antenna.excludeBots, withReplies: antenna.withReplies, withFile: antenna.withFile, - }).then(x => this.antennasRepository.findOneByOrFail(x.identifiers[0])); + }); this.logger.succ('Antenna created: ' + result.id); this.globalEventService.publishInternalEvent('antennaCreated', result); } diff --git a/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts b/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts index a5992c28c8..db9255b35d 100644 --- a/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts +++ b/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts @@ -79,11 +79,11 @@ export class ImportUserListsProcessorService { }); if (list == null) { - list = await this.userListsRepository.insert({ + list = await this.userListsRepository.insertOne({ id: this.idService.gen(), userId: user.id, name: listName, - }).then(x => this.userListsRepository.findOneByOrFail(x.identifiers[0])); + }); } let target = this.utilityService.isSelfHost(host!) ? await this.usersRepository.findOneBy({ diff --git a/packages/backend/src/server/api/SigninService.ts b/packages/backend/src/server/api/SigninService.ts index 714e56e8c3..70306c3113 100644 --- a/packages/backend/src/server/api/SigninService.ts +++ b/packages/backend/src/server/api/SigninService.ts @@ -29,13 +29,13 @@ export class SigninService { public signin(request: FastifyRequest, reply: FastifyReply, user: MiLocalUser) { setImmediate(async () => { // Append signin history - const record = await this.signinsRepository.insert({ + const record = await this.signinsRepository.insertOne({ id: this.idService.gen(), userId: user.id, ip: request.ip, headers: request.headers as any, success: true, - }).then(x => this.signinsRepository.findOneByOrFail(x.identifiers[0])); + }); // Publish signin event this.globalEventService.publishMainStream(user.id, 'signin', await this.signinEntityService.pack(record)); diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts index 546de48e6b..632b0c62bc 100644 --- a/packages/backend/src/server/api/SignupApiService.ts +++ b/packages/backend/src/server/api/SignupApiService.ts @@ -183,13 +183,13 @@ export class SignupApiService { const salt = await bcrypt.genSalt(8); const hash = await bcrypt.hash(password, salt); - const pendingUser = await this.userPendingsRepository.insert({ + const pendingUser = await this.userPendingsRepository.insertOne({ id: this.idService.gen(), code, email: emailAddress!, username: username, password: hash, - }).then(x => this.userPendingsRepository.findOneByOrFail(x.identifiers[0])); + }); const link = `${this.config.url}/signup-complete/${code}`; diff --git a/packages/backend/src/server/api/endpoints/admin/ad/create.ts b/packages/backend/src/server/api/endpoints/admin/ad/create.ts index 1e7a9fb3ec..955154f4fb 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/create.ts @@ -50,7 +50,7 @@ export default class extends Endpoint { // eslint- private moderationLogService: ModerationLogService, ) { super(meta, paramDef, async (ps, me) => { - const ad = await this.adsRepository.insert({ + const ad = await this.adsRepository.insertOne({ id: this.idService.gen(), expiresAt: new Date(ps.expiresAt), startsAt: new Date(ps.startsAt), @@ -61,7 +61,7 @@ export default class extends Endpoint { // eslint- ratio: ps.ratio, place: ps.place, memo: ps.memo, - }).then(r => this.adsRepository.findOneByOrFail({ id: r.identifiers[0].id })); + }); this.moderationLogService.log(me, 'createAd', { adId: ad.id, diff --git a/packages/backend/src/server/api/endpoints/admin/invite/create.ts b/packages/backend/src/server/api/endpoints/admin/invite/create.ts index 0f551e1ba2..5ecae3161a 100644 --- a/packages/backend/src/server/api/endpoints/admin/invite/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/invite/create.ts @@ -66,11 +66,11 @@ export default class extends Endpoint { // eslint- const ticketsPromises = []; for (let i = 0; i < ps.count; i++) { - ticketsPromises.push(this.registrationTicketsRepository.insert({ + ticketsPromises.push(this.registrationTicketsRepository.insertOne({ id: this.idService.gen(), expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null, code: generateInviteCode(), - }).then(x => this.registrationTicketsRepository.findOneByOrFail(x.identifiers[0]))); + })); } const tickets = await Promise.all(ticketsPromises); diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts index 6b7bacb054..ec08198514 100644 --- a/packages/backend/src/server/api/endpoints/antennas/create.ts +++ b/packages/backend/src/server/api/endpoints/antennas/create.ts @@ -112,7 +112,7 @@ export default class extends Endpoint { // eslint- const now = new Date(); - const antenna = await this.antennasRepository.insert({ + const antenna = await this.antennasRepository.insertOne({ id: this.idService.gen(now.getTime()), lastUsedAt: now, userId: me.id, @@ -127,7 +127,7 @@ export default class extends Endpoint { // eslint- excludeBots: ps.excludeBots, withReplies: ps.withReplies, withFile: ps.withFile, - }).then(x => this.antennasRepository.findOneByOrFail(x.identifiers[0])); + }); this.globalEventService.publishInternalEvent('antennaCreated', antenna); diff --git a/packages/backend/src/server/api/endpoints/app/create.ts b/packages/backend/src/server/api/endpoints/app/create.ts index 492705d6f9..ba847fc4f0 100644 --- a/packages/backend/src/server/api/endpoints/app/create.ts +++ b/packages/backend/src/server/api/endpoints/app/create.ts @@ -54,7 +54,7 @@ export default class extends Endpoint { // eslint- const permission = unique(ps.permission.map(v => v.replace(/^(.+)(\/|-)(read|write)$/, '$3:$1'))); // Create account - const app = await this.appsRepository.insert({ + const app = await this.appsRepository.insertOne({ id: this.idService.gen(), userId: me ? me.id : null, name: ps.name, @@ -62,7 +62,7 @@ export default class extends Endpoint { // eslint- permission, callbackUrl: ps.callbackUrl, secret: secret, - }).then(x => this.appsRepository.findOneByOrFail(x.identifiers[0])); + }); return await this.appEntityService.pack(app, null, { detail: true, diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts index 26dd893138..f8ddfdb75c 100644 --- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts +++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts @@ -78,11 +78,11 @@ export default class extends Endpoint { // eslint- const token = randomUUID(); // Create session token document - const doc = await this.authSessionsRepository.insert({ + const doc = await this.authSessionsRepository.insertOne({ id: this.idService.gen(), appId: app.id, token: token, - }).then(x => this.authSessionsRepository.findOneByOrFail(x.identifiers[0])); + }); return { token: doc.token, diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts index 2866db5424..e3a6d2d670 100644 --- a/packages/backend/src/server/api/endpoints/channels/create.ts +++ b/packages/backend/src/server/api/endpoints/channels/create.ts @@ -80,7 +80,7 @@ export default class extends Endpoint { // eslint- } } - const channel = await this.channelsRepository.insert({ + const channel = await this.channelsRepository.insertOne({ id: this.idService.gen(), userId: me.id, name: ps.name, @@ -89,7 +89,7 @@ export default class extends Endpoint { // eslint- isSensitive: ps.isSensitive ?? false, ...(ps.color !== undefined ? { color: ps.color } : {}), allowRenoteToExternal: ps.allowRenoteToExternal ?? true, - } as MiChannel).then(x => this.channelsRepository.findOneByOrFail(x.identifiers[0])); + } as MiChannel); return await this.channelEntityService.pack(channel, me); }); diff --git a/packages/backend/src/server/api/endpoints/drive/folders/create.ts b/packages/backend/src/server/api/endpoints/drive/folders/create.ts index c94070d9ff..08d9d9cdc3 100644 --- a/packages/backend/src/server/api/endpoints/drive/folders/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/folders/create.ts @@ -75,12 +75,12 @@ export default class extends Endpoint { // eslint- } // Create folder - const folder = await this.driveFoldersRepository.insert({ + const folder = await this.driveFoldersRepository.insertOne({ id: this.idService.gen(), name: ps.name, parentId: parent !== null ? parent.id : null, userId: me.id, - }).then(x => this.driveFoldersRepository.findOneByOrFail(x.identifiers[0])); + }); const folderObj = await this.driveFolderEntityService.pack(folder); diff --git a/packages/backend/src/server/api/endpoints/flash/create.ts b/packages/backend/src/server/api/endpoints/flash/create.ts index 361496e17e..64f13a577e 100644 --- a/packages/backend/src/server/api/endpoints/flash/create.ts +++ b/packages/backend/src/server/api/endpoints/flash/create.ts @@ -59,7 +59,7 @@ export default class extends Endpoint { // eslint- private idService: IdService, ) { super(meta, paramDef, async (ps, me) => { - const flash = await this.flashsRepository.insert({ + const flash = await this.flashsRepository.insertOne({ id: this.idService.gen(), userId: me.id, updatedAt: new Date(), @@ -68,7 +68,7 @@ export default class extends Endpoint { // eslint- script: ps.script, permissions: ps.permissions, visibility: ps.visibility, - }).then(x => this.flashsRepository.findOneByOrFail(x.identifiers[0])); + }); return await this.flashEntityService.pack(flash); }); diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts index b07cdf1ed9..46f8998810 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts @@ -76,7 +76,7 @@ export default class extends Endpoint { // eslint- throw new Error(); } - const post = await this.galleryPostsRepository.insert(new MiGalleryPost({ + const post = await this.galleryPostsRepository.insertOne(new MiGalleryPost({ id: this.idService.gen(), updatedAt: new Date(), title: ps.title, @@ -84,7 +84,7 @@ export default class extends Endpoint { // eslint- userId: me.id, isSensitive: ps.isSensitive, fileIds: files.map(file => file.id), - })).then(x => this.galleryPostsRepository.findOneByOrFail(x.identifiers[0])); + })); return await this.galleryPostEntityService.pack(post, me); }); diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts index 535a3ea308..c692380288 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts @@ -89,14 +89,14 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.tooManyWebhooks); } - const webhook = await this.webhooksRepository.insert({ + const webhook = await this.webhooksRepository.insertOne({ id: this.idService.gen(), userId: me.id, name: ps.name, url: ps.url, secret: ps.secret, on: ps.on, - }).then(x => this.webhooksRepository.findOneByOrFail(x.identifiers[0])); + }); this.globalEventService.publishInternalEvent('webhookCreated', webhook); diff --git a/packages/backend/src/server/api/endpoints/invite/create.ts b/packages/backend/src/server/api/endpoints/invite/create.ts index 0ff125ad9c..a70b587da7 100644 --- a/packages/backend/src/server/api/endpoints/invite/create.ts +++ b/packages/backend/src/server/api/endpoints/invite/create.ts @@ -66,13 +66,13 @@ export default class extends Endpoint { // eslint- } } - const ticket = await this.registrationTicketsRepository.insert({ + const ticket = await this.registrationTicketsRepository.insertOne({ id: this.idService.gen(), createdBy: me, createdById: me.id, expiresAt: policies.inviteExpirationTime ? new Date(Date.now() + (policies.inviteExpirationTime * 1000 * 60)) : null, code: generateInviteCode(), - }).then(x => this.registrationTicketsRepository.findOneByOrFail(x.identifiers[0])); + }); return await this.inviteCodeEntityService.pack(ticket, me); }); diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts index a91c506afd..f33f49075b 100644 --- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts +++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts @@ -144,12 +144,12 @@ export default class extends Endpoint { // eslint- } // Create vote - const vote = await this.pollVotesRepository.insert({ + const vote = await this.pollVotesRepository.insertOne({ id: this.idService.gen(createdAt.getTime()), noteId: note.id, userId: me.id, choice: ps.choice, - }).then(x => this.pollVotesRepository.findOneByOrFail(x.identifiers[0])); + }); // Increment votes count const index = ps.choice + 1; // In SQL, array index is 1 based diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts index 3a02d359f8..fa03b0b457 100644 --- a/packages/backend/src/server/api/endpoints/pages/create.ts +++ b/packages/backend/src/server/api/endpoints/pages/create.ts @@ -102,7 +102,7 @@ export default class extends Endpoint { // eslint- } }); - const page = await this.pagesRepository.insert(new MiPage({ + const page = await this.pagesRepository.insertOne(new MiPage({ id: this.idService.gen(), updatedAt: new Date(), title: ps.title, @@ -117,7 +117,7 @@ export default class extends Endpoint { // eslint- alignCenter: ps.alignCenter, hideTitleWhenPinned: ps.hideTitleWhenPinned, font: ps.font, - })).then(x => this.pagesRepository.findOneByOrFail(x.identifiers[0])); + })); return await this.pageEntityService.pack(page); }); diff --git a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts index e2db71c5c7..8504da0209 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts @@ -104,11 +104,11 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.tooManyUserLists); } - const userList = await this.userListsRepository.insert({ + const userList = await this.userListsRepository.insertOne({ id: this.idService.gen(), userId: me.id, name: ps.name, - } as MiUserList).then(x => this.userListsRepository.findOneByOrFail(x.identifiers[0])); + } as MiUserList); const users = (await this.userListMembershipsRepository.findBy({ userListId: ps.listId, diff --git a/packages/backend/src/server/api/endpoints/users/lists/create.ts b/packages/backend/src/server/api/endpoints/users/lists/create.ts index 952580e639..9378bde5cb 100644 --- a/packages/backend/src/server/api/endpoints/users/lists/create.ts +++ b/packages/backend/src/server/api/endpoints/users/lists/create.ts @@ -65,11 +65,11 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.tooManyUserLists); } - const userList = await this.userListsRepository.insert({ + const userList = await this.userListsRepository.insertOne({ id: this.idService.gen(), userId: me.id, name: ps.name, - } as MiUserList).then(x => this.userListsRepository.findOneByOrFail(x.identifiers[0])); + } as MiUserList); return await this.userListEntityService.pack(userList); }); diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts index 1750dd6206..48e14b68cc 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -82,14 +82,14 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.cannotReportAdmin); } - const report = await this.abuseUserReportsRepository.insert({ + const report = await this.abuseUserReportsRepository.insertOne({ id: this.idService.gen(), targetUserId: user.id, targetUserHost: user.host, reporterId: me.id, reporterHost: null, comment: ps.comment, - }).then(x => this.abuseUserReportsRepository.findOneByOrFail(x.identifiers[0])); + }); // Publish event to moderators setImmediate(async () => { diff --git a/packages/backend/test/e2e/move.ts b/packages/backend/test/e2e/move.ts index 35050130dc..74cf61a785 100644 --- a/packages/backend/test/e2e/move.ts +++ b/packages/backend/test/e2e/move.ts @@ -9,7 +9,7 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; import { loadConfig } from '@/config.js'; -import { MiUser, UsersRepository } from '@/models/_.js'; +import { MiRepository, MiUser, UsersRepository, miRepository } from '@/models/_.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { jobQueue } from '@/boot/common.js'; import { api, initTestDb, signup, sleep, successfulApiCall, uploadFile } from '../utils.js'; @@ -42,7 +42,7 @@ describe('Account Move', () => { dave = await signup({ username: 'dave' }); eve = await signup({ username: 'eve' }); frank = await signup({ username: 'frank' }); - Users = connection.getRepository(MiUser); + Users = connection.getRepository(MiUser).extend(miRepository as MiRepository); }, 1000 * 60 * 2); afterAll(async () => { diff --git a/packages/backend/test/e2e/reversi-game.ts b/packages/backend/test/e2e/reversi-game.ts new file mode 100644 index 0000000000..788255beac --- /dev/null +++ b/packages/backend/test/e2e/reversi-game.ts @@ -0,0 +1,33 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +process.env.NODE_ENV = 'test'; + +import * as assert from 'assert'; +import { ReversiMatchResponse } from 'misskey-js/entities.js'; +import { api, signup } from '../utils.js'; +import type * as misskey from 'misskey-js'; + +describe('ReversiGame', () => { + let alice: misskey.entities.SignupResponse; + let bob: misskey.entities.SignupResponse; + + beforeAll(async () => { + alice = await signup({ username: 'alice' }); + bob = await signup({ username: 'bob' }); + }, 1000 * 60 * 2); + + test('matches when alice invites bob and bob accepts', async () => { + const response1 = await api('reversi/match', { userId: bob.id }, alice); + assert.strictEqual(response1.status, 204); + assert.strictEqual(response1.body, null); + const response2 = await api('reversi/match', { userId: alice.id }, bob); + assert.strictEqual(response2.status, 200); + assert.notStrictEqual(response2.body, null); + const body = response2.body as ReversiMatchResponse; + assert.strictEqual(body.user1.id, alice.id); + assert.strictEqual(body.user2.id, bob.id); + }); +}); From 27ac3d795e7098124a7eea0dd59f6f1ef8f32394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:14:37 +0900 Subject: [PATCH 005/246] Update about-misskey.vue --- packages/frontend/src/pages/about-misskey.vue | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue index b55ae220d8..629f00689d 100644 --- a/packages/frontend/src/pages/about-misskey.vue +++ b/packages/frontend/src/pages/about-misskey.vue @@ -102,13 +102,16 @@ SPDX-License-Identifier: AGPL-3.0-only
- Mask Network + Mask Network
- XServer + XServer
- Skeb + Skeb +
+
+ Skeb
From 43cccaaee9be42fab38eaa9ca04bb5e55b5d8db7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Tue, 4 Jun 2024 13:15:35 +0900 Subject: [PATCH 006/246] fix --- packages/frontend/src/pages/about-misskey.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue index 629f00689d..cc0394f401 100644 --- a/packages/frontend/src/pages/about-misskey.vue +++ b/packages/frontend/src/pages/about-misskey.vue @@ -111,7 +111,7 @@ SPDX-License-Identifier: AGPL-3.0-only Skeb
- Skeb + GMO Pepabo
From d4a8c63264939c4ec36af628f7e1516d2ae60254 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 6 Jun 2024 09:32:04 +0900 Subject: [PATCH 007/246] enhance(backend): sentry integration for job queues --- .../src/queue/QueueProcessorService.ts | 389 +++++++++++------- 1 file changed, 231 insertions(+), 158 deletions(-) diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index ce999d9cef..eb1901d069 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -5,6 +5,7 @@ import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; import * as Bull from 'bullmq'; +import * as Sentry from '@sentry/node'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; @@ -135,199 +136,271 @@ export class QueueProcessorService implements OnApplicationShutdown { } //#region system - this.systemQueueWorker = new Bull.Worker(QUEUE.SYSTEM, (job) => { - switch (job.name) { - case 'tickCharts': return this.tickChartsProcessorService.process(); - case 'resyncCharts': return this.resyncChartsProcessorService.process(); - case 'cleanCharts': return this.cleanChartsProcessorService.process(); - case 'aggregateRetention': return this.aggregateRetentionProcessorService.process(); - case 'checkExpiredMutings': return this.checkExpiredMutingsProcessorService.process(); - case 'clean': return this.cleanProcessorService.process(); - default: throw new Error(`unrecognized job type ${job.name} for system`); - } - }, { - ...baseQueueOptions(this.config, QUEUE.SYSTEM), - autorun: false, - }); + { + const processer = (job: Bull.Job) => { + switch (job.name) { + case 'tickCharts': return this.tickChartsProcessorService.process(); + case 'resyncCharts': return this.resyncChartsProcessorService.process(); + case 'cleanCharts': return this.cleanChartsProcessorService.process(); + case 'aggregateRetention': return this.aggregateRetentionProcessorService.process(); + case 'checkExpiredMutings': return this.checkExpiredMutingsProcessorService.process(); + case 'clean': return this.cleanProcessorService.process(); + default: throw new Error(`unrecognized job type ${job.name} for system`); + } + }; - const systemLogger = this.logger.createSubLogger('system'); + this.systemQueueWorker = new Bull.Worker(QUEUE.SYSTEM, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: System: ' + job.name }, () => processer(job)); + } else { + return processer(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.SYSTEM), + autorun: false, + }); - this.systemQueueWorker - .on('active', (job) => systemLogger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => systemLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => systemLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => systemLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => systemLogger.warn(`stalled id=${jobId}`)); + const systemLogger = this.logger.createSubLogger('system'); + + this.systemQueueWorker + .on('active', (job) => systemLogger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => systemLogger.debug(`completed(${result}) id=${job.id}`)) + .on('failed', (job, err) => systemLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => systemLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => systemLogger.warn(`stalled id=${jobId}`)); + } //#endregion //#region db - this.dbQueueWorker = new Bull.Worker(QUEUE.DB, (job) => { - switch (job.name) { - case 'deleteDriveFiles': return this.deleteDriveFilesProcessorService.process(job); - case 'exportCustomEmojis': return this.exportCustomEmojisProcessorService.process(job); - case 'exportNotes': return this.exportNotesProcessorService.process(job); - case 'exportClips': return this.exportClipsProcessorService.process(job); - case 'exportFavorites': return this.exportFavoritesProcessorService.process(job); - case 'exportFollowing': return this.exportFollowingProcessorService.process(job); - case 'exportMuting': return this.exportMutingProcessorService.process(job); - case 'exportBlocking': return this.exportBlockingProcessorService.process(job); - case 'exportUserLists': return this.exportUserListsProcessorService.process(job); - case 'exportAntennas': return this.exportAntennasProcessorService.process(job); - case 'importFollowing': return this.importFollowingProcessorService.process(job); - case 'importFollowingToDb': return this.importFollowingProcessorService.processDb(job); - case 'importMuting': return this.importMutingProcessorService.process(job); - case 'importBlocking': return this.importBlockingProcessorService.process(job); - case 'importBlockingToDb': return this.importBlockingProcessorService.processDb(job); - case 'importUserLists': return this.importUserListsProcessorService.process(job); - case 'importCustomEmojis': return this.importCustomEmojisProcessorService.process(job); - case 'importAntennas': return this.importAntennasProcessorService.process(job); - case 'deleteAccount': return this.deleteAccountProcessorService.process(job); - default: throw new Error(`unrecognized job type ${job.name} for db`); - } - }, { - ...baseQueueOptions(this.config, QUEUE.DB), - autorun: false, - }); + { + const processer = (job: Bull.Job) => { + switch (job.name) { + case 'deleteDriveFiles': return this.deleteDriveFilesProcessorService.process(job); + case 'exportCustomEmojis': return this.exportCustomEmojisProcessorService.process(job); + case 'exportNotes': return this.exportNotesProcessorService.process(job); + case 'exportClips': return this.exportClipsProcessorService.process(job); + case 'exportFavorites': return this.exportFavoritesProcessorService.process(job); + case 'exportFollowing': return this.exportFollowingProcessorService.process(job); + case 'exportMuting': return this.exportMutingProcessorService.process(job); + case 'exportBlocking': return this.exportBlockingProcessorService.process(job); + case 'exportUserLists': return this.exportUserListsProcessorService.process(job); + case 'exportAntennas': return this.exportAntennasProcessorService.process(job); + case 'importFollowing': return this.importFollowingProcessorService.process(job); + case 'importFollowingToDb': return this.importFollowingProcessorService.processDb(job); + case 'importMuting': return this.importMutingProcessorService.process(job); + case 'importBlocking': return this.importBlockingProcessorService.process(job); + case 'importBlockingToDb': return this.importBlockingProcessorService.processDb(job); + case 'importUserLists': return this.importUserListsProcessorService.process(job); + case 'importCustomEmojis': return this.importCustomEmojisProcessorService.process(job); + case 'importAntennas': return this.importAntennasProcessorService.process(job); + case 'deleteAccount': return this.deleteAccountProcessorService.process(job); + default: throw new Error(`unrecognized job type ${job.name} for db`); + } + }; - const dbLogger = this.logger.createSubLogger('db'); + this.dbQueueWorker = new Bull.Worker(QUEUE.DB, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: DB: ' + job.name }, () => processer(job)); + } else { + return processer(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.DB), + autorun: false, + }); - this.dbQueueWorker - .on('active', (job) => dbLogger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => dbLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => dbLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => dbLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => dbLogger.warn(`stalled id=${jobId}`)); + const dbLogger = this.logger.createSubLogger('db'); + + this.dbQueueWorker + .on('active', (job) => dbLogger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => dbLogger.debug(`completed(${result}) id=${job.id}`)) + .on('failed', (job, err) => dbLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => dbLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => dbLogger.warn(`stalled id=${jobId}`)); + } //#endregion //#region deliver - this.deliverQueueWorker = new Bull.Worker(QUEUE.DELIVER, (job) => this.deliverProcessorService.process(job), { - ...baseQueueOptions(this.config, QUEUE.DELIVER), - autorun: false, - concurrency: this.config.deliverJobConcurrency ?? 128, - limiter: { - max: this.config.deliverJobPerSec ?? 128, - duration: 1000, - }, - settings: { - backoffStrategy: httpRelatedBackoff, - }, - }); + { + this.deliverQueueWorker = new Bull.Worker(QUEUE.DELIVER, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: Deliver' }, () => this.deliverProcessorService.process(job)); + } else { + return this.deliverProcessorService.process(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.DELIVER), + autorun: false, + concurrency: this.config.deliverJobConcurrency ?? 128, + limiter: { + max: this.config.deliverJobPerSec ?? 128, + duration: 1000, + }, + settings: { + backoffStrategy: httpRelatedBackoff, + }, + }); - const deliverLogger = this.logger.createSubLogger('deliver'); + const deliverLogger = this.logger.createSubLogger('deliver'); - this.deliverQueueWorker - .on('active', (job) => deliverLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('completed', (job, result) => deliverLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('failed', (job, err) => deliverLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) - .on('error', (err: Error) => deliverLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => deliverLogger.warn(`stalled id=${jobId}`)); + this.deliverQueueWorker + .on('active', (job) => deliverLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('completed', (job, result) => deliverLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('failed', (job, err) => deliverLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) + .on('error', (err: Error) => deliverLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => deliverLogger.warn(`stalled id=${jobId}`)); + } //#endregion //#region inbox - this.inboxQueueWorker = new Bull.Worker(QUEUE.INBOX, (job) => this.inboxProcessorService.process(job), { - ...baseQueueOptions(this.config, QUEUE.INBOX), - autorun: false, - concurrency: this.config.inboxJobConcurrency ?? 16, - limiter: { - max: this.config.inboxJobPerSec ?? 32, - duration: 1000, - }, - settings: { - backoffStrategy: httpRelatedBackoff, - }, - }); + { + this.inboxQueueWorker = new Bull.Worker(QUEUE.INBOX, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: Inbox' }, () => this.inboxProcessorService.process(job)); + } else { + return this.inboxProcessorService.process(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.INBOX), + autorun: false, + concurrency: this.config.inboxJobConcurrency ?? 16, + limiter: { + max: this.config.inboxJobPerSec ?? 32, + duration: 1000, + }, + settings: { + backoffStrategy: httpRelatedBackoff, + }, + }); - const inboxLogger = this.logger.createSubLogger('inbox'); + const inboxLogger = this.logger.createSubLogger('inbox'); - this.inboxQueueWorker - .on('active', (job) => inboxLogger.debug(`active ${getJobInfo(job, true)}`)) - .on('completed', (job, result) => inboxLogger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) - .on('failed', (job, err) => inboxLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => inboxLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => inboxLogger.warn(`stalled id=${jobId}`)); + this.inboxQueueWorker + .on('active', (job) => inboxLogger.debug(`active ${getJobInfo(job, true)}`)) + .on('completed', (job, result) => inboxLogger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) + .on('failed', (job, err) => inboxLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => inboxLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => inboxLogger.warn(`stalled id=${jobId}`)); + } //#endregion //#region webhook deliver - this.webhookDeliverQueueWorker = new Bull.Worker(QUEUE.WEBHOOK_DELIVER, (job) => this.webhookDeliverProcessorService.process(job), { - ...baseQueueOptions(this.config, QUEUE.WEBHOOK_DELIVER), - autorun: false, - concurrency: 64, - limiter: { - max: 64, - duration: 1000, - }, - settings: { - backoffStrategy: httpRelatedBackoff, - }, - }); + { + this.webhookDeliverQueueWorker = new Bull.Worker(QUEUE.WEBHOOK_DELIVER, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: WebhookDeliver' }, () => this.webhookDeliverProcessorService.process(job)); + } else { + return this.webhookDeliverProcessorService.process(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.WEBHOOK_DELIVER), + autorun: false, + concurrency: 64, + limiter: { + max: 64, + duration: 1000, + }, + settings: { + backoffStrategy: httpRelatedBackoff, + }, + }); - const webhookLogger = this.logger.createSubLogger('webhook'); + const webhookLogger = this.logger.createSubLogger('webhook'); - this.webhookDeliverQueueWorker - .on('active', (job) => webhookLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('completed', (job, result) => webhookLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('failed', (job, err) => webhookLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) - .on('error', (err: Error) => webhookLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => webhookLogger.warn(`stalled id=${jobId}`)); + this.webhookDeliverQueueWorker + .on('active', (job) => webhookLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('completed', (job, result) => webhookLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('failed', (job, err) => webhookLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) + .on('error', (err: Error) => webhookLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => webhookLogger.warn(`stalled id=${jobId}`)); + } //#endregion //#region relationship - this.relationshipQueueWorker = new Bull.Worker(QUEUE.RELATIONSHIP, (job) => { - switch (job.name) { - case 'follow': return this.relationshipProcessorService.processFollow(job); - case 'unfollow': return this.relationshipProcessorService.processUnfollow(job); - case 'block': return this.relationshipProcessorService.processBlock(job); - case 'unblock': return this.relationshipProcessorService.processUnblock(job); - default: throw new Error(`unrecognized job type ${job.name} for relationship`); - } - }, { - ...baseQueueOptions(this.config, QUEUE.RELATIONSHIP), - autorun: false, - concurrency: this.config.relationshipJobConcurrency ?? 16, - limiter: { - max: this.config.relationshipJobPerSec ?? 64, - duration: 1000, - }, - }); + { + const processer = (job: Bull.Job) => { + switch (job.name) { + case 'follow': return this.relationshipProcessorService.processFollow(job); + case 'unfollow': return this.relationshipProcessorService.processUnfollow(job); + case 'block': return this.relationshipProcessorService.processBlock(job); + case 'unblock': return this.relationshipProcessorService.processUnblock(job); + default: throw new Error(`unrecognized job type ${job.name} for relationship`); + } + }; - const relationshipLogger = this.logger.createSubLogger('relationship'); + this.relationshipQueueWorker = new Bull.Worker(QUEUE.RELATIONSHIP, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: Relationship: ' + job.name }, () => processer(job)); + } else { + return processer(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.RELATIONSHIP), + autorun: false, + concurrency: this.config.relationshipJobConcurrency ?? 16, + limiter: { + max: this.config.relationshipJobPerSec ?? 64, + duration: 1000, + }, + }); - this.relationshipQueueWorker - .on('active', (job) => relationshipLogger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => relationshipLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => relationshipLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => relationshipLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => relationshipLogger.warn(`stalled id=${jobId}`)); + const relationshipLogger = this.logger.createSubLogger('relationship'); + + this.relationshipQueueWorker + .on('active', (job) => relationshipLogger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => relationshipLogger.debug(`completed(${result}) id=${job.id}`)) + .on('failed', (job, err) => relationshipLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => relationshipLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => relationshipLogger.warn(`stalled id=${jobId}`)); + } //#endregion //#region object storage - this.objectStorageQueueWorker = new Bull.Worker(QUEUE.OBJECT_STORAGE, (job) => { - switch (job.name) { - case 'deleteFile': return this.deleteFileProcessorService.process(job); - case 'cleanRemoteFiles': return this.cleanRemoteFilesProcessorService.process(job); - default: throw new Error(`unrecognized job type ${job.name} for objectStorage`); - } - }, { - ...baseQueueOptions(this.config, QUEUE.OBJECT_STORAGE), - autorun: false, - concurrency: 16, - }); + { + const processer = (job: Bull.Job) => { + switch (job.name) { + case 'deleteFile': return this.deleteFileProcessorService.process(job); + case 'cleanRemoteFiles': return this.cleanRemoteFilesProcessorService.process(job); + default: throw new Error(`unrecognized job type ${job.name} for objectStorage`); + } + }; - const objectStorageLogger = this.logger.createSubLogger('objectStorage'); + this.objectStorageQueueWorker = new Bull.Worker(QUEUE.OBJECT_STORAGE, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: ObjectStorage: ' + job.name }, () => processer(job)); + } else { + return processer(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.OBJECT_STORAGE), + autorun: false, + concurrency: 16, + }); - this.objectStorageQueueWorker - .on('active', (job) => objectStorageLogger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => objectStorageLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => objectStorageLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) - .on('error', (err: Error) => objectStorageLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => objectStorageLogger.warn(`stalled id=${jobId}`)); + const objectStorageLogger = this.logger.createSubLogger('objectStorage'); + + this.objectStorageQueueWorker + .on('active', (job) => objectStorageLogger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => objectStorageLogger.debug(`completed(${result}) id=${job.id}`)) + .on('failed', (job, err) => objectStorageLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('error', (err: Error) => objectStorageLogger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => objectStorageLogger.warn(`stalled id=${jobId}`)); + } //#endregion //#region ended poll notification - this.endedPollNotificationQueueWorker = new Bull.Worker(QUEUE.ENDED_POLL_NOTIFICATION, (job) => this.endedPollNotificationProcessorService.process(job), { - ...baseQueueOptions(this.config, QUEUE.ENDED_POLL_NOTIFICATION), - autorun: false, - }); + { + this.endedPollNotificationQueueWorker = new Bull.Worker(QUEUE.ENDED_POLL_NOTIFICATION, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: EndedPollNotification' }, () => this.endedPollNotificationProcessorService.process(job)); + } else { + return this.endedPollNotificationProcessorService.process(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.ENDED_POLL_NOTIFICATION), + autorun: false, + }); + } //#endregion } From dbf9e1194bf5b84ec711c14f27c11d2bfeb37f20 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:01:50 +0900 Subject: [PATCH 008/246] refactor(backend): remove unused logger option --- packages/backend/src/core/LoggerService.ts | 4 ++-- .../backend/src/core/chart/ChartLoggerService.ts | 2 +- packages/backend/src/logger.ts | 14 +++++--------- packages/backend/src/server/FileServerService.ts | 2 +- packages/backend/src/server/ServerService.ts | 2 +- 5 files changed, 10 insertions(+), 14 deletions(-) diff --git a/packages/backend/src/core/LoggerService.ts b/packages/backend/src/core/LoggerService.ts index 96d9b09992..f102461a50 100644 --- a/packages/backend/src/core/LoggerService.ts +++ b/packages/backend/src/core/LoggerService.ts @@ -15,7 +15,7 @@ export class LoggerService { } @bindThis - public getLogger(domain: string, color?: KEYWORD | undefined, store?: boolean) { - return new Logger(domain, color, store); + public getLogger(domain: string, color?: KEYWORD | undefined) { + return new Logger(domain, color); } } diff --git a/packages/backend/src/core/chart/ChartLoggerService.ts b/packages/backend/src/core/chart/ChartLoggerService.ts index afc728d564..20815ea968 100644 --- a/packages/backend/src/core/chart/ChartLoggerService.ts +++ b/packages/backend/src/core/chart/ChartLoggerService.ts @@ -14,6 +14,6 @@ export class ChartLoggerService { constructor( private loggerService: LoggerService, ) { - this.logger = this.loggerService.getLogger('chart', 'white', process.env.NODE_ENV !== 'test'); + this.logger = this.loggerService.getLogger('chart', 'white'); } } diff --git a/packages/backend/src/logger.ts b/packages/backend/src/logger.ts index d4705af601..ff5363a425 100644 --- a/packages/backend/src/logger.ts +++ b/packages/backend/src/logger.ts @@ -22,31 +22,27 @@ type Level = 'error' | 'success' | 'warning' | 'debug' | 'info'; export default class Logger { private context: Context; private parentLogger: Logger | null = null; - private store: boolean; - constructor(context: string, color?: KEYWORD, store = true) { + constructor(context: string, color?: KEYWORD) { this.context = { name: context, color: color, }; - this.store = store; } @bindThis - public createSubLogger(context: string, color?: KEYWORD, store = true): Logger { - const logger = new Logger(context, color, store); + public createSubLogger(context: string, color?: KEYWORD): Logger { + const logger = new Logger(context, color); logger.parentLogger = this; return logger; } @bindThis - private log(level: Level, message: string, data?: Record | null, important = false, subContexts: Context[] = [], store = true): void { + private log(level: Level, message: string, data?: Record | null, important = false, subContexts: Context[] = []): void { if (envOption.quiet) return; - if (!this.store) store = false; - if (level === 'debug') store = false; if (this.parentLogger) { - this.parentLogger.log(level, message, data, important, [this.context].concat(subContexts), store); + this.parentLogger.log(level, message, data, important, [this.context].concat(subContexts)); return; } diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts index 9db3aa1bfb..77a637d895 100644 --- a/packages/backend/src/server/FileServerService.ts +++ b/packages/backend/src/server/FileServerService.ts @@ -53,7 +53,7 @@ export class FileServerService { private internalStorageService: InternalStorageService, private loggerService: LoggerService, ) { - this.logger = this.loggerService.getLogger('server', 'gray', false); + this.logger = this.loggerService.getLogger('server', 'gray'); //this.createServer = this.createServer.bind(this); } diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index 3572f16627..9c849480f2 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -68,7 +68,7 @@ export class ServerService implements OnApplicationShutdown { private loggerService: LoggerService, private oauth2ProviderService: OAuth2ProviderService, ) { - this.logger = this.loggerService.getLogger('server', 'gray', false); + this.logger = this.loggerService.getLogger('server', 'gray'); } @bindThis From 65d19279a2c19c3e6be1c4c50cc9b01c94420d6c Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:11:43 +0900 Subject: [PATCH 009/246] fix --- packages/backend/src/boot/master.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index 75e1a80cd1..4bc5c799cf 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -25,7 +25,7 @@ const _dirname = dirname(_filename); const meta = JSON.parse(fs.readFileSync(`${_dirname}/../../../../built/meta.json`, 'utf-8')); const logger = new Logger('core', 'cyan'); -const bootLogger = logger.createSubLogger('boot', 'magenta', false); +const bootLogger = logger.createSubLogger('boot', 'magenta'); const themeColor = chalk.hex('#86b300'); From ab69e113f4921462b72f1f352dfefe52b37862f5 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:20:54 +0900 Subject: [PATCH 010/246] enhance(backend): improve sentry integration --- packages/backend/src/boot/worker.ts | 23 +++++++++++++++++++ .../src/queue/QueueProcessorService.ts | 4 ++-- .../backend/src/server/api/ApiCallService.ts | 14 +++++++---- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/boot/worker.ts b/packages/backend/src/boot/worker.ts index d4a7cd56e5..5d4a15b29f 100644 --- a/packages/backend/src/boot/worker.ts +++ b/packages/backend/src/boot/worker.ts @@ -4,13 +4,36 @@ */ import cluster from 'node:cluster'; +import * as Sentry from '@sentry/node'; +import { nodeProfilingIntegration } from '@sentry/profiling-node'; import { envOption } from '@/env.js'; +import { loadConfig } from '@/config.js'; import { jobQueue, server } from './common.js'; /** * Init worker process */ export async function workerMain() { + const config = loadConfig(); + + if (config.sentryForBackend) { + Sentry.init({ + integrations: [ + ...(config.sentryForBackend.enableNodeProfiling ? [nodeProfilingIntegration()] : []), + ], + + // Performance Monitoring + tracesSampleRate: 1.0, // Capture 100% of the transactions + + // Set sampling rate for profiling - this is relative to tracesSampleRate + profilesSampleRate: 1.0, + + maxBreadcrumbs: 0, + + ...config.sentryForBackend.options, + }); + } + if (envOption.onlyServer) { await server(); } else if (envOption.onlyQueue) { diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index eb1901d069..4f333df791 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -165,7 +165,7 @@ export class QueueProcessorService implements OnApplicationShutdown { this.systemQueueWorker .on('active', (job) => systemLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => systemLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => systemLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('failed', (job, err) => systemLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) .on('error', (err: Error) => systemLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => systemLogger.warn(`stalled id=${jobId}`)); } @@ -214,7 +214,7 @@ export class QueueProcessorService implements OnApplicationShutdown { this.dbQueueWorker .on('active', (job) => dbLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => dbLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => dbLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('failed', (job, err) => dbLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) .on('error', (err: Error) => dbLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => dbLogger.warn(`stalled id=${jobId}`)); } diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index 271ef80554..e21a5e90ab 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -93,7 +93,7 @@ export class ApiCallService implements OnApplicationShutdown { } } - #onExecError(ep: IEndpoint, data: any, err: Error): void { + #onExecError(ep: IEndpoint, data: any, err: Error, userId?: MiUser['id']): void { if (err instanceof ApiError || err instanceof AuthenticationError) { throw err; } else { @@ -108,10 +108,12 @@ export class ApiCallService implements OnApplicationShutdown { id: errId, }, }); - console.error(err, errId); if (this.config.sentryForBackend) { Sentry.captureMessage(`Internal error occurred in ${ep.name}: ${err.message}`, { + user: { + id: userId, + }, extra: { ep: ep.name, ps: data, @@ -410,9 +412,13 @@ export class ApiCallService implements OnApplicationShutdown { // API invoking if (this.config.sentryForBackend) { - return await Sentry.startSpan({ name: 'API: ' + ep.name }, () => ep.exec(data, user, token, file, request.ip, request.headers).catch((err: Error) => this.#onExecError(ep, data, err))); + return await Sentry.startSpan({ + name: 'API: ' + ep.name, + }, () => ep.exec(data, user, token, file, request.ip, request.headers) + .catch((err: Error) => this.#onExecError(ep, data, err, user?.id))); } else { - return await ep.exec(data, user, token, file, request.ip, request.headers).catch((err: Error) => this.#onExecError(ep, data, err)); + return await ep.exec(data, user, token, file, request.ip, request.headers) + .catch((err: Error) => this.#onExecError(ep, data, err, user?.id)); } } From a697a7f97b401d1545a7f61694b2704b4d3ac9fc Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:38:34 +0900 Subject: [PATCH 011/246] enhance(backend): improve sentry integration --- .../src/queue/QueueProcessorService.ts | 63 ++++++++++++++++--- 1 file changed, 56 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index 4f333df791..fdeb6a9518 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -165,7 +165,14 @@ export class QueueProcessorService implements OnApplicationShutdown { this.systemQueueWorker .on('active', (job) => systemLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => systemLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => systemLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('failed', (job, err) => { + systemLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + if (config.sentryForBackend) { + Sentry.captureMessage(`Queue: System: ${job?.name ?? '?'}`, { + extra: { job, err }, + }); + } + }) .on('error', (err: Error) => systemLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => systemLogger.warn(`stalled id=${jobId}`)); } @@ -214,7 +221,14 @@ export class QueueProcessorService implements OnApplicationShutdown { this.dbQueueWorker .on('active', (job) => dbLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => dbLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => dbLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('failed', (job, err) => { + dbLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + if (config.sentryForBackend) { + Sentry.captureMessage(`Queue: DB: ${job?.name ?? '?'}`, { + extra: { job, err }, + }); + } + }) .on('error', (err: Error) => dbLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => dbLogger.warn(`stalled id=${jobId}`)); } @@ -246,7 +260,14 @@ export class QueueProcessorService implements OnApplicationShutdown { this.deliverQueueWorker .on('active', (job) => deliverLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) .on('completed', (job, result) => deliverLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('failed', (job, err) => deliverLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) + .on('failed', (job, err) => { + deliverLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + if (config.sentryForBackend) { + Sentry.captureMessage('Queue: Deliver', { + extra: { job, err }, + }); + } + }) .on('error', (err: Error) => deliverLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => deliverLogger.warn(`stalled id=${jobId}`)); } @@ -278,7 +299,14 @@ export class QueueProcessorService implements OnApplicationShutdown { this.inboxQueueWorker .on('active', (job) => inboxLogger.debug(`active ${getJobInfo(job, true)}`)) .on('completed', (job, result) => inboxLogger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) - .on('failed', (job, err) => inboxLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) })) + .on('failed', (job, err) => { + inboxLogger.error(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) }); + if (config.sentryForBackend) { + Sentry.captureMessage('Queue: Inbox', { + extra: { job, err }, + }); + } + }) .on('error', (err: Error) => inboxLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => inboxLogger.warn(`stalled id=${jobId}`)); } @@ -310,7 +338,14 @@ export class QueueProcessorService implements OnApplicationShutdown { this.webhookDeliverQueueWorker .on('active', (job) => webhookLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) .on('completed', (job, result) => webhookLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('failed', (job, err) => webhookLogger.warn(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`)) + .on('failed', (job, err) => { + webhookLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + if (config.sentryForBackend) { + Sentry.captureMessage('Queue: WebhookDeliver', { + extra: { job, err }, + }); + } + }) .on('error', (err: Error) => webhookLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => webhookLogger.warn(`stalled id=${jobId}`)); } @@ -349,7 +384,14 @@ export class QueueProcessorService implements OnApplicationShutdown { this.relationshipQueueWorker .on('active', (job) => relationshipLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => relationshipLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => relationshipLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('failed', (job, err) => { + relationshipLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + if (config.sentryForBackend) { + Sentry.captureMessage(`Queue: Relationship: ${job?.name ?? '?'}`, { + extra: { job, err }, + }); + } + }) .on('error', (err: Error) => relationshipLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => relationshipLogger.warn(`stalled id=${jobId}`)); } @@ -382,7 +424,14 @@ export class QueueProcessorService implements OnApplicationShutdown { this.objectStorageQueueWorker .on('active', (job) => objectStorageLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => objectStorageLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => objectStorageLogger.warn(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) })) + .on('failed', (job, err) => { + objectStorageLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + if (config.sentryForBackend) { + Sentry.captureMessage(`Queue: ObjectStorage: ${job?.name ?? '?'}`, { + extra: { job, err }, + }); + } + }) .on('error', (err: Error) => objectStorageLogger.error(`error ${err.stack}`, { e: renderError(err) })) .on('stalled', (jobId) => objectStorageLogger.warn(`stalled id=${jobId}`)); } From d55e638a231b380e733dc0ada3c3de410f918a93 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:40:11 +0900 Subject: [PATCH 012/246] lint fixes --- packages/backend/src/NestLogger.ts | 2 +- packages/backend/src/boot/entry.ts | 2 +- packages/backend/src/postgres.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/NestLogger.ts b/packages/backend/src/NestLogger.ts index 80f1f7a024..d0be19664f 100644 --- a/packages/backend/src/NestLogger.ts +++ b/packages/backend/src/NestLogger.ts @@ -7,7 +7,7 @@ import { LoggerService } from '@nestjs/common'; import Logger from '@/logger.js'; const logger = new Logger('core', 'cyan'); -const nestLogger = logger.createSubLogger('nest', 'green', false); +const nestLogger = logger.createSubLogger('nest', 'green'); export class NestLogger implements LoggerService { /** diff --git a/packages/backend/src/boot/entry.ts b/packages/backend/src/boot/entry.ts index 04c6ca9723..25375c3015 100644 --- a/packages/backend/src/boot/entry.ts +++ b/packages/backend/src/boot/entry.ts @@ -25,7 +25,7 @@ Error.stackTraceLimit = Infinity; EventEmitter.defaultMaxListeners = 128; const logger = new Logger('core', 'cyan'); -const clusterLogger = logger.createSubLogger('cluster', 'orange', false); +const clusterLogger = logger.createSubLogger('cluster', 'orange'); const ev = new Xev(); //#region Events diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index 2d14537bbb..aa2aa5e373 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -85,7 +85,7 @@ import { bindThis } from '@/decorators.js'; export const dbLogger = new MisskeyLogger('db'); -const sqlLogger = dbLogger.createSubLogger('sql', 'gray', false); +const sqlLogger = dbLogger.createSubLogger('sql', 'gray'); class MyCustomLogger implements Logger { @bindThis From 8f833d742fdb10f088479c78ad489461773a8b81 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 6 Jun 2024 11:51:31 +0900 Subject: [PATCH 013/246] enhance(backend): improve sentry integration --- .../backend/src/queue/QueueProcessorService.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index fdeb6a9518..6a87be021e 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -165,10 +165,10 @@ export class QueueProcessorService implements OnApplicationShutdown { this.systemQueueWorker .on('active', (job) => systemLogger.debug(`active id=${job.id}`)) .on('completed', (job, result) => systemLogger.debug(`completed(${result}) id=${job.id}`)) - .on('failed', (job, err) => { + .on('failed', (job, err: Error) => { systemLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: System: ${job?.name ?? '?'}`, { + Sentry.captureMessage(`Queue: System: ${job?.name ?? '?'}: ${err.message}`, { extra: { job, err }, }); } @@ -224,7 +224,7 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('failed', (job, err) => { dbLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: DB: ${job?.name ?? '?'}`, { + Sentry.captureMessage(`Queue: DB: ${job?.name ?? '?'}: ${err.message}`, { extra: { job, err }, }); } @@ -263,7 +263,7 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('failed', (job, err) => { deliverLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { - Sentry.captureMessage('Queue: Deliver', { + Sentry.captureMessage(`Queue: Deliver: ${err.message}`, { extra: { job, err }, }); } @@ -302,7 +302,7 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('failed', (job, err) => { inboxLogger.error(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage('Queue: Inbox', { + Sentry.captureMessage(`Queue: Inbox: ${err.message}`, { extra: { job, err }, }); } @@ -341,7 +341,7 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('failed', (job, err) => { webhookLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { - Sentry.captureMessage('Queue: WebhookDeliver', { + Sentry.captureMessage(`Queue: WebhookDeliver: ${err.message}`, { extra: { job, err }, }); } @@ -387,7 +387,7 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('failed', (job, err) => { relationshipLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: Relationship: ${job?.name ?? '?'}`, { + Sentry.captureMessage(`Queue: Relationship: ${job?.name ?? '?'}: ${err.message}`, { extra: { job, err }, }); } @@ -427,7 +427,7 @@ export class QueueProcessorService implements OnApplicationShutdown { .on('failed', (job, err) => { objectStorageLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: ObjectStorage: ${job?.name ?? '?'}`, { + Sentry.captureMessage(`Queue: ObjectStorage: ${job?.name ?? '?'}: ${err.message}`, { extra: { job, err }, }); } From 00157864e95f4fae0c8aacff16ddac7f322ad68c Mon Sep 17 00:00:00 2001 From: taichan <40626578+tai-cha@users.noreply.github.com> Date: Fri, 7 Jun 2024 09:00:01 +0900 Subject: [PATCH 014/246] =?UTF-8?q?fix(backend):=20=E3=83=81=E3=83=A3?= =?UTF-8?q?=E3=83=BC=E3=83=88=E7=94=9F=E6=88=90=E6=99=82=E3=81=ABinstance.?= =?UTF-8?q?isSuspended=E3=81=8C=E8=AA=AD=E3=81=BE=E3=82=8C=E3=81=A6?= =?UTF-8?q?=E3=81=97=E3=81=BE=E3=81=86=E5=95=8F=E9=A1=8C=E3=81=AE=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20(#13951)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(backend): use sustensionState instead of isSuspended * Update CHANGELOG.md --- CHANGELOG.md | 2 +- packages/backend/src/core/chart/charts/federation.ts | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d4ef23d27..3cccb451d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - ### Server -- +- チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 ## 2024.5.0 diff --git a/packages/backend/src/core/chart/charts/federation.ts b/packages/backend/src/core/chart/charts/federation.ts index 5e4555ee96..c2329a2f73 100644 --- a/packages/backend/src/core/chart/charts/federation.ts +++ b/packages/backend/src/core/chart/charts/federation.ts @@ -47,7 +47,7 @@ export default class FederationChart extends Chart { // eslint-di const suspendedInstancesQuery = this.instancesRepository.createQueryBuilder('instance') .select('instance.host') - .where('instance.isSuspended = true'); + .where('instance.suspensionState != \'none\''); const pubsubSubQuery = this.followingsRepository.createQueryBuilder('f') .select('f.followerHost') @@ -89,7 +89,7 @@ export default class FederationChart extends Chart { // eslint-di .select('COUNT(instance.id)') .where(`instance.host IN (${ subInstancesQuery.getQuery() })`) .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) - .andWhere('instance.isSuspended = false') + .andWhere('instance.suspensionState = \'none\'') .andWhere('instance.isNotResponding = false') .getRawOne() .then(x => parseInt(x.count, 10)), @@ -97,7 +97,7 @@ export default class FederationChart extends Chart { // eslint-di .select('COUNT(instance.id)') .where(`instance.host IN (${ pubInstancesQuery.getQuery() })`) .andWhere(meta.blockedHosts.length === 0 ? '1=1' : 'instance.host NOT ILIKE ANY(ARRAY[:...blocked])', { blocked: meta.blockedHosts.flatMap(x => [x, `%.${x}`]) }) - .andWhere('instance.isSuspended = false') + .andWhere('instance.suspensionState = \'none\'') .andWhere('instance.isNotResponding = false') .getRawOne() .then(x => parseInt(x.count, 10)), From 859271613958cc4a9bc8fcd9616c3146c07a50a4 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 7 Jun 2024 13:15:37 +0900 Subject: [PATCH 015/246] enhance(backend): improve sentry integration --- packages/backend/src/queue/QueueProcessorService.ts | 7 +++++++ packages/backend/src/server/api/ApiCallService.ts | 1 + 2 files changed, 8 insertions(+) diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index 6a87be021e..7bfe1f4caa 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -169,6 +169,7 @@ export class QueueProcessorService implements OnApplicationShutdown { systemLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: System: ${job?.name ?? '?'}: ${err.message}`, { + level: 'error', extra: { job, err }, }); } @@ -225,6 +226,7 @@ export class QueueProcessorService implements OnApplicationShutdown { dbLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: DB: ${job?.name ?? '?'}: ${err.message}`, { + level: 'error', extra: { job, err }, }); } @@ -264,6 +266,7 @@ export class QueueProcessorService implements OnApplicationShutdown { deliverLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Deliver: ${err.message}`, { + level: 'error', extra: { job, err }, }); } @@ -303,6 +306,7 @@ export class QueueProcessorService implements OnApplicationShutdown { inboxLogger.error(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Inbox: ${err.message}`, { + level: 'error', extra: { job, err }, }); } @@ -342,6 +346,7 @@ export class QueueProcessorService implements OnApplicationShutdown { webhookLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: WebhookDeliver: ${err.message}`, { + level: 'error', extra: { job, err }, }); } @@ -388,6 +393,7 @@ export class QueueProcessorService implements OnApplicationShutdown { relationshipLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Relationship: ${job?.name ?? '?'}: ${err.message}`, { + level: 'error', extra: { job, err }, }); } @@ -428,6 +434,7 @@ export class QueueProcessorService implements OnApplicationShutdown { objectStorageLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: ObjectStorage: ${job?.name ?? '?'}: ${err.message}`, { + level: 'error', extra: { job, err }, }); } diff --git a/packages/backend/src/server/api/ApiCallService.ts b/packages/backend/src/server/api/ApiCallService.ts index e21a5e90ab..166f9c8675 100644 --- a/packages/backend/src/server/api/ApiCallService.ts +++ b/packages/backend/src/server/api/ApiCallService.ts @@ -111,6 +111,7 @@ export class ApiCallService implements OnApplicationShutdown { if (this.config.sentryForBackend) { Sentry.captureMessage(`Internal error occurred in ${ep.name}: ${err.message}`, { + level: 'error', user: { id: userId, }, From e0cf5b24022e22179355cf9439d3cfea6036daba Mon Sep 17 00:00:00 2001 From: Porlam Nicla <84321396+GrapeApple0@users.noreply.github.com> Date: Fri, 7 Jun 2024 14:46:46 +0900 Subject: [PATCH 016/246] =?UTF-8?q?=E9=85=8D=E4=BF=A1=E5=81=9C=E6=AD=A2?= =?UTF-8?q?=E3=81=97=E3=81=9F=E3=82=A4=E3=83=B3=E3=82=B9=E3=82=BF=E3=83=B3?= =?UTF-8?q?=E3=82=B9=E4=B8=80=E8=A6=A7=E3=81=8C=E8=A6=8B=E3=82=8C=E3=81=AA?= =?UTF-8?q?=E3=81=8F=E3=81=AA=E3=82=8B=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20(#13945)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 配信停止したインスタンス一覧が見れなくなる問題を修正 * Update CHANGELOG.md --- CHANGELOG.md | 2 +- .../backend/src/server/api/endpoints/federation/instances.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3cccb451d5..f93811c606 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ## Unreleased ### General -- +- Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正 ### Client - diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 4ef4315fb3..36f4bf5aa6 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -117,9 +117,9 @@ export default class extends Endpoint { // eslint- if (typeof ps.suspended === 'boolean') { if (ps.suspended) { - query.andWhere('instance.isSuspended = TRUE'); + query.andWhere('instance.suspensionState != \'none\''); } else { - query.andWhere('instance.isSuspended = FALSE'); + query.andWhere('instance.suspensionState = \'none\''); } } From 61fae45390283aee7ac582aa5303aae863de0f7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8A=E3=81=95=E3=82=80=E3=81=AE=E3=81=B2=E3=81=A8?= <46447427+samunohito@users.noreply.github.com> Date: Sat, 8 Jun 2024 15:34:19 +0900 Subject: [PATCH 017/246] =?UTF-8?q?feat:=20=E9=80=9A=E5=A0=B1=E3=82=92?= =?UTF-8?q?=E5=8F=97=E3=81=91=E3=81=9F=E9=9A=9B=E3=81=AB=E3=83=A1=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E3=81=BE=E3=81=9F=E3=81=AFWebhook=E3=81=A7=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E3=82=92=E9=80=81=E5=87=BA=E5=87=BA=E6=9D=A5=E3=82=8B?= =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=E3=81=99=E3=82=8B=20(#13758)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: 通報を受けた際にメールまたはWebhookで通知を送出出来るようにする * モデログに対応&エンドポイントを単一オブジェクトでのサポートに変更(API経由で大量に作るシチュエーションもないと思うので) * fix spdx * fix migration * fix migration * fix models * add e2e webhook * tweak * fix modlog * fix bugs * add tests and fix bugs * add tests and fix bugs * add tests * fix path * regenerate locale * 混入除去 * 混入除去 * add abuseReportResolved * fix pnpm-lock.yaml * add abuseReportResolved test * fix bugs * fix ui * add tests * fix CHANGELOG.md * add tests * add RoleService.getModeratorIds tests * WebhookServiceをUserとSystemに分割 * fix CHANGELOG.md * fix test * insertOneを使う用に * fix * regenerate locales * revert version * separate webhook job queue * fix * :art: * Update QueueProcessorService.ts --------- Co-authored-by: osamu <46447427+sam-osamu@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 1 + locales/index.d.ts | 94 +++ locales/ja-JP.yml | 27 + ...1713656541000-abuse-report-notification.js | 62 ++ .../core/AbuseReportNotificationService.ts | 406 ++++++++++ .../backend/src/core/AbuseReportService.ts | 128 ++++ packages/backend/src/core/CoreModule.ts | 44 +- packages/backend/src/core/EmailService.ts | 2 + .../backend/src/core/GlobalEventService.ts | 4 + .../backend/src/core/NoteCreateService.ts | 12 +- packages/backend/src/core/QueueModule.ts | 38 +- packages/backend/src/core/QueueService.ts | 63 +- packages/backend/src/core/RoleService.ts | 30 +- .../backend/src/core/SystemWebhookService.ts | 233 ++++++ .../backend/src/core/UserBlockingService.ts | 6 +- .../backend/src/core/UserFollowingService.ts | 12 +- .../backend/src/core/UserWebhookService.ts | 99 +++ packages/backend/src/core/WebhookService.ts | 97 --- .../src/core/activitypub/ApInboxService.ts | 10 +- ...eportNotificationRecipientEntityService.ts | 88 +++ .../entities/SystemWebhookEntityService.ts | 74 ++ packages/backend/src/di-symbols.ts | 2 + packages/backend/src/misc/json-schema.ts | 28 +- .../AbuseReportNotificationRecipient.ts | 100 +++ .../backend/src/models/RepositoryModule.ts | 98 ++- packages/backend/src/models/SystemWebhook.ts | 98 +++ packages/backend/src/models/_.ts | 6 + .../abuse-report-notification-recipient.ts | 50 ++ .../src/models/json-schema/system-webhook.ts | 54 ++ packages/backend/src/postgres.ts | 8 +- .../backend/src/queue/QueueProcessorModule.ts | 6 +- .../src/queue/QueueProcessorService.ts | 153 ++-- packages/backend/src/queue/const.ts | 3 +- .../SystemWebhookDeliverProcessorService.ts | 87 +++ ... => UserWebhookDeliverProcessorService.ts} | 6 +- packages/backend/src/queue/types.ts | 12 +- .../backend/src/server/api/EndpointsModule.ts | 42 +- packages/backend/src/server/api/endpoints.ts | 38 +- .../notification-recipient/create.ts | 122 +++ .../notification-recipient/delete.ts | 44 ++ .../notification-recipient/list.ts | 55 ++ .../notification-recipient/show.ts | 64 ++ .../notification-recipient/update.ts | 128 ++++ .../server/api/endpoints/admin/queue/stats.ts | 5 +- .../admin/resolve-abuse-user-report.ts | 53 +- .../endpoints/admin/system-webhook/create.ts | 85 +++ .../endpoints/admin/system-webhook/delete.ts | 44 ++ .../endpoints/admin/system-webhook/list.ts | 60 ++ .../endpoints/admin/system-webhook/show.ts | 62 ++ .../endpoints/admin/system-webhook/update.ts | 91 +++ .../api/endpoints/users/report-abuse.ts | 54 +- .../src/server/web/ClientServerService.ts | 17 +- packages/backend/src/types.ts | 32 + .../backend/test/e2e/synalio/abuse-report.ts | 401 ++++++++++ .../unit/AbuseReportNotificationService.ts | 343 +++++++++ packages/backend/test/unit/RoleService.ts | 132 +++- .../backend/test/unit/SystemWebhookService.ts | 515 +++++++++++++ packages/frontend/src/components/MkButton.vue | 2 + .../frontend/src/components/MkDivider.vue | 32 + packages/frontend/src/components/MkSwitch.vue | 5 +- .../components/MkSystemWebhookEditor.impl.ts | 45 ++ .../src/components/MkSystemWebhookEditor.vue | 217 ++++++ .../notification-recipient.editor.vue | 307 ++++++++ .../notification-recipient.item.vue | 114 +++ .../abuse-report/notification-recipient.vue | 176 +++++ packages/frontend/src/pages/admin/abuses.vue | 85 ++- packages/frontend/src/pages/admin/index.vue | 5 + .../src/pages/admin/modlog.ModLog.vue | 48 +- .../src/pages/admin/system-webhook.item.vue | 117 +++ .../src/pages/admin/system-webhook.vue | 96 +++ packages/frontend/src/router/definition.ts | 8 + packages/misskey-js/etc/misskey-js.api.md | 105 ++- .../misskey-js/src/autogen/apiClientJSDoc.ts | 120 +++ packages/misskey-js/src/autogen/endpoint.ts | 28 + packages/misskey-js/src/autogen/entities.ts | 18 + packages/misskey-js/src/autogen/models.ts | 2 + packages/misskey-js/src/autogen/types.ts | 693 ++++++++++++++++++ packages/misskey-js/src/consts.ts | 26 + packages/misskey-js/src/entities.ts | 19 +- 79 files changed, 6527 insertions(+), 369 deletions(-) create mode 100644 packages/backend/migration/1713656541000-abuse-report-notification.js create mode 100644 packages/backend/src/core/AbuseReportNotificationService.ts create mode 100644 packages/backend/src/core/AbuseReportService.ts create mode 100644 packages/backend/src/core/SystemWebhookService.ts create mode 100644 packages/backend/src/core/UserWebhookService.ts delete mode 100644 packages/backend/src/core/WebhookService.ts create mode 100644 packages/backend/src/core/entities/AbuseReportNotificationRecipientEntityService.ts create mode 100644 packages/backend/src/core/entities/SystemWebhookEntityService.ts create mode 100644 packages/backend/src/models/AbuseReportNotificationRecipient.ts create mode 100644 packages/backend/src/models/SystemWebhook.ts create mode 100644 packages/backend/src/models/json-schema/abuse-report-notification-recipient.ts create mode 100644 packages/backend/src/models/json-schema/system-webhook.ts create mode 100644 packages/backend/src/queue/processors/SystemWebhookDeliverProcessorService.ts rename packages/backend/src/queue/processors/{WebhookDeliverProcessorService.ts => UserWebhookDeliverProcessorService.ts} (92%) create mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts create mode 100644 packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts create mode 100644 packages/backend/test/e2e/synalio/abuse-report.ts create mode 100644 packages/backend/test/unit/AbuseReportNotificationService.ts create mode 100644 packages/backend/test/unit/SystemWebhookService.ts create mode 100644 packages/frontend/src/components/MkDivider.vue create mode 100644 packages/frontend/src/components/MkSystemWebhookEditor.impl.ts create mode 100644 packages/frontend/src/components/MkSystemWebhookEditor.vue create mode 100644 packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue create mode 100644 packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue create mode 100644 packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue create mode 100644 packages/frontend/src/pages/admin/system-webhook.item.vue create mode 100644 packages/frontend/src/pages/admin/system-webhook.vue diff --git a/CHANGELOG.md b/CHANGELOG.md index f93811c606..8b70636d82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## Unreleased ### General +- Feat: 通報を受けた際、または解決した際に、予め登録した宛先に通知を飛ばせるように(mail or webhook) #13705 - Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正 ### Client diff --git a/locales/index.d.ts b/locales/index.d.ts index 0b1b86d373..acdc1fc421 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -9305,6 +9305,10 @@ export interface Locale extends ILocale { * Webhookを作成 */ "createWebhook": string; + /** + * Webhookを編集 + */ + "modifyWebhook": string; /** * 名前 */ @@ -9351,6 +9355,72 @@ export interface Locale extends ILocale { */ "mention": string; }; + "_systemEvents": { + /** + * ユーザーから通報があったとき + */ + "abuseReport": string; + /** + * ユーザーからの通報を処理したとき + */ + "abuseReportResolved": string; + }; + /** + * Webhookを削除しますか? + */ + "deleteConfirm": string; + }; + "_abuseReport": { + "_notificationRecipient": { + /** + * 通報の通知先を追加 + */ + "createRecipient": string; + /** + * 通報の通知先を編集 + */ + "modifyRecipient": string; + /** + * 通知先の種類 + */ + "recipientType": string; + "_recipientType": { + /** + * メール + */ + "mail": string; + /** + * Webhook + */ + "webhook": string; + "_captions": { + /** + * モデレーター権限を持つユーザーのメールアドレスに通知を送ります(通報を受けた時のみ) + */ + "mail": string; + /** + * 指定したSystemWebhookに通知を送ります(通報を受けた時と通報を解決した時にそれぞれ発信) + */ + "webhook": string; + }; + }; + /** + * キーワード + */ + "keywords": string; + /** + * 通知先ユーザー + */ + "notifiedUser": string; + /** + * 使用するWebhook + */ + "notifiedWebhook": string; + /** + * 通知先を削除しますか? + */ + "deleteConfirm": string; + }; }; "_moderationLogTypes": { /** @@ -9497,6 +9567,30 @@ export interface Locale extends ILocale { * ユーザーのバナーを解除 */ "unsetUserBanner": string; + /** + * SystemWebhookを作成 + */ + "createSystemWebhook": string; + /** + * SystemWebhookを更新 + */ + "updateSystemWebhook": string; + /** + * SystemWebhookを削除 + */ + "deleteSystemWebhook": string; + /** + * 通報の通知先を作成 + */ + "createAbuseReportNotificationRecipient": string; + /** + * 通報の通知先を更新 + */ + "updateAbuseReportNotificationRecipient": string; + /** + * 通報の通知先を削除 + */ + "deleteAbuseReportNotificationRecipient": string; }; "_fileViewer": { /** diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index a89cfbd843..3ac1ce82a3 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2468,6 +2468,7 @@ _drivecleaner: _webhookSettings: createWebhook: "Webhookを作成" + modifyWebhook: "Webhookを編集" name: "名前" secret: "シークレット" events: "Webhookを実行するタイミング" @@ -2480,6 +2481,26 @@ _webhookSettings: renote: "Renoteされたとき" reaction: "リアクションがあったとき" mention: "メンションされたとき" + _systemEvents: + abuseReport: "ユーザーから通報があったとき" + abuseReportResolved: "ユーザーからの通報を処理したとき" + deleteConfirm: "Webhookを削除しますか?" + +_abuseReport: + _notificationRecipient: + createRecipient: "通報の通知先を追加" + modifyRecipient: "通報の通知先を編集" + recipientType: "通知先の種類" + _recipientType: + mail: "メール" + webhook: "Webhook" + _captions: + mail: "モデレーター権限を持つユーザーのメールアドレスに通知を送ります(通報を受けた時のみ)" + webhook: "指定したSystemWebhookに通知を送ります(通報を受けた時と通報を解決した時にそれぞれ発信)" + keywords: "キーワード" + notifiedUser: "通知先ユーザー" + notifiedWebhook: "使用するWebhook" + deleteConfirm: "通知先を削除しますか?" _moderationLogTypes: createRole: "ロールを作成" @@ -2518,6 +2539,12 @@ _moderationLogTypes: deleteAvatarDecoration: "アイコンデコレーションを削除" unsetUserAvatar: "ユーザーのアイコンを解除" unsetUserBanner: "ユーザーのバナーを解除" + createSystemWebhook: "SystemWebhookを作成" + updateSystemWebhook: "SystemWebhookを更新" + deleteSystemWebhook: "SystemWebhookを削除" + createAbuseReportNotificationRecipient: "通報の通知先を作成" + updateAbuseReportNotificationRecipient: "通報の通知先を更新" + deleteAbuseReportNotificationRecipient: "通報の通知先を削除" _fileViewer: title: "ファイルの詳細" diff --git a/packages/backend/migration/1713656541000-abuse-report-notification.js b/packages/backend/migration/1713656541000-abuse-report-notification.js new file mode 100644 index 0000000000..4a754f81e2 --- /dev/null +++ b/packages/backend/migration/1713656541000-abuse-report-notification.js @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export class AbuseReportNotification1713656541000 { + name = 'AbuseReportNotification1713656541000' + + async up(queryRunner) { + await queryRunner.query(` + CREATE TABLE "system_webhook" ( + "id" varchar(32) NOT NULL, + "isActive" boolean NOT NULL DEFAULT true, + "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "latestSentAt" timestamp with time zone NULL DEFAULT NULL, + "latestStatus" integer NULL DEFAULT NULL, + "name" varchar(255) NOT NULL, + "on" varchar(128) [] NOT NULL DEFAULT '{}'::character varying[], + "url" varchar(1024) NOT NULL, + "secret" varchar(1024) NOT NULL, + CONSTRAINT "PK_system_webhook_id" PRIMARY KEY ("id") + ); + CREATE INDEX "IDX_system_webhook_isActive" ON "system_webhook" ("isActive"); + CREATE INDEX "IDX_system_webhook_on" ON "system_webhook" USING gin ("on"); + + CREATE TABLE "abuse_report_notification_recipient" ( + "id" varchar(32) NOT NULL, + "isActive" boolean NOT NULL DEFAULT true, + "updatedAt" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "name" varchar(255) NOT NULL, + "method" varchar(64) NOT NULL, + "userId" varchar(32) NULL DEFAULT NULL, + "systemWebhookId" varchar(32) NULL DEFAULT NULL, + CONSTRAINT "PK_abuse_report_notification_recipient_id" PRIMARY KEY ("id"), + CONSTRAINT "FK_abuse_report_notification_recipient_userId1" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_abuse_report_notification_recipient_userId2" FOREIGN KEY ("userId") REFERENCES "user_profile"("userId") ON DELETE CASCADE ON UPDATE NO ACTION, + CONSTRAINT "FK_abuse_report_notification_recipient_systemWebhookId" FOREIGN KEY ("systemWebhookId") REFERENCES "system_webhook"("id") ON DELETE CASCADE ON UPDATE NO ACTION + ); + CREATE INDEX "IDX_abuse_report_notification_recipient_isActive" ON "abuse_report_notification_recipient" ("isActive"); + CREATE INDEX "IDX_abuse_report_notification_recipient_method" ON "abuse_report_notification_recipient" ("method"); + CREATE INDEX "IDX_abuse_report_notification_recipient_userId" ON "abuse_report_notification_recipient" ("userId"); + CREATE INDEX "IDX_abuse_report_notification_recipient_systemWebhookId" ON "abuse_report_notification_recipient" ("systemWebhookId"); + `); + } + + async down(queryRunner) { + await queryRunner.query(` + ALTER TABLE "abuse_report_notification_recipient" DROP CONSTRAINT "FK_abuse_report_notification_recipient_userId1"; + ALTER TABLE "abuse_report_notification_recipient" DROP CONSTRAINT "FK_abuse_report_notification_recipient_userId2"; + ALTER TABLE "abuse_report_notification_recipient" DROP CONSTRAINT "FK_abuse_report_notification_recipient_systemWebhookId"; + DROP INDEX "IDX_abuse_report_notification_recipient_isActive"; + DROP INDEX "IDX_abuse_report_notification_recipient_method"; + DROP INDEX "IDX_abuse_report_notification_recipient_userId"; + DROP INDEX "IDX_abuse_report_notification_recipient_systemWebhookId"; + DROP TABLE "abuse_report_notification_recipient"; + + DROP INDEX "IDX_system_webhook_isActive"; + DROP INDEX "IDX_system_webhook_on"; + DROP TABLE "system_webhook"; + `); + } +} diff --git a/packages/backend/src/core/AbuseReportNotificationService.ts b/packages/backend/src/core/AbuseReportNotificationService.ts new file mode 100644 index 0000000000..df752afcd8 --- /dev/null +++ b/packages/backend/src/core/AbuseReportNotificationService.ts @@ -0,0 +1,406 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable, type OnApplicationShutdown } from '@nestjs/common'; +import { Brackets, In, IsNull, Not } from 'typeorm'; +import * as Redis from 'ioredis'; +import sanitizeHtml from 'sanitize-html'; +import { DI } from '@/di-symbols.js'; +import { bindThis } from '@/decorators.js'; +import { GlobalEvents, GlobalEventService } from '@/core/GlobalEventService.js'; +import { isNotNull } from '@/misc/is-not-null.js'; +import type { + AbuseReportNotificationRecipientRepository, + MiAbuseReportNotificationRecipient, + MiAbuseUserReport, + MiUser, +} from '@/models/_.js'; +import { EmailService } from '@/core/EmailService.js'; +import { MetaService } from '@/core/MetaService.js'; +import { RoleService } from '@/core/RoleService.js'; +import { RecipientMethod } from '@/models/AbuseReportNotificationRecipient.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; +import { IdService } from './IdService.js'; + +@Injectable() +export class AbuseReportNotificationService implements OnApplicationShutdown { + constructor( + @Inject(DI.abuseReportNotificationRecipientRepository) + private abuseReportNotificationRecipientRepository: AbuseReportNotificationRecipientRepository, + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, + private idService: IdService, + private roleService: RoleService, + private systemWebhookService: SystemWebhookService, + private emailService: EmailService, + private metaService: MetaService, + private moderationLogService: ModerationLogService, + private globalEventService: GlobalEventService, + ) { + this.redisForSub.on('message', this.onMessage); + } + + /** + * 管理者用Redisイベントを用いて{@link abuseReports}の内容を管理者各位に通知する. + * 通知先ユーザは{@link RoleService.getModeratorIds}の取得結果に依る. + * + * @see RoleService.getModeratorIds + * @see GlobalEventService.publishAdminStream + */ + @bindThis + public async notifyAdminStream(abuseReports: MiAbuseUserReport[]) { + if (abuseReports.length <= 0) { + return; + } + + const moderatorIds = await this.roleService.getModeratorIds(true, true); + + for (const moderatorId of moderatorIds) { + for (const abuseReport of abuseReports) { + this.globalEventService.publishAdminStream( + moderatorId, + 'newAbuseUserReport', + { + id: abuseReport.id, + targetUserId: abuseReport.targetUserId, + reporterId: abuseReport.reporterId, + comment: abuseReport.comment, + }, + ); + } + } + } + + /** + * Mailを用いて{@link abuseReports}の内容を管理者各位に通知する. + * メールアドレスの送信先は以下の通り. + * - モデレータ権限所有者ユーザ(設定画面からメールアドレスの設定を行っているユーザに限る) + * - metaテーブルに設定されているメールアドレス + * + * @see EmailService.sendEmail + */ + @bindThis + public async notifyMail(abuseReports: MiAbuseUserReport[]) { + if (abuseReports.length <= 0) { + return; + } + + const recipientEMailAddresses = await this.fetchEMailRecipients().then(it => it + .filter(it => it.isActive && it.userProfile?.emailVerified) + .map(it => it.userProfile?.email) + .filter(isNotNull), + ); + + // 送信先の鮮度を保つため、毎回取得する + const meta = await this.metaService.fetch(true); + recipientEMailAddresses.push( + ...(meta.email ? [meta.email] : []), + ); + + if (recipientEMailAddresses.length <= 0) { + return; + } + + for (const mailAddress of recipientEMailAddresses) { + await Promise.all( + abuseReports.map(it => { + // TODO: 送信処理はJobQueue化したい + return this.emailService.sendEmail( + mailAddress, + 'New Abuse Report', + sanitizeHtml(it.comment), + sanitizeHtml(it.comment), + ); + }), + ); + } + } + + /** + * SystemWebhookを用いて{@link abuseReports}の内容を管理者各位に通知する. + * ここではJobQueueへのエンキューのみを行うため、即時実行されない. + * + * @see SystemWebhookService.enqueueSystemWebhook + */ + @bindThis + public async notifySystemWebhook( + abuseReports: MiAbuseUserReport[], + type: 'abuseReport' | 'abuseReportResolved', + ) { + if (abuseReports.length <= 0) { + return; + } + + const recipientWebhookIds = await this.fetchWebhookRecipients() + .then(it => it + .filter(it => it.isActive && it.systemWebhookId && it.method === 'webhook') + .map(it => it.systemWebhookId) + .filter(isNotNull)); + for (const webhookId of recipientWebhookIds) { + await Promise.all( + abuseReports.map(it => { + return this.systemWebhookService.enqueueSystemWebhook( + webhookId, + type, + it, + ); + }), + ); + } + } + + /** + * 通報の通知先一覧を取得する. + * + * @param {Object} [params] クエリの取得条件 + * @param {Object} [params.method] 取得する通知先の通知方法 + * @param {Object} [opts] 動作時の詳細なオプション + * @param {boolean} [opts.removeUnauthorized] 副作用としてモデレータ権限を持たない送信先ユーザをDBから削除するかどうか(default: true) + * @param {boolean} [opts.joinUser] 通知先のユーザ情報をJOINするかどうか(default: false) + * @param {boolean} [opts.joinSystemWebhook] 通知先のSystemWebhook情報をJOINするかどうか(default: false) + * @see removeUnauthorizedRecipientUsers + */ + @bindThis + public async fetchRecipients( + params?: { + ids?: MiAbuseReportNotificationRecipient['id'][], + method?: RecipientMethod[], + }, + opts?: { + removeUnauthorized?: boolean, + joinUser?: boolean, + joinSystemWebhook?: boolean, + }, + ): Promise { + const query = this.abuseReportNotificationRecipientRepository.createQueryBuilder('recipient'); + + if (opts?.joinUser) { + query.innerJoinAndSelect('user', 'user', 'recipient.userId = user.id'); + query.innerJoinAndSelect('recipient.userProfile', 'userProfile'); + } + + if (opts?.joinSystemWebhook) { + query.innerJoinAndSelect('recipient.systemWebhook', 'systemWebhook'); + } + + if (params?.ids) { + query.andWhere({ id: In(params.ids) }); + } + + if (params?.method) { + query.andWhere(new Brackets(qb => { + if (params.method?.includes('email')) { + qb.orWhere({ method: 'email', userId: Not(IsNull()) }); + } + if (params.method?.includes('webhook')) { + qb.orWhere({ method: 'webhook', userId: IsNull() }); + } + })); + } + + const recipients = await query.getMany(); + if (recipients.length <= 0) { + return []; + } + + // アサイン有効期限切れはイベントで拾えないので、このタイミングでチェック及び削除(オプション) + return (opts?.removeUnauthorized ?? true) + ? await this.removeUnauthorizedRecipientUsers(recipients) + : recipients; + } + + /** + * EMailの通知先一覧を取得する. + * リレーション先の{@link MiUser}および{@link MiUserProfile}も同時に取得する. + * + * @param {Object} [opts] + * @param {boolean} [opts.removeUnauthorized] 副作用としてモデレータ権限を持たない送信先ユーザをDBから削除するかどうか(default: true) + * @see removeUnauthorizedRecipientUsers + */ + @bindThis + public async fetchEMailRecipients(opts?: { + removeUnauthorized?: boolean + }): Promise { + return this.fetchRecipients({ method: ['email'] }, { joinUser: true, ...opts }); + } + + /** + * Webhookの通知先一覧を取得する. + * リレーション先の{@link MiSystemWebhook}も同時に取得する. + */ + @bindThis + public fetchWebhookRecipients(): Promise { + return this.fetchRecipients({ method: ['webhook'] }, { joinSystemWebhook: true }); + } + + /** + * 通知先を作成する. + */ + @bindThis + public async createRecipient( + params: { + isActive: MiAbuseReportNotificationRecipient['isActive']; + name: MiAbuseReportNotificationRecipient['name']; + method: MiAbuseReportNotificationRecipient['method']; + userId: MiAbuseReportNotificationRecipient['userId']; + systemWebhookId: MiAbuseReportNotificationRecipient['systemWebhookId']; + }, + updater: MiUser, + ): Promise { + const id = this.idService.gen(); + await this.abuseReportNotificationRecipientRepository.insert({ + ...params, + id, + }); + + const created = await this.abuseReportNotificationRecipientRepository.findOneByOrFail({ id: id }); + + this.moderationLogService + .log(updater, 'createAbuseReportNotificationRecipient', { + recipientId: id, + recipient: created, + }) + .then(); + + return created; + } + + /** + * 通知先を更新する. + */ + @bindThis + public async updateRecipient( + params: { + id: MiAbuseReportNotificationRecipient['id']; + isActive: MiAbuseReportNotificationRecipient['isActive']; + name: MiAbuseReportNotificationRecipient['name']; + method: MiAbuseReportNotificationRecipient['method']; + userId: MiAbuseReportNotificationRecipient['userId']; + systemWebhookId: MiAbuseReportNotificationRecipient['systemWebhookId']; + }, + updater: MiUser, + ): Promise { + const beforeEntity = await this.abuseReportNotificationRecipientRepository.findOneByOrFail({ id: params.id }); + + await this.abuseReportNotificationRecipientRepository.update(params.id, { + isActive: params.isActive, + updatedAt: new Date(), + name: params.name, + method: params.method, + userId: params.userId, + systemWebhookId: params.systemWebhookId, + }); + + const afterEntity = await this.abuseReportNotificationRecipientRepository.findOneByOrFail({ id: params.id }); + + this.moderationLogService + .log(updater, 'updateAbuseReportNotificationRecipient', { + recipientId: params.id, + before: beforeEntity, + after: afterEntity, + }) + .then(); + + return afterEntity; + } + + /** + * 通知先を削除する. + */ + @bindThis + public async deleteRecipient( + id: MiAbuseReportNotificationRecipient['id'], + updater: MiUser, + ) { + const entity = await this.abuseReportNotificationRecipientRepository.findBy({ id }); + + await this.abuseReportNotificationRecipientRepository.delete(id); + + this.moderationLogService + .log(updater, 'deleteAbuseReportNotificationRecipient', { + recipientId: id, + recipient: entity, + }) + .then(); + } + + /** + * モデレータ権限を持たない(*1)通知先ユーザを削除する. + * + * *1: 以下の両方を満たすものの事を言う + * - 通知先にユーザIDが設定されている + * - 付与ロールにモデレータ権限がない or アサインの有効期限が切れている + * + * @param recipients 通知先一覧の配列 + * @returns {@lisk recipients}からモデレータ権限を持たない通知先を削除した配列 + */ + @bindThis + private async removeUnauthorizedRecipientUsers(recipients: MiAbuseReportNotificationRecipient[]): Promise { + const userRecipients = recipients.filter(it => it.userId !== null); + const recipientUserIds = new Set(userRecipients.map(it => it.userId).filter(isNotNull)); + if (recipientUserIds.size <= 0) { + // ユーザが通知先として設定されていない場合、この関数での処理を行うべきレコードが無い + return recipients; + } + + // モデレータ権限の有無で通知先設定を振り分ける + const authorizedUserIds = await this.roleService.getModeratorIds(true, true); + const authorizedUserRecipients = Array.of(); + const unauthorizedUserRecipients = Array.of(); + for (const recipient of userRecipients) { + // eslint-disable-next-line + if (authorizedUserIds.includes(recipient.userId!)) { + authorizedUserRecipients.push(recipient); + } else { + unauthorizedUserRecipients.push(recipient); + } + } + + // モデレータ権限を持たない通知先をDBから削除する + if (unauthorizedUserRecipients.length > 0) { + await this.abuseReportNotificationRecipientRepository.delete(unauthorizedUserRecipients.map(it => it.id)); + } + const nonUserRecipients = recipients.filter(it => it.userId === null); + return [...nonUserRecipients, ...authorizedUserRecipients].sort((a, b) => a.id.localeCompare(b.id)); + } + + @bindThis + private async onMessage(_: string, data: string): Promise { + const obj = JSON.parse(data); + if (obj.channel !== 'internal') { + return; + } + + const { type } = obj.message as GlobalEvents['internal']['payload']; + switch (type) { + case 'roleUpdated': + case 'roleDeleted': + case 'userRoleUnassigned': { + // 場合によってはキャッシュ更新よりも先にここが呼ばれてしまう可能性があるのでnextTickで遅延実行 + process.nextTick(async () => { + const recipients = await this.abuseReportNotificationRecipientRepository.findBy({ + userId: Not(IsNull()), + }); + await this.removeUnauthorizedRecipientUsers(recipients); + }); + break; + } + default: { + break; + } + } + } + + @bindThis + public dispose(): void { + this.redisForSub.off('message', this.onMessage); + } + + @bindThis + public onApplicationShutdown(signal?: string | undefined): void { + this.dispose(); + } +} diff --git a/packages/backend/src/core/AbuseReportService.ts b/packages/backend/src/core/AbuseReportService.ts new file mode 100644 index 0000000000..69c51509ba --- /dev/null +++ b/packages/backend/src/core/AbuseReportService.ts @@ -0,0 +1,128 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { In } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import { bindThis } from '@/decorators.js'; +import type { AbuseUserReportsRepository, MiAbuseUserReport, MiUser, UsersRepository } from '@/models/_.js'; +import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; +import { QueueService } from '@/core/QueueService.js'; +import { InstanceActorService } from '@/core/InstanceActorService.js'; +import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { IdService } from './IdService.js'; + +@Injectable() +export class AbuseReportService { + constructor( + @Inject(DI.abuseUserReportsRepository) + private abuseUserReportsRepository: AbuseUserReportsRepository, + @Inject(DI.usersRepository) + private usersRepository: UsersRepository, + private idService: IdService, + private abuseReportNotificationService: AbuseReportNotificationService, + private queueService: QueueService, + private instanceActorService: InstanceActorService, + private apRendererService: ApRendererService, + private moderationLogService: ModerationLogService, + ) { + } + + /** + * ユーザからの通報をDBに記録し、その内容を下記の手段で管理者各位に通知する. + * - 管理者用Redisイベント + * - EMail(モデレータ権限所有者ユーザ+metaテーブルに設定されているメールアドレス) + * - SystemWebhook + * + * @param params 通報内容. もし複数件の通報に対応した時のために、あらかじめ複数件を処理できる前提で考える + * @see AbuseReportNotificationService.notify + */ + @bindThis + public async report(params: { + targetUserId: MiAbuseUserReport['targetUserId'], + targetUserHost: MiAbuseUserReport['targetUserHost'], + reporterId: MiAbuseUserReport['reporterId'], + reporterHost: MiAbuseUserReport['reporterHost'], + comment: string, + }[]) { + const entities = params.map(param => { + return { + id: this.idService.gen(), + targetUserId: param.targetUserId, + targetUserHost: param.targetUserHost, + reporterId: param.reporterId, + reporterHost: param.reporterHost, + comment: param.comment, + }; + }); + + const reports = Array.of(); + for (const entity of entities) { + const report = await this.abuseUserReportsRepository.insertOne(entity); + reports.push(report); + } + + return Promise.all([ + this.abuseReportNotificationService.notifyAdminStream(reports), + this.abuseReportNotificationService.notifySystemWebhook(reports, 'abuseReport'), + this.abuseReportNotificationService.notifyMail(reports), + ]); + } + + /** + * 通報を解決し、その内容を下記の手段で管理者各位に通知する. + * - SystemWebhook + * + * @param params 通報内容. もし複数件の通報に対応した時のために、あらかじめ複数件を処理できる前提で考える + * @param operator 通報を処理したユーザ + * @see AbuseReportNotificationService.notify + */ + @bindThis + public async resolve( + params: { + reportId: string; + forward: boolean; + }[], + operator: MiUser, + ) { + const paramsMap = new Map(params.map(it => [it.reportId, it])); + const reports = await this.abuseUserReportsRepository.findBy({ + id: In(params.map(it => it.reportId)), + }); + + for (const report of reports) { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const ps = paramsMap.get(report.id)!; + + await this.abuseUserReportsRepository.update(report.id, { + resolved: true, + assigneeId: operator.id, + forwarded: ps.forward && report.targetUserHost !== null, + }); + + if (ps.forward && report.targetUserHost != null) { + const actor = await this.instanceActorService.getInstanceActor(); + const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); + + // eslint-disable-next-line + const flag = this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment); + const contextAssignedFlag = this.apRendererService.addContext(flag); + this.queueService.deliver(actor, contextAssignedFlag, targetUser.inbox, false); + } + + this.moderationLogService + .log(operator, 'resolveAbuseReport', { + reportId: report.id, + report: report, + forwarded: ps.forward && report.targetUserHost !== null, + }) + .then(); + } + + return this.abuseUserReportsRepository.findBy({ id: In(reports.map(it => it.id)) }) + .then(reports => this.abuseReportNotificationService.notifySystemWebhook(reports, 'abuseReportResolved')); + } +} diff --git a/packages/backend/src/core/CoreModule.ts b/packages/backend/src/core/CoreModule.ts index be80df6f1c..b5b34487ec 100644 --- a/packages/backend/src/core/CoreModule.ts +++ b/packages/backend/src/core/CoreModule.ts @@ -5,6 +5,13 @@ import { Module } from '@nestjs/common'; import { FanoutTimelineEndpointService } from '@/core/FanoutTimelineEndpointService.js'; +import { AbuseReportService } from '@/core/AbuseReportService.js'; +import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; +import { + AbuseReportNotificationRecipientEntityService, +} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; +import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; import { AccountMoveService } from './AccountMoveService.js'; import { AccountUpdateService } from './AccountUpdateService.js'; import { AiService } from './AiService.js'; @@ -56,7 +63,7 @@ import { UserMutingService } from './UserMutingService.js'; import { UserSuspendService } from './UserSuspendService.js'; import { UserAuthService } from './UserAuthService.js'; import { VideoProcessingService } from './VideoProcessingService.js'; -import { WebhookService } from './WebhookService.js'; +import { UserWebhookService } from './UserWebhookService.js'; import { ProxyAccountService } from './ProxyAccountService.js'; import { UtilityService } from './UtilityService.js'; import { FileInfoService } from './FileInfoService.js'; @@ -144,6 +151,8 @@ import type { Provider } from '@nestjs/common'; //#region 文字列ベースでのinjection用(循環参照対応のため) const $LoggerService: Provider = { provide: 'LoggerService', useExisting: LoggerService }; +const $AbuseReportService: Provider = { provide: 'AbuseReportService', useExisting: AbuseReportService }; +const $AbuseReportNotificationService: Provider = { provide: 'AbuseReportNotificationService', useExisting: AbuseReportNotificationService }; const $AccountMoveService: Provider = { provide: 'AccountMoveService', useExisting: AccountMoveService }; const $AccountUpdateService: Provider = { provide: 'AccountUpdateService', useExisting: AccountUpdateService }; const $AiService: Provider = { provide: 'AiService', useExisting: AiService }; @@ -196,7 +205,8 @@ const $UserMutingService: Provider = { provide: 'UserMutingService', useExisting const $UserSuspendService: Provider = { provide: 'UserSuspendService', useExisting: UserSuspendService }; const $UserAuthService: Provider = { provide: 'UserAuthService', useExisting: UserAuthService }; const $VideoProcessingService: Provider = { provide: 'VideoProcessingService', useExisting: VideoProcessingService }; -const $WebhookService: Provider = { provide: 'WebhookService', useExisting: WebhookService }; +const $UserWebhookService: Provider = { provide: 'UserWebhookService', useExisting: UserWebhookService }; +const $SystemWebhookService: Provider = { provide: 'SystemWebhookService', useExisting: SystemWebhookService }; const $UtilityService: Provider = { provide: 'UtilityService', useExisting: UtilityService }; const $FileInfoService: Provider = { provide: 'FileInfoService', useExisting: FileInfoService }; const $SearchService: Provider = { provide: 'SearchService', useExisting: SearchService }; @@ -225,6 +235,7 @@ const $ChartManagementService: Provider = { provide: 'ChartManagementService', u const $AbuseUserReportEntityService: Provider = { provide: 'AbuseUserReportEntityService', useExisting: AbuseUserReportEntityService }; const $AnnouncementEntityService: Provider = { provide: 'AnnouncementEntityService', useExisting: AnnouncementEntityService }; +const $AbuseReportNotificationRecipientEntityService: Provider = { provide: 'AbuseReportNotificationRecipientEntityService', useExisting: AbuseReportNotificationRecipientEntityService }; const $AntennaEntityService: Provider = { provide: 'AntennaEntityService', useExisting: AntennaEntityService }; const $AppEntityService: Provider = { provide: 'AppEntityService', useExisting: AppEntityService }; const $AuthSessionEntityService: Provider = { provide: 'AuthSessionEntityService', useExisting: AuthSessionEntityService }; @@ -258,6 +269,7 @@ const $FlashLikeEntityService: Provider = { provide: 'FlashLikeEntityService', u const $RoleEntityService: Provider = { provide: 'RoleEntityService', useExisting: RoleEntityService }; const $ReversiGameEntityService: Provider = { provide: 'ReversiGameEntityService', useExisting: ReversiGameEntityService }; const $MetaEntityService: Provider = { provide: 'MetaEntityService', useExisting: MetaEntityService }; +const $SystemWebhookEntityService: Provider = { provide: 'SystemWebhookEntityService', useExisting: SystemWebhookEntityService }; const $ApAudienceService: Provider = { provide: 'ApAudienceService', useExisting: ApAudienceService }; const $ApDbResolverService: Provider = { provide: 'ApDbResolverService', useExisting: ApDbResolverService }; @@ -285,6 +297,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting ], providers: [ LoggerService, + AbuseReportService, + AbuseReportNotificationService, AccountMoveService, AccountUpdateService, AiService, @@ -337,7 +351,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserSuspendService, UserAuthService, VideoProcessingService, - WebhookService, + UserWebhookService, + SystemWebhookService, UtilityService, FileInfoService, SearchService, @@ -366,6 +381,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting AbuseUserReportEntityService, AnnouncementEntityService, + AbuseReportNotificationRecipientEntityService, AntennaEntityService, AppEntityService, AuthSessionEntityService, @@ -399,6 +415,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting RoleEntityService, ReversiGameEntityService, MetaEntityService, + SystemWebhookEntityService, ApAudienceService, ApDbResolverService, @@ -422,6 +439,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting //#region 文字列ベースでのinjection用(循環参照対応のため) $LoggerService, + $AbuseReportService, + $AbuseReportNotificationService, $AccountMoveService, $AccountUpdateService, $AiService, @@ -474,7 +493,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserSuspendService, $UserAuthService, $VideoProcessingService, - $WebhookService, + $UserWebhookService, + $SystemWebhookService, $UtilityService, $FileInfoService, $SearchService, @@ -503,6 +523,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $AbuseUserReportEntityService, $AnnouncementEntityService, + $AbuseReportNotificationRecipientEntityService, $AntennaEntityService, $AppEntityService, $AuthSessionEntityService, @@ -536,6 +557,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $RoleEntityService, $ReversiGameEntityService, $MetaEntityService, + $SystemWebhookEntityService, $ApAudienceService, $ApDbResolverService, @@ -560,6 +582,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting exports: [ QueueModule, LoggerService, + AbuseReportService, + AbuseReportNotificationService, AccountMoveService, AccountUpdateService, AiService, @@ -612,7 +636,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting UserSuspendService, UserAuthService, VideoProcessingService, - WebhookService, + UserWebhookService, + SystemWebhookService, UtilityService, FileInfoService, SearchService, @@ -640,6 +665,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting AbuseUserReportEntityService, AnnouncementEntityService, + AbuseReportNotificationRecipientEntityService, AntennaEntityService, AppEntityService, AuthSessionEntityService, @@ -673,6 +699,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting RoleEntityService, ReversiGameEntityService, MetaEntityService, + SystemWebhookEntityService, ApAudienceService, ApDbResolverService, @@ -696,6 +723,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting //#region 文字列ベースでのinjection用(循環参照対応のため) $LoggerService, + $AbuseReportService, + $AbuseReportNotificationService, $AccountMoveService, $AccountUpdateService, $AiService, @@ -748,7 +777,8 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $UserSuspendService, $UserAuthService, $VideoProcessingService, - $WebhookService, + $UserWebhookService, + $SystemWebhookService, $UtilityService, $FileInfoService, $SearchService, @@ -776,6 +806,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $AbuseUserReportEntityService, $AnnouncementEntityService, + $AbuseReportNotificationRecipientEntityService, $AntennaEntityService, $AppEntityService, $AuthSessionEntityService, @@ -809,6 +840,7 @@ const $ApQuestionService: Provider = { provide: 'ApQuestionService', useExisting $RoleEntityService, $ReversiGameEntityService, $MetaEntityService, + $SystemWebhookEntityService, $ApAudienceService, $ApDbResolverService, diff --git a/packages/backend/src/core/EmailService.ts b/packages/backend/src/core/EmailService.ts index 08f8f80a6e..435dbbae28 100644 --- a/packages/backend/src/core/EmailService.ts +++ b/packages/backend/src/core/EmailService.ts @@ -16,6 +16,7 @@ import type { UserProfilesRepository } from '@/models/_.js'; import { LoggerService } from '@/core/LoggerService.js'; import { bindThis } from '@/decorators.js'; import { HttpRequestService } from '@/core/HttpRequestService.js'; +import { QueueService } from '@/core/QueueService.js'; @Injectable() export class EmailService { @@ -32,6 +33,7 @@ export class EmailService { private loggerService: LoggerService, private utilityService: UtilityService, private httpRequestService: HttpRequestService, + private queueService: QueueService, ) { this.logger = this.loggerService.getLogger('email'); } diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index 90efd63f3a..a70743bed2 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -18,6 +18,7 @@ import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import type { MiSignin } from '@/models/Signin.js'; import type { MiPage } from '@/models/Page.js'; import type { MiWebhook } from '@/models/Webhook.js'; +import type { MiSystemWebhook } from '@/models/SystemWebhook.js'; import type { MiMeta } from '@/models/Meta.js'; import { MiAvatarDecoration, MiReversiGame, MiRole, MiRoleAssignment } from '@/models/_.js'; import type { Packed } from '@/misc/json-schema.js'; @@ -227,6 +228,9 @@ export interface InternalEventTypes { webhookCreated: MiWebhook; webhookDeleted: MiWebhook; webhookUpdated: MiWebhook; + systemWebhookCreated: MiSystemWebhook; + systemWebhookDeleted: MiSystemWebhook; + systemWebhookUpdated: MiSystemWebhook; antennaCreated: MiAntenna; antennaDeleted: MiAntenna; antennaUpdated: MiAntenna; diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index e5580f36d1..0c9de117d2 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -38,7 +38,7 @@ import InstanceChart from '@/core/chart/charts/instance.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { NotificationService } from '@/core/NotificationService.js'; -import { WebhookService } from '@/core/WebhookService.js'; +import { UserWebhookService } from '@/core/UserWebhookService.js'; import { HashtagService } from '@/core/HashtagService.js'; import { AntennaService } from '@/core/AntennaService.js'; import { QueueService } from '@/core/QueueService.js'; @@ -205,7 +205,7 @@ export class NoteCreateService implements OnApplicationShutdown { private federatedInstanceService: FederatedInstanceService, private hashtagService: HashtagService, private antennaService: AntennaService, - private webhookService: WebhookService, + private webhookService: UserWebhookService, private featuredService: FeaturedService, private remoteUserResolveService: RemoteUserResolveService, private apDeliverManagerService: ApDeliverManagerService, @@ -606,7 +606,7 @@ export class NoteCreateService implements OnApplicationShutdown { this.webhookService.getActiveWebhooks().then(webhooks => { webhooks = webhooks.filter(x => x.userId === user.id && x.on.includes('note')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'note', { + this.queueService.userWebhookDeliver(webhook, 'note', { note: noteObj, }); } @@ -633,7 +633,7 @@ export class NoteCreateService implements OnApplicationShutdown { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === data.reply!.userId && x.on.includes('reply')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'reply', { + this.queueService.userWebhookDeliver(webhook, 'reply', { note: noteObj, }); } @@ -656,7 +656,7 @@ export class NoteCreateService implements OnApplicationShutdown { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === data.renote!.userId && x.on.includes('renote')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'renote', { + this.queueService.userWebhookDeliver(webhook, 'renote', { note: noteObj, }); } @@ -788,7 +788,7 @@ export class NoteCreateService implements OnApplicationShutdown { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === u.id && x.on.includes('mention')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'mention', { + this.queueService.userWebhookDeliver(webhook, 'mention', { note: detailPackedNote, }); } diff --git a/packages/backend/src/core/QueueModule.ts b/packages/backend/src/core/QueueModule.ts index 216734e9e5..b10b8e5899 100644 --- a/packages/backend/src/core/QueueModule.ts +++ b/packages/backend/src/core/QueueModule.ts @@ -7,10 +7,17 @@ import { Inject, Module, OnApplicationShutdown } from '@nestjs/common'; import * as Bull from 'bullmq'; import { DI } from '@/di-symbols.js'; import type { Config } from '@/config.js'; -import { QUEUE, baseQueueOptions } from '@/queue/const.js'; +import { baseQueueOptions, QUEUE } from '@/queue/const.js'; import { allSettled } from '@/misc/promise-tracker.js'; +import { + DeliverJobData, + EndedPollNotificationJobData, + InboxJobData, + RelationshipJobData, + UserWebhookDeliverJobData, + SystemWebhookDeliverJobData, +} from '../queue/types.js'; import type { Provider } from '@nestjs/common'; -import type { DeliverJobData, InboxJobData, EndedPollNotificationJobData, WebhookDeliverJobData, RelationshipJobData } from '../queue/types.js'; export type SystemQueue = Bull.Queue>; export type EndedPollNotificationQueue = Bull.Queue; @@ -19,7 +26,8 @@ export type InboxQueue = Bull.Queue; export type DbQueue = Bull.Queue; export type RelationshipQueue = Bull.Queue; export type ObjectStorageQueue = Bull.Queue; -export type WebhookDeliverQueue = Bull.Queue; +export type UserWebhookDeliverQueue = Bull.Queue; +export type SystemWebhookDeliverQueue = Bull.Queue; const $system: Provider = { provide: 'queue:system', @@ -63,9 +71,15 @@ const $objectStorage: Provider = { inject: [DI.config], }; -const $webhookDeliver: Provider = { - provide: 'queue:webhookDeliver', - useFactory: (config: Config) => new Bull.Queue(QUEUE.WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.WEBHOOK_DELIVER)), +const $userWebhookDeliver: Provider = { + provide: 'queue:userWebhookDeliver', + useFactory: (config: Config) => new Bull.Queue(QUEUE.USER_WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.USER_WEBHOOK_DELIVER)), + inject: [DI.config], +}; + +const $systemWebhookDeliver: Provider = { + provide: 'queue:systemWebhookDeliver', + useFactory: (config: Config) => new Bull.Queue(QUEUE.SYSTEM_WEBHOOK_DELIVER, baseQueueOptions(config, QUEUE.SYSTEM_WEBHOOK_DELIVER)), inject: [DI.config], }; @@ -80,7 +94,8 @@ const $webhookDeliver: Provider = { $db, $relationship, $objectStorage, - $webhookDeliver, + $userWebhookDeliver, + $systemWebhookDeliver, ], exports: [ $system, @@ -90,7 +105,8 @@ const $webhookDeliver: Provider = { $db, $relationship, $objectStorage, - $webhookDeliver, + $userWebhookDeliver, + $systemWebhookDeliver, ], }) export class QueueModule implements OnApplicationShutdown { @@ -102,7 +118,8 @@ export class QueueModule implements OnApplicationShutdown { @Inject('queue:db') public dbQueue: DbQueue, @Inject('queue:relationship') public relationshipQueue: RelationshipQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, - @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, + @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, + @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, ) {} public async dispose(): Promise { @@ -117,7 +134,8 @@ export class QueueModule implements OnApplicationShutdown { this.dbQueue.close(), this.relationshipQueue.close(), this.objectStorageQueue.close(), - this.webhookDeliverQueue.close(), + this.userWebhookDeliverQueue.close(), + this.systemWebhookDeliverQueue.close(), ]); } diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index c258a22927..80827a500b 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -8,15 +8,33 @@ import { Inject, Injectable } from '@nestjs/common'; import type { IActivity } from '@/core/activitypub/type.js'; import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiWebhook, webhookEventTypes } from '@/models/Webhook.js'; +import type { MiSystemWebhook, SystemWebhookEventType } from '@/models/SystemWebhook.js'; import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import { bindThis } from '@/decorators.js'; import type { Antenna } from '@/server/api/endpoints/i/import-antennas.js'; -import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, RelationshipQueue, SystemQueue, WebhookDeliverQueue } from './QueueModule.js'; -import type { DbJobData, DeliverJobData, RelationshipJobData, ThinUser } from '../queue/types.js'; +import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js'; +import type { + DbJobData, + DeliverJobData, + RelationshipJobData, + SystemWebhookDeliverJobData, + ThinUser, + UserWebhookDeliverJobData, +} from '../queue/types.js'; +import type { + DbQueue, + DeliverQueue, + EndedPollNotificationQueue, + InboxQueue, + ObjectStorageQueue, + RelationshipQueue, + SystemQueue, + UserWebhookDeliverQueue, + SystemWebhookDeliverQueue, +} from './QueueModule.js'; import type httpSignature from '@peertube/http-signature'; import type * as Bull from 'bullmq'; -import { ApRequestCreator } from '@/core/activitypub/ApRequestService.js'; @Injectable() export class QueueService { @@ -31,7 +49,8 @@ export class QueueService { @Inject('queue:db') public dbQueue: DbQueue, @Inject('queue:relationship') public relationshipQueue: RelationshipQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, - @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, + @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, + @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, ) { this.systemQueue.add('tickCharts', { }, { @@ -431,9 +450,13 @@ export class QueueService { }); } + /** + * @see UserWebhookDeliverJobData + * @see WebhookDeliverProcessorService + */ @bindThis - public webhookDeliver(webhook: MiWebhook, type: typeof webhookEventTypes[number], content: unknown) { - const data = { + public userWebhookDeliver(webhook: MiWebhook, type: typeof webhookEventTypes[number], content: unknown) { + const data: UserWebhookDeliverJobData = { type, content, webhookId: webhook.id, @@ -444,7 +467,33 @@ export class QueueService { eventId: randomUUID(), }; - return this.webhookDeliverQueue.add(webhook.id, data, { + return this.userWebhookDeliverQueue.add(webhook.id, data, { + attempts: 4, + backoff: { + type: 'custom', + }, + removeOnComplete: true, + removeOnFail: true, + }); + } + + /** + * @see SystemWebhookDeliverJobData + * @see WebhookDeliverProcessorService + */ + @bindThis + public systemWebhookDeliver(webhook: MiSystemWebhook, type: SystemWebhookEventType, content: unknown) { + const data: SystemWebhookDeliverJobData = { + type, + content, + webhookId: webhook.id, + to: webhook.url, + secret: webhook.secret, + createdAt: Date.now(), + eventId: randomUUID(), + }; + + return this.systemWebhookDeliverQueue.add(webhook.id, data, { attempts: 4, backoff: { type: 'custom', diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts index d6eea70297..e2ebecb99f 100644 --- a/packages/backend/src/core/RoleService.ts +++ b/packages/backend/src/core/RoleService.ts @@ -410,14 +410,32 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit { } @bindThis - public async getModeratorIds(includeAdmins = true): Promise { + public async getModeratorIds(includeAdmins = true, excludeExpire = false): Promise { const roles = await this.rolesCache.fetch(() => this.rolesRepository.findBy({})); - const moderatorRoles = includeAdmins ? roles.filter(r => r.isModerator || r.isAdministrator) : roles.filter(r => r.isModerator); - const assigns = moderatorRoles.length > 0 ? await this.roleAssignmentsRepository.findBy({ - roleId: In(moderatorRoles.map(r => r.id)), - }) : []; + const moderatorRoles = includeAdmins + ? roles.filter(r => r.isModerator || r.isAdministrator) + : roles.filter(r => r.isModerator); + // TODO: isRootなアカウントも含める - return assigns.map(a => a.userId); + const assigns = moderatorRoles.length > 0 + ? await this.roleAssignmentsRepository.findBy({ roleId: In(moderatorRoles.map(r => r.id)) }) + : []; + + const now = Date.now(); + const result = [ + // Setを経由して重複を除去(ユーザIDは重複する可能性があるので) + ...new Set( + assigns + .filter(it => + (excludeExpire) + ? (it.expiresAt == null || it.expiresAt.getTime() > now) + : true, + ) + .map(a => a.userId), + ), + ]; + + return result.sort((x, y) => x.localeCompare(y)); } @bindThis diff --git a/packages/backend/src/core/SystemWebhookService.ts b/packages/backend/src/core/SystemWebhookService.ts new file mode 100644 index 0000000000..bc6851f788 --- /dev/null +++ b/packages/backend/src/core/SystemWebhookService.ts @@ -0,0 +1,233 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import * as Redis from 'ioredis'; +import type { MiUser, SystemWebhooksRepository } from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; +import { bindThis } from '@/decorators.js'; +import { GlobalEvents, GlobalEventService } from '@/core/GlobalEventService.js'; +import { MiSystemWebhook, type SystemWebhookEventType } from '@/models/SystemWebhook.js'; +import { IdService } from '@/core/IdService.js'; +import { QueueService } from '@/core/QueueService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { LoggerService } from '@/core/LoggerService.js'; +import Logger from '@/logger.js'; +import type { OnApplicationShutdown } from '@nestjs/common'; + +@Injectable() +export class SystemWebhookService implements OnApplicationShutdown { + private logger: Logger; + private activeSystemWebhooksFetched = false; + private activeSystemWebhooks: MiSystemWebhook[] = []; + + constructor( + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, + @Inject(DI.systemWebhooksRepository) + private systemWebhooksRepository: SystemWebhooksRepository, + private idService: IdService, + private queueService: QueueService, + private moderationLogService: ModerationLogService, + private loggerService: LoggerService, + private globalEventService: GlobalEventService, + ) { + this.redisForSub.on('message', this.onMessage); + this.logger = this.loggerService.getLogger('webhook'); + } + + @bindThis + public async fetchActiveSystemWebhooks() { + if (!this.activeSystemWebhooksFetched) { + this.activeSystemWebhooks = await this.systemWebhooksRepository.findBy({ + isActive: true, + }); + this.activeSystemWebhooksFetched = true; + } + + return this.activeSystemWebhooks; + } + + /** + * SystemWebhook の一覧を取得する. + */ + @bindThis + public async fetchSystemWebhooks(params?: { + ids?: MiSystemWebhook['id'][]; + isActive?: MiSystemWebhook['isActive']; + on?: MiSystemWebhook['on']; + }): Promise { + const query = this.systemWebhooksRepository.createQueryBuilder('systemWebhook'); + if (params) { + if (params.ids && params.ids.length > 0) { + query.andWhere('systemWebhook.id IN (:...ids)', { ids: params.ids }); + } + if (params.isActive !== undefined) { + query.andWhere('systemWebhook.isActive = :isActive', { isActive: params.isActive }); + } + if (params.on && params.on.length > 0) { + query.andWhere(':on <@ systemWebhook.on', { on: params.on }); + } + } + + return query.getMany(); + } + + /** + * SystemWebhook を作成する. + */ + @bindThis + public async createSystemWebhook( + params: { + isActive: MiSystemWebhook['isActive']; + name: MiSystemWebhook['name']; + on: MiSystemWebhook['on']; + url: MiSystemWebhook['url']; + secret: MiSystemWebhook['secret']; + }, + updater: MiUser, + ): Promise { + const id = this.idService.gen(); + await this.systemWebhooksRepository.insert({ + ...params, + id, + }); + + const webhook = await this.systemWebhooksRepository.findOneByOrFail({ id }); + this.globalEventService.publishInternalEvent('systemWebhookCreated', webhook); + this.moderationLogService + .log(updater, 'createSystemWebhook', { + systemWebhookId: webhook.id, + webhook: webhook, + }) + .then(); + + return webhook; + } + + /** + * SystemWebhook を更新する. + */ + @bindThis + public async updateSystemWebhook( + params: { + id: MiSystemWebhook['id']; + isActive: MiSystemWebhook['isActive']; + name: MiSystemWebhook['name']; + on: MiSystemWebhook['on']; + url: MiSystemWebhook['url']; + secret: MiSystemWebhook['secret']; + }, + updater: MiUser, + ): Promise { + const beforeEntity = await this.systemWebhooksRepository.findOneByOrFail({ id: params.id }); + await this.systemWebhooksRepository.update(beforeEntity.id, { + updatedAt: new Date(), + isActive: params.isActive, + name: params.name, + on: params.on, + url: params.url, + secret: params.secret, + }); + + const afterEntity = await this.systemWebhooksRepository.findOneByOrFail({ id: beforeEntity.id }); + this.globalEventService.publishInternalEvent('systemWebhookUpdated', afterEntity); + this.moderationLogService + .log(updater, 'updateSystemWebhook', { + systemWebhookId: beforeEntity.id, + before: beforeEntity, + after: afterEntity, + }) + .then(); + + return afterEntity; + } + + /** + * SystemWebhook を削除する. + */ + @bindThis + public async deleteSystemWebhook(id: MiSystemWebhook['id'], updater: MiUser) { + const webhook = await this.systemWebhooksRepository.findOneByOrFail({ id }); + await this.systemWebhooksRepository.delete(id); + + this.globalEventService.publishInternalEvent('systemWebhookDeleted', webhook); + this.moderationLogService + .log(updater, 'deleteSystemWebhook', { + systemWebhookId: webhook.id, + webhook, + }) + .then(); + } + + /** + * SystemWebhook をWebhook配送キューに追加する + * @see QueueService.systemWebhookDeliver + */ + @bindThis + public async enqueueSystemWebhook(webhook: MiSystemWebhook | MiSystemWebhook['id'], type: SystemWebhookEventType, content: unknown) { + const webhookEntity = typeof webhook === 'string' + ? (await this.fetchActiveSystemWebhooks()).find(a => a.id === webhook) + : webhook; + if (!webhookEntity || !webhookEntity.isActive) { + this.logger.info(`Webhook is not active or not found : ${webhook}`); + return; + } + + if (!webhookEntity.on.includes(type)) { + this.logger.info(`Webhook ${webhookEntity.id} is not listening to ${type}`); + return; + } + + return this.queueService.systemWebhookDeliver(webhookEntity, type, content); + } + + @bindThis + private async onMessage(_: string, data: string): Promise { + const obj = JSON.parse(data); + if (obj.channel !== 'internal') { + return; + } + + const { type, body } = obj.message as GlobalEvents['internal']['payload']; + switch (type) { + case 'systemWebhookCreated': { + if (body.isActive) { + this.activeSystemWebhooks.push(MiSystemWebhook.deserialize(body)); + } + break; + } + case 'systemWebhookUpdated': { + if (body.isActive) { + const i = this.activeSystemWebhooks.findIndex(a => a.id === body.id); + if (i > -1) { + this.activeSystemWebhooks[i] = MiSystemWebhook.deserialize(body); + } else { + this.activeSystemWebhooks.push(MiSystemWebhook.deserialize(body)); + } + } else { + this.activeSystemWebhooks = this.activeSystemWebhooks.filter(a => a.id !== body.id); + } + break; + } + case 'systemWebhookDeleted': { + this.activeSystemWebhooks = this.activeSystemWebhooks.filter(a => a.id !== body.id); + break; + } + default: + break; + } + } + + @bindThis + public dispose(): void { + this.redisForSub.off('message', this.onMessage); + } + + @bindThis + public onApplicationShutdown(signal?: string | undefined): void { + this.dispose(); + } +} diff --git a/packages/backend/src/core/UserBlockingService.ts b/packages/backend/src/core/UserBlockingService.ts index 96f389b54c..2f1310b8ef 100644 --- a/packages/backend/src/core/UserBlockingService.ts +++ b/packages/backend/src/core/UserBlockingService.ts @@ -16,7 +16,7 @@ import Logger from '@/logger.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; import { LoggerService } from '@/core/LoggerService.js'; -import { WebhookService } from '@/core/WebhookService.js'; +import { UserWebhookService } from '@/core/UserWebhookService.js'; import { bindThis } from '@/decorators.js'; import { CacheService } from '@/core/CacheService.js'; import { UserFollowingService } from '@/core/UserFollowingService.js'; @@ -46,7 +46,7 @@ export class UserBlockingService implements OnModuleInit { private idService: IdService, private queueService: QueueService, private globalEventService: GlobalEventService, - private webhookService: WebhookService, + private webhookService: UserWebhookService, private apRendererService: ApRendererService, private loggerService: LoggerService, ) { @@ -121,7 +121,7 @@ export class UserBlockingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'unfollow', { + this.queueService.userWebhookDeliver(webhook, 'unfollow', { user: packed, }); } diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts index 406ea04031..267a6a3f1b 100644 --- a/packages/backend/src/core/UserFollowingService.ts +++ b/packages/backend/src/core/UserFollowingService.ts @@ -16,7 +16,7 @@ import { isDuplicateKeyValueError } from '@/misc/is-duplicate-key-value-error.js import type { Packed } from '@/misc/json-schema.js'; import InstanceChart from '@/core/chart/charts/instance.js'; import { FederatedInstanceService } from '@/core/FederatedInstanceService.js'; -import { WebhookService } from '@/core/WebhookService.js'; +import { UserWebhookService } from '@/core/UserWebhookService.js'; import { NotificationService } from '@/core/NotificationService.js'; import { DI } from '@/di-symbols.js'; import type { FollowingsRepository, FollowRequestsRepository, InstancesRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js'; @@ -82,7 +82,7 @@ export class UserFollowingService implements OnModuleInit { private metaService: MetaService, private notificationService: NotificationService, private federatedInstanceService: FederatedInstanceService, - private webhookService: WebhookService, + private webhookService: UserWebhookService, private apRendererService: ApRendererService, private accountMoveService: AccountMoveService, private fanoutTimelineService: FanoutTimelineService, @@ -331,7 +331,7 @@ export class UserFollowingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('follow')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'follow', { + this.queueService.userWebhookDeliver(webhook, 'follow', { user: packed, }); } @@ -345,7 +345,7 @@ export class UserFollowingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === followee.id && x.on.includes('followed')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'followed', { + this.queueService.userWebhookDeliver(webhook, 'followed', { user: packed, }); } @@ -398,7 +398,7 @@ export class UserFollowingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'unfollow', { + this.queueService.userWebhookDeliver(webhook, 'unfollow', { user: packed, }); } @@ -740,7 +740,7 @@ export class UserFollowingService implements OnModuleInit { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === follower.id && x.on.includes('unfollow')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'unfollow', { + this.queueService.userWebhookDeliver(webhook, 'unfollow', { user: packedFollowee, }); } diff --git a/packages/backend/src/core/UserWebhookService.ts b/packages/backend/src/core/UserWebhookService.ts new file mode 100644 index 0000000000..e96bfeea95 --- /dev/null +++ b/packages/backend/src/core/UserWebhookService.ts @@ -0,0 +1,99 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import * as Redis from 'ioredis'; +import type { WebhooksRepository } from '@/models/_.js'; +import type { MiWebhook } from '@/models/Webhook.js'; +import { DI } from '@/di-symbols.js'; +import { bindThis } from '@/decorators.js'; +import { GlobalEvents } from '@/core/GlobalEventService.js'; +import type { OnApplicationShutdown } from '@nestjs/common'; + +@Injectable() +export class UserWebhookService implements OnApplicationShutdown { + private activeWebhooksFetched = false; + private activeWebhooks: MiWebhook[] = []; + + constructor( + @Inject(DI.redisForSub) + private redisForSub: Redis.Redis, + @Inject(DI.webhooksRepository) + private webhooksRepository: WebhooksRepository, + ) { + this.redisForSub.on('message', this.onMessage); + } + + @bindThis + public async getActiveWebhooks() { + if (!this.activeWebhooksFetched) { + this.activeWebhooks = await this.webhooksRepository.findBy({ + active: true, + }); + this.activeWebhooksFetched = true; + } + + return this.activeWebhooks; + } + + @bindThis + private async onMessage(_: string, data: string): Promise { + const obj = JSON.parse(data); + if (obj.channel !== 'internal') { + return; + } + + const { type, body } = obj.message as GlobalEvents['internal']['payload']; + switch (type) { + case 'webhookCreated': { + if (body.active) { + this.activeWebhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい + ...body, + latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, + user: null, // joinなカラムは通常取ってこないので + }); + } + break; + } + case 'webhookUpdated': { + if (body.active) { + const i = this.activeWebhooks.findIndex(a => a.id === body.id); + if (i > -1) { + this.activeWebhooks[i] = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい + ...body, + latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, + user: null, // joinなカラムは通常取ってこないので + }; + } else { + this.activeWebhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい + ...body, + latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, + user: null, // joinなカラムは通常取ってこないので + }); + } + } else { + this.activeWebhooks = this.activeWebhooks.filter(a => a.id !== body.id); + } + break; + } + case 'webhookDeleted': { + this.activeWebhooks = this.activeWebhooks.filter(a => a.id !== body.id); + break; + } + default: + break; + } + } + + @bindThis + public dispose(): void { + this.redisForSub.off('message', this.onMessage); + } + + @bindThis + public onApplicationShutdown(signal?: string | undefined): void { + this.dispose(); + } +} diff --git a/packages/backend/src/core/WebhookService.ts b/packages/backend/src/core/WebhookService.ts deleted file mode 100644 index 6be34977b0..0000000000 --- a/packages/backend/src/core/WebhookService.ts +++ /dev/null @@ -1,97 +0,0 @@ -/* - * SPDX-FileCopyrightText: syuilo and misskey-project - * SPDX-License-Identifier: AGPL-3.0-only - */ - -import { Inject, Injectable } from '@nestjs/common'; -import * as Redis from 'ioredis'; -import type { WebhooksRepository } from '@/models/_.js'; -import type { MiWebhook } from '@/models/Webhook.js'; -import { DI } from '@/di-symbols.js'; -import { bindThis } from '@/decorators.js'; -import type { GlobalEvents } from '@/core/GlobalEventService.js'; -import type { OnApplicationShutdown } from '@nestjs/common'; - -@Injectable() -export class WebhookService implements OnApplicationShutdown { - private webhooksFetched = false; - private webhooks: MiWebhook[] = []; - - constructor( - @Inject(DI.redisForSub) - private redisForSub: Redis.Redis, - - @Inject(DI.webhooksRepository) - private webhooksRepository: WebhooksRepository, - ) { - //this.onMessage = this.onMessage.bind(this); - this.redisForSub.on('message', this.onMessage); - } - - @bindThis - public async getActiveWebhooks() { - if (!this.webhooksFetched) { - this.webhooks = await this.webhooksRepository.findBy({ - active: true, - }); - this.webhooksFetched = true; - } - - return this.webhooks; - } - - @bindThis - private async onMessage(_: string, data: string): Promise { - const obj = JSON.parse(data); - - if (obj.channel === 'internal') { - const { type, body } = obj.message as GlobalEvents['internal']['payload']; - switch (type) { - case 'webhookCreated': - if (body.active) { - this.webhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい - ...body, - latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, - user: null, // joinなカラムは通常取ってこないので - }); - } - break; - case 'webhookUpdated': - if (body.active) { - const i = this.webhooks.findIndex(a => a.id === body.id); - if (i > -1) { - this.webhooks[i] = { // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい - ...body, - latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, - user: null, // joinなカラムは通常取ってこないので - }; - } else { - this.webhooks.push({ // TODO: このあたりのデシリアライズ処理は各modelファイル内に関数としてexportしたい - ...body, - latestSentAt: body.latestSentAt ? new Date(body.latestSentAt) : null, - user: null, // joinなカラムは通常取ってこないので - }); - } - } else { - this.webhooks = this.webhooks.filter(a => a.id !== body.id); - } - break; - case 'webhookDeleted': - this.webhooks = this.webhooks.filter(a => a.id !== body.id); - break; - default: - break; - } - } - } - - @bindThis - public dispose(): void { - this.redisForSub.off('message', this.onMessage); - } - - @bindThis - public onApplicationShutdown(signal?: string | undefined): void { - this.dispose(); - } -} diff --git a/packages/backend/src/core/activitypub/ApInboxService.ts b/packages/backend/src/core/activitypub/ApInboxService.ts index d0d206760c..de3178b482 100644 --- a/packages/backend/src/core/activitypub/ApInboxService.ts +++ b/packages/backend/src/core/activitypub/ApInboxService.ts @@ -29,6 +29,7 @@ import { bindThis } from '@/decorators.js'; import type { MiRemoteUser } from '@/models/User.js'; import { isNotNull } from '@/misc/is-not-null.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { AbuseReportService } from '@/core/AbuseReportService.js'; import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { ApNoteService } from './models/ApNoteService.js'; import { ApLoggerService } from './ApLoggerService.js'; @@ -57,9 +58,6 @@ export class ApInboxService { @Inject(DI.followingsRepository) private followingsRepository: FollowingsRepository, - @Inject(DI.abuseUserReportsRepository) - private abuseUserReportsRepository: AbuseUserReportsRepository, - @Inject(DI.followRequestsRepository) private followRequestsRepository: FollowRequestsRepository, @@ -68,6 +66,7 @@ export class ApInboxService { private utilityService: UtilityService, private idService: IdService, private metaService: MetaService, + private abuseReportService: AbuseReportService, private userFollowingService: UserFollowingService, private apAudienceService: ApAudienceService, private reactionService: ReactionService, @@ -545,14 +544,13 @@ export class ApInboxService { }); if (users.length < 1) return 'skip'; - await this.abuseUserReportsRepository.insert({ - id: this.idService.gen(), + await this.abuseReportService.report([{ targetUserId: users[0].id, targetUserHost: users[0].host, reporterId: actor.id, reporterHost: actor.host, comment: `${activity.content}\n${JSON.stringify(uris, null, 2)}`, - }); + }]); return 'ok'; } diff --git a/packages/backend/src/core/entities/AbuseReportNotificationRecipientEntityService.ts b/packages/backend/src/core/entities/AbuseReportNotificationRecipientEntityService.ts new file mode 100644 index 0000000000..6819afafd9 --- /dev/null +++ b/packages/backend/src/core/entities/AbuseReportNotificationRecipientEntityService.ts @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { In } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import type { AbuseReportNotificationRecipientRepository, MiAbuseReportNotificationRecipient } from '@/models/_.js'; +import { bindThis } from '@/decorators.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; +import { Packed } from '@/misc/json-schema.js'; +import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; +import { isNotNull } from '@/misc/is-not-null.js'; + +@Injectable() +export class AbuseReportNotificationRecipientEntityService { + constructor( + @Inject(DI.abuseReportNotificationRecipientRepository) + private abuseReportNotificationRecipientRepository: AbuseReportNotificationRecipientRepository, + private userEntityService: UserEntityService, + private systemWebhookEntityService: SystemWebhookEntityService, + ) { + } + + @bindThis + public async pack( + src: MiAbuseReportNotificationRecipient['id'] | MiAbuseReportNotificationRecipient, + opts?: { + users: Map>, + webhooks: Map>, + }, + ): Promise> { + const recipient = typeof src === 'object' + ? src + : await this.abuseReportNotificationRecipientRepository.findOneByOrFail({ id: src }); + const user = recipient.userId + ? (opts?.users.get(recipient.userId) ?? await this.userEntityService.pack<'UserLite'>(recipient.userId)) + : undefined; + const webhook = recipient.systemWebhookId + ? (opts?.webhooks.get(recipient.systemWebhookId) ?? await this.systemWebhookEntityService.pack(recipient.systemWebhookId)) + : undefined; + + return { + id: recipient.id, + isActive: recipient.isActive, + updatedAt: recipient.updatedAt.toISOString(), + name: recipient.name, + method: recipient.method, + userId: recipient.userId ?? undefined, + user: user, + systemWebhookId: recipient.systemWebhookId ?? undefined, + systemWebhook: webhook, + }; + } + + @bindThis + public async packMany( + src: MiAbuseReportNotificationRecipient['id'][] | MiAbuseReportNotificationRecipient[], + ): Promise[]> { + const objs = src.filter((it): it is MiAbuseReportNotificationRecipient => typeof it === 'object'); + const ids = src.filter((it): it is MiAbuseReportNotificationRecipient['id'] => typeof it === 'string'); + if (ids.length > 0) { + objs.push( + ...await this.abuseReportNotificationRecipientRepository.findBy({ id: In(ids) }), + ); + } + + const userIds = objs.map(it => it.userId).filter(isNotNull); + const users: Map> = (userIds.length > 0) + ? await this.userEntityService.packMany(userIds) + .then(it => new Map(it.map(it => [it.id, it]))) + : new Map(); + + const systemWebhookIds = objs.map(it => it.systemWebhookId).filter(isNotNull); + const systemWebhooks: Map> = (systemWebhookIds.length > 0) + ? await this.systemWebhookEntityService.packMany(systemWebhookIds) + .then(it => new Map(it.map(it => [it.id, it]))) + : new Map(); + + return Promise + .all( + objs.map(it => this.pack(it, { users: users, webhooks: systemWebhooks })), + ) + .then(it => it.sort((a, b) => a.id.localeCompare(b.id))); + } +} + diff --git a/packages/backend/src/core/entities/SystemWebhookEntityService.ts b/packages/backend/src/core/entities/SystemWebhookEntityService.ts new file mode 100644 index 0000000000..e18734091c --- /dev/null +++ b/packages/backend/src/core/entities/SystemWebhookEntityService.ts @@ -0,0 +1,74 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { In } from 'typeorm'; +import { DI } from '@/di-symbols.js'; +import type { MiSystemWebhook, SystemWebhooksRepository } from '@/models/_.js'; +import { bindThis } from '@/decorators.js'; +import { Packed } from '@/misc/json-schema.js'; + +@Injectable() +export class SystemWebhookEntityService { + constructor( + @Inject(DI.systemWebhooksRepository) + private systemWebhooksRepository: SystemWebhooksRepository, + ) { + } + + @bindThis + public async pack( + src: MiSystemWebhook['id'] | MiSystemWebhook, + opts?: { + webhooks: Map + }, + ): Promise> { + const webhook = typeof src === 'object' + ? src + : opts?.webhooks.get(src) ?? await this.systemWebhooksRepository.findOneByOrFail({ id: src }); + + return { + id: webhook.id, + isActive: webhook.isActive, + updatedAt: webhook.updatedAt.toISOString(), + latestSentAt: webhook.latestSentAt?.toISOString() ?? null, + latestStatus: webhook.latestStatus, + name: webhook.name, + on: webhook.on, + url: webhook.url, + secret: webhook.secret, + }; + } + + @bindThis + public async packMany(src: MiSystemWebhook['id'][] | MiSystemWebhook[]): Promise[]> { + if (src.length === 0) { + return []; + } + + const webhooks = Array.of(); + webhooks.push( + ...src.filter((it): it is MiSystemWebhook => typeof it === 'object'), + ); + + const ids = src.filter((it): it is MiSystemWebhook['id'] => typeof it === 'string'); + if (ids.length > 0) { + webhooks.push( + ...await this.systemWebhooksRepository.findBy({ id: In(ids) }), + ); + } + + return Promise + .all( + webhooks.map(x => + this.pack(x, { + webhooks: new Map(webhooks.map(x => [x.id, x])), + }), + ), + ) + .then(it => it.sort((a, b) => a.id.localeCompare(b.id))); + } +} + diff --git a/packages/backend/src/di-symbols.ts b/packages/backend/src/di-symbols.ts index 919f4794a3..271082b4ff 100644 --- a/packages/backend/src/di-symbols.ts +++ b/packages/backend/src/di-symbols.ts @@ -49,6 +49,7 @@ export const DI = { swSubscriptionsRepository: Symbol('swSubscriptionsRepository'), hashtagsRepository: Symbol('hashtagsRepository'), abuseUserReportsRepository: Symbol('abuseUserReportsRepository'), + abuseReportNotificationRecipientRepository: Symbol('abuseReportNotificationRecipientRepository'), registrationTicketsRepository: Symbol('registrationTicketsRepository'), authSessionsRepository: Symbol('authSessionsRepository'), accessTokensRepository: Symbol('accessTokensRepository'), @@ -70,6 +71,7 @@ export const DI = { channelFavoritesRepository: Symbol('channelFavoritesRepository'), registryItemsRepository: Symbol('registryItemsRepository'), webhooksRepository: Symbol('webhooksRepository'), + systemWebhooksRepository: Symbol('systemWebhooksRepository'), adsRepository: Symbol('adsRepository'), passwordResetRequestsRepository: Symbol('passwordResetRequestsRepository'), retentionAggregationsRepository: Symbol('retentionAggregationsRepository'), diff --git a/packages/backend/src/misc/json-schema.ts b/packages/backend/src/misc/json-schema.ts index 41e5bfe9e4..a721b8663c 100644 --- a/packages/backend/src/misc/json-schema.ts +++ b/packages/backend/src/misc/json-schema.ts @@ -4,12 +4,12 @@ */ import { - packedUserLiteSchema, - packedUserDetailedNotMeOnlySchema, packedMeDetailedOnlySchema, - packedUserDetailedNotMeSchema, packedMeDetailedSchema, + packedUserDetailedNotMeOnlySchema, + packedUserDetailedNotMeSchema, packedUserDetailedSchema, + packedUserLiteSchema, packedUserSchema, } from '@/models/json-schema/user.js'; import { packedNoteSchema } from '@/models/json-schema/note.js'; @@ -25,7 +25,7 @@ import { packedBlockingSchema } from '@/models/json-schema/blocking.js'; import { packedNoteReactionSchema } from '@/models/json-schema/note-reaction.js'; import { packedHashtagSchema } from '@/models/json-schema/hashtag.js'; import { packedInviteCodeSchema } from '@/models/json-schema/invite-code.js'; -import { packedPageSchema, packedPageBlockSchema } from '@/models/json-schema/page.js'; +import { packedPageBlockSchema, packedPageSchema } from '@/models/json-schema/page.js'; import { packedNoteFavoriteSchema } from '@/models/json-schema/note-favorite.js'; import { packedChannelSchema } from '@/models/json-schema/channel.js'; import { packedAntennaSchema } from '@/models/json-schema/antenna.js'; @@ -38,25 +38,27 @@ import { packedFlashSchema } from '@/models/json-schema/flash.js'; import { packedAnnouncementSchema } from '@/models/json-schema/announcement.js'; import { packedSigninSchema } from '@/models/json-schema/signin.js'; import { - packedRoleLiteSchema, - packedRoleSchema, - packedRolePoliciesSchema, + packedRoleCondFormulaFollowersOrFollowingOrNotesSchema, packedRoleCondFormulaLogicsSchema, - packedRoleCondFormulaValueNot, - packedRoleCondFormulaValueIsLocalOrRemoteSchema, packedRoleCondFormulaValueAssignedRoleSchema, packedRoleCondFormulaValueCreatedSchema, - packedRoleCondFormulaFollowersOrFollowingOrNotesSchema, + packedRoleCondFormulaValueIsLocalOrRemoteSchema, + packedRoleCondFormulaValueNot, packedRoleCondFormulaValueSchema, packedRoleCondFormulaValueUserSettingBooleanSchema, + packedRoleLiteSchema, + packedRolePoliciesSchema, + packedRoleSchema, } from '@/models/json-schema/role.js'; import { packedAdSchema } from '@/models/json-schema/ad.js'; -import { packedReversiGameLiteSchema, packedReversiGameDetailedSchema } from '@/models/json-schema/reversi-game.js'; +import { packedReversiGameDetailedSchema, packedReversiGameLiteSchema } from '@/models/json-schema/reversi-game.js'; import { - packedMetaLiteSchema, packedMetaDetailedOnlySchema, packedMetaDetailedSchema, + packedMetaLiteSchema, } from '@/models/json-schema/meta.js'; +import { packedSystemWebhookSchema } from '@/models/json-schema/system-webhook.js'; +import { packedAbuseReportNotificationRecipientSchema } from '@/models/json-schema/abuse-report-notification-recipient.js'; export const refs = { UserLite: packedUserLiteSchema, @@ -111,6 +113,8 @@ export const refs = { MetaLite: packedMetaLiteSchema, MetaDetailedOnly: packedMetaDetailedOnlySchema, MetaDetailed: packedMetaDetailedSchema, + SystemWebhook: packedSystemWebhookSchema, + AbuseReportNotificationRecipient: packedAbuseReportNotificationRecipientSchema, }; export type Packed = SchemaType; diff --git a/packages/backend/src/models/AbuseReportNotificationRecipient.ts b/packages/backend/src/models/AbuseReportNotificationRecipient.ts new file mode 100644 index 0000000000..fbff880afc --- /dev/null +++ b/packages/backend/src/models/AbuseReportNotificationRecipient.ts @@ -0,0 +1,100 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Column, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm'; +import { MiSystemWebhook } from '@/models/SystemWebhook.js'; +import { MiUserProfile } from '@/models/UserProfile.js'; +import { id } from './util/id.js'; +import { MiUser } from './User.js'; + +/** + * 通報受信時に通知を送信する方法. + */ +export type RecipientMethod = 'email' | 'webhook'; + +@Entity('abuse_report_notification_recipient') +export class MiAbuseReportNotificationRecipient { + @PrimaryColumn(id()) + public id: string; + + /** + * 有効かどうか. + */ + @Index() + @Column('boolean', { + default: true, + }) + public isActive: boolean; + + /** + * 更新日時. + */ + @Column('timestamp with time zone', { + default: () => 'CURRENT_TIMESTAMP', + }) + public updatedAt: Date; + + /** + * 通知設定名. + */ + @Column('varchar', { + length: 255, + }) + public name: string; + + /** + * 通知方法. + */ + @Index() + @Column('varchar', { + length: 64, + }) + public method: RecipientMethod; + + /** + * 通知先のユーザID. + */ + @Index() + @Column({ + ...id(), + nullable: true, + }) + public userId: MiUser['id'] | null; + + /** + * 通知先のユーザ. + */ + @ManyToOne(type => MiUser, { + onDelete: 'CASCADE', + }) + @JoinColumn({ name: 'userId', referencedColumnName: 'id', foreignKeyConstraintName: 'FK_abuse_report_notification_recipient_userId1' }) + public user: MiUser | null; + + /** + * 通知先のユーザプロフィール. + */ + @ManyToOne(type => MiUserProfile, {}) + @JoinColumn({ name: 'userId', referencedColumnName: 'userId', foreignKeyConstraintName: 'FK_abuse_report_notification_recipient_userId2' }) + public userProfile: MiUserProfile | null; + + /** + * 通知先のシステムWebhookId. + */ + @Index() + @Column({ + ...id(), + nullable: true, + }) + public systemWebhookId: string | null; + + /** + * 通知先のシステムWebhook. + */ + @ManyToOne(type => MiSystemWebhook, { + onDelete: 'CASCADE', + }) + @JoinColumn() + public systemWebhook: MiSystemWebhook | null; +} diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index d3062d6b36..ea0f88baba 100644 --- a/packages/backend/src/models/RepositoryModule.ts +++ b/packages/backend/src/models/RepositoryModule.ts @@ -3,11 +3,83 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import type { Provider } from '@nestjs/common'; import { Module } from '@nestjs/common'; import { DI } from '@/di-symbols.js'; -import { MiRepository, MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook, MiBubbleGameRecord, MiReversiGame, miRepository } from './_.js'; +import { + MiAbuseReportNotificationRecipient, + MiAbuseUserReport, + MiAccessToken, + MiAd, + MiAnnouncement, + MiAnnouncementRead, + MiAntenna, + MiApp, + MiAuthSession, + MiAvatarDecoration, + MiBlocking, + MiBubbleGameRecord, + MiChannel, + MiChannelFavorite, + MiChannelFollowing, + MiClip, + MiClipFavorite, + MiClipNote, + MiDriveFile, + MiDriveFolder, + MiEmoji, + MiFlash, + MiFlashLike, + MiFollowing, + MiFollowRequest, + MiGalleryLike, + MiGalleryPost, + MiHashtag, + MiInstance, + MiMeta, + MiModerationLog, + MiMuting, + MiNote, + MiNoteFavorite, + MiNoteReaction, + MiNoteThreadMuting, + MiNoteUnread, + MiPage, + MiPageLike, + MiPasswordResetRequest, + MiPoll, + MiPollVote, + MiPromoNote, + MiPromoRead, + MiRegistrationTicket, + MiRegistryItem, + MiRelay, + MiRenoteMuting, + MiRepository, + miRepository, + MiRetentionAggregation, + MiReversiGame, + MiRole, + MiRoleAssignment, + MiSignin, + MiSwSubscription, + MiSystemWebhook, + MiUsedUsername, + MiUser, + MiUserIp, + MiUserKeypair, + MiUserList, + MiUserListFavorite, + MiUserListMembership, + MiUserMemo, + MiUserNotePining, + MiUserPending, + MiUserProfile, + MiUserPublickey, + MiUserSecurityKey, + MiWebhook +} from './_.js'; import type { DataSource } from 'typeorm'; -import type { Provider } from '@nestjs/common'; const $usersRepository: Provider = { provide: DI.usersRepository, @@ -225,6 +297,12 @@ const $abuseUserReportsRepository: Provider = { inject: [DI.db], }; +const $abuseReportNotificationRecipientRepository: Provider = { + provide: DI.abuseReportNotificationRecipientRepository, + useFactory: (db: DataSource) => db.getRepository(MiAbuseReportNotificationRecipient), + inject: [DI.db], +}; + const $registrationTicketsRepository: Provider = { provide: DI.registrationTicketsRepository, useFactory: (db: DataSource) => db.getRepository(MiRegistrationTicket).extend(miRepository as MiRepository), @@ -351,6 +429,12 @@ const $webhooksRepository: Provider = { inject: [DI.db], }; +const $systemWebhooksRepository: Provider = { + provide: DI.systemWebhooksRepository, + useFactory: (db: DataSource) => db.getRepository(MiSystemWebhook), + inject: [DI.db], +}; + const $adsRepository: Provider = { provide: DI.adsRepository, useFactory: (db: DataSource) => db.getRepository(MiAd).extend(miRepository as MiRepository), @@ -412,8 +496,7 @@ const $reversiGamesRepository: Provider = { }; @Module({ - imports: [ - ], + imports: [], providers: [ $usersRepository, $notesRepository, @@ -451,6 +534,7 @@ const $reversiGamesRepository: Provider = { $swSubscriptionsRepository, $hashtagsRepository, $abuseUserReportsRepository, + $abuseReportNotificationRecipientRepository, $registrationTicketsRepository, $authSessionsRepository, $accessTokensRepository, @@ -472,6 +556,7 @@ const $reversiGamesRepository: Provider = { $channelFavoritesRepository, $registryItemsRepository, $webhooksRepository, + $systemWebhooksRepository, $adsRepository, $passwordResetRequestsRepository, $retentionAggregationsRepository, @@ -520,6 +605,7 @@ const $reversiGamesRepository: Provider = { $swSubscriptionsRepository, $hashtagsRepository, $abuseUserReportsRepository, + $abuseReportNotificationRecipientRepository, $registrationTicketsRepository, $authSessionsRepository, $accessTokensRepository, @@ -541,6 +627,7 @@ const $reversiGamesRepository: Provider = { $channelFavoritesRepository, $registryItemsRepository, $webhooksRepository, + $systemWebhooksRepository, $adsRepository, $passwordResetRequestsRepository, $retentionAggregationsRepository, @@ -553,4 +640,5 @@ const $reversiGamesRepository: Provider = { $reversiGamesRepository, ], }) -export class RepositoryModule {} +export class RepositoryModule { +} diff --git a/packages/backend/src/models/SystemWebhook.ts b/packages/backend/src/models/SystemWebhook.ts new file mode 100644 index 0000000000..86fb323d1d --- /dev/null +++ b/packages/backend/src/models/SystemWebhook.ts @@ -0,0 +1,98 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Column, Entity, Index, PrimaryColumn } from 'typeorm'; +import { Serialized } from '@/types.js'; +import { id } from './util/id.js'; + +export const systemWebhookEventTypes = [ + // ユーザからの通報を受けたとき + 'abuseReport', + // 通報を処理したとき + 'abuseReportResolved', +] as const; +export type SystemWebhookEventType = typeof systemWebhookEventTypes[number]; + +@Entity('system_webhook') +export class MiSystemWebhook { + @PrimaryColumn(id()) + public id: string; + + /** + * 有効かどうか. + */ + @Index('IDX_system_webhook_isActive', { synchronize: false }) + @Column('boolean', { + default: true, + }) + public isActive: boolean; + + /** + * 更新日時. + */ + @Column('timestamp with time zone', { + default: () => 'CURRENT_TIMESTAMP', + }) + public updatedAt: Date; + + /** + * 最後に送信された日時. + */ + @Column('timestamp with time zone', { + nullable: true, + }) + public latestSentAt: Date | null; + + /** + * 最後に送信されたステータスコード + */ + @Column('integer', { + nullable: true, + }) + public latestStatus: number | null; + + /** + * 通知設定名. + */ + @Column('varchar', { + length: 255, + }) + public name: string; + + /** + * イベント種別. + */ + @Index('IDX_system_webhook_on', { synchronize: false }) + @Column('varchar', { + length: 128, + array: true, + default: '{}', + }) + public on: SystemWebhookEventType[]; + + /** + * Webhook送信先のURL. + */ + @Column('varchar', { + length: 1024, + }) + public url: string; + + /** + * Webhook検証用の値. + */ + @Column('varchar', { + length: 1024, + }) + public secret: string; + + static deserialize(obj: Serialized): MiSystemWebhook { + return { + ...obj, + updatedAt: new Date(obj.updatedAt), + latestSentAt: obj.latestSentAt ? new Date(obj.latestSentAt) : null, + }; + } +} diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 2e6a41586e..d366ce48d0 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -11,6 +11,7 @@ import { RawSqlResultsToEntityTransformer } from 'typeorm/query-builder/transfor import { ObjectUtils } from 'typeorm/util/ObjectUtils.js'; import { OrmUtils } from 'typeorm/util/OrmUtils.js'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; +import { MiAbuseReportNotificationRecipient } from '@/models/AbuseReportNotificationRecipient.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; import { MiAnnouncement } from '@/models/Announcement.js'; @@ -68,6 +69,7 @@ import { MiUserPublickey } from '@/models/UserPublickey.js'; import { MiUserSecurityKey } from '@/models/UserSecurityKey.js'; import { MiUserMemo } from '@/models/UserMemo.js'; import { MiWebhook } from '@/models/Webhook.js'; +import { MiSystemWebhook } from '@/models/SystemWebhook.js'; import { MiChannel } from '@/models/Channel.js'; import { MiRetentionAggregation } from '@/models/RetentionAggregation.js'; import { MiRole } from '@/models/Role.js'; @@ -144,6 +146,7 @@ export const miRepository = { export { MiAbuseUserReport, + MiAbuseReportNotificationRecipient, MiAccessToken, MiAd, MiAnnouncement, @@ -201,6 +204,7 @@ export { MiUserPublickey, MiUserSecurityKey, MiWebhook, + MiSystemWebhook, MiChannel, MiRetentionAggregation, MiRole, @@ -213,6 +217,7 @@ export { }; export type AbuseUserReportsRepository = Repository & MiRepository; +export type AbuseReportNotificationRecipientRepository = Repository & MiRepository; export type AccessTokensRepository = Repository & MiRepository; export type AdsRepository = Repository & MiRepository; export type AnnouncementsRepository = Repository & MiRepository; @@ -270,6 +275,7 @@ export type UserProfilesRepository = Repository & MiRepository & MiRepository; export type UserSecurityKeysRepository = Repository & MiRepository; export type WebhooksRepository = Repository & MiRepository; +export type SystemWebhooksRepository = Repository & MiRepository; export type ChannelsRepository = Repository & MiRepository; export type RetentionAggregationsRepository = Repository & MiRepository; export type RolesRepository = Repository & MiRepository; diff --git a/packages/backend/src/models/json-schema/abuse-report-notification-recipient.ts b/packages/backend/src/models/json-schema/abuse-report-notification-recipient.ts new file mode 100644 index 0000000000..6215f0f5a2 --- /dev/null +++ b/packages/backend/src/models/json-schema/abuse-report-notification-recipient.ts @@ -0,0 +1,50 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +export const packedAbuseReportNotificationRecipientSchema = { + type: 'object', + properties: { + id: { + type: 'string', + optional: false, nullable: false, + }, + isActive: { + type: 'boolean', + optional: false, nullable: false, + }, + updatedAt: { + type: 'string', + format: 'date-time', + optional: false, nullable: false, + }, + name: { + type: 'string', + optional: false, nullable: false, + }, + method: { + type: 'string', + optional: false, nullable: false, + enum: ['email', 'webhook'], + }, + userId: { + type: 'string', + optional: true, nullable: false, + }, + user: { + type: 'object', + optional: true, nullable: false, + ref: 'UserLite', + }, + systemWebhookId: { + type: 'string', + optional: true, nullable: false, + }, + systemWebhook: { + type: 'object', + optional: true, nullable: false, + ref: 'SystemWebhook', + }, + }, +} as const; diff --git a/packages/backend/src/models/json-schema/system-webhook.ts b/packages/backend/src/models/json-schema/system-webhook.ts new file mode 100644 index 0000000000..d83065a743 --- /dev/null +++ b/packages/backend/src/models/json-schema/system-webhook.ts @@ -0,0 +1,54 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; + +export const packedSystemWebhookSchema = { + type: 'object', + properties: { + id: { + type: 'string', + optional: false, nullable: false, + }, + isActive: { + type: 'boolean', + optional: false, nullable: false, + }, + updatedAt: { + type: 'string', + format: 'date-time', + optional: false, nullable: false, + }, + latestSentAt: { + type: 'string', + format: 'date-time', + optional: false, nullable: true, + }, + latestStatus: { + type: 'number', + optional: false, nullable: true, + }, + name: { + type: 'string', + optional: false, nullable: false, + }, + on: { + type: 'array', + items: { + type: 'string', + optional: false, nullable: false, + enum: systemWebhookEventTypes, + }, + }, + url: { + type: 'string', + optional: false, nullable: false, + }, + secret: { + type: 'string', + optional: false, nullable: false, + }, + }, +} as const; diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index aa2aa5e373..251a03c303 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -5,13 +5,12 @@ // https://github.com/typeorm/typeorm/issues/2400 import pg from 'pg'; -pg.types.setTypeParser(20, Number); - import { DataSource, Logger } from 'typeorm'; import * as highlight from 'cli-highlight'; import { entities as charts } from '@/core/chart/entities.js'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; +import { MiAbuseReportNotificationRecipient } from '@/models/AbuseReportNotificationRecipient.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; import { MiAnnouncement } from '@/models/Announcement.js'; @@ -69,6 +68,7 @@ import { MiUserProfile } from '@/models/UserProfile.js'; import { MiUserPublickey } from '@/models/UserPublickey.js'; import { MiUserSecurityKey } from '@/models/UserSecurityKey.js'; import { MiWebhook } from '@/models/Webhook.js'; +import { MiSystemWebhook } from '@/models/SystemWebhook.js'; import { MiChannel } from '@/models/Channel.js'; import { MiRetentionAggregation } from '@/models/RetentionAggregation.js'; import { MiRole } from '@/models/Role.js'; @@ -83,6 +83,8 @@ import { Config } from '@/config.js'; import MisskeyLogger from '@/logger.js'; import { bindThis } from '@/decorators.js'; +pg.types.setTypeParser(20, Number); + export const dbLogger = new MisskeyLogger('db'); const sqlLogger = dbLogger.createSubLogger('sql', 'gray'); @@ -167,6 +169,7 @@ export const entities = [ MiHashtag, MiSwSubscription, MiAbuseUserReport, + MiAbuseReportNotificationRecipient, MiRegistrationTicket, MiSignin, MiModerationLog, @@ -185,6 +188,7 @@ export const entities = [ MiPasswordResetRequest, MiUserPending, MiWebhook, + MiSystemWebhook, MiUserIp, MiRetentionAggregation, MiRole, diff --git a/packages/backend/src/queue/QueueProcessorModule.ts b/packages/backend/src/queue/QueueProcessorModule.ts index 8086158997..a1fd38fcc5 100644 --- a/packages/backend/src/queue/QueueProcessorModule.ts +++ b/packages/backend/src/queue/QueueProcessorModule.ts @@ -11,7 +11,8 @@ import { QueueProcessorService } from './QueueProcessorService.js'; import { DeliverProcessorService } from './processors/DeliverProcessorService.js'; import { EndedPollNotificationProcessorService } from './processors/EndedPollNotificationProcessorService.js'; import { InboxProcessorService } from './processors/InboxProcessorService.js'; -import { WebhookDeliverProcessorService } from './processors/WebhookDeliverProcessorService.js'; +import { UserWebhookDeliverProcessorService } from './processors/UserWebhookDeliverProcessorService.js'; +import { SystemWebhookDeliverProcessorService } from './processors/SystemWebhookDeliverProcessorService.js'; import { CheckExpiredMutingsProcessorService } from './processors/CheckExpiredMutingsProcessorService.js'; import { CleanChartsProcessorService } from './processors/CleanChartsProcessorService.js'; import { CleanProcessorService } from './processors/CleanProcessorService.js'; @@ -71,7 +72,8 @@ import { RelationshipProcessorService } from './processors/RelationshipProcessor DeleteFileProcessorService, CleanRemoteFilesProcessorService, RelationshipProcessorService, - WebhookDeliverProcessorService, + UserWebhookDeliverProcessorService, + SystemWebhookDeliverProcessorService, EndedPollNotificationProcessorService, DeliverProcessorService, InboxProcessorService, diff --git a/packages/backend/src/queue/QueueProcessorService.ts b/packages/backend/src/queue/QueueProcessorService.ts index 7bfe1f4caa..7bd74f3210 100644 --- a/packages/backend/src/queue/QueueProcessorService.ts +++ b/packages/backend/src/queue/QueueProcessorService.ts @@ -10,7 +10,8 @@ import type { Config } from '@/config.js'; import { DI } from '@/di-symbols.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; -import { WebhookDeliverProcessorService } from './processors/WebhookDeliverProcessorService.js'; +import { UserWebhookDeliverProcessorService } from './processors/UserWebhookDeliverProcessorService.js'; +import { SystemWebhookDeliverProcessorService } from './processors/SystemWebhookDeliverProcessorService.js'; import { EndedPollNotificationProcessorService } from './processors/EndedPollNotificationProcessorService.js'; import { DeliverProcessorService } from './processors/DeliverProcessorService.js'; import { InboxProcessorService } from './processors/InboxProcessorService.js'; @@ -76,7 +77,8 @@ export class QueueProcessorService implements OnApplicationShutdown { private dbQueueWorker: Bull.Worker; private deliverQueueWorker: Bull.Worker; private inboxQueueWorker: Bull.Worker; - private webhookDeliverQueueWorker: Bull.Worker; + private userWebhookDeliverQueueWorker: Bull.Worker; + private systemWebhookDeliverQueueWorker: Bull.Worker; private relationshipQueueWorker: Bull.Worker; private objectStorageQueueWorker: Bull.Worker; private endedPollNotificationQueueWorker: Bull.Worker; @@ -86,7 +88,8 @@ export class QueueProcessorService implements OnApplicationShutdown { private config: Config, private queueLoggerService: QueueLoggerService, - private webhookDeliverProcessorService: WebhookDeliverProcessorService, + private userWebhookDeliverProcessorService: UserWebhookDeliverProcessorService, + private systemWebhookDeliverProcessorService: SystemWebhookDeliverProcessorService, private endedPollNotificationProcessorService: EndedPollNotificationProcessorService, private deliverProcessorService: DeliverProcessorService, private inboxProcessorService: InboxProcessorService, @@ -160,13 +163,13 @@ export class QueueProcessorService implements OnApplicationShutdown { autorun: false, }); - const systemLogger = this.logger.createSubLogger('system'); + const logger = this.logger.createSubLogger('system'); this.systemQueueWorker - .on('active', (job) => systemLogger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => systemLogger.debug(`completed(${result}) id=${job.id}`)) + .on('active', (job) => logger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err: Error) => { - systemLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: System: ${job?.name ?? '?'}: ${err.message}`, { level: 'error', @@ -174,8 +177,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => systemLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => systemLogger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -217,13 +220,13 @@ export class QueueProcessorService implements OnApplicationShutdown { autorun: false, }); - const dbLogger = this.logger.createSubLogger('db'); + const logger = this.logger.createSubLogger('db'); this.dbQueueWorker - .on('active', (job) => dbLogger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => dbLogger.debug(`completed(${result}) id=${job.id}`)) + .on('active', (job) => logger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - dbLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: DB: ${job?.name ?? '?'}: ${err.message}`, { level: 'error', @@ -231,8 +234,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => dbLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => dbLogger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -257,13 +260,13 @@ export class QueueProcessorService implements OnApplicationShutdown { }, }); - const deliverLogger = this.logger.createSubLogger('deliver'); + const logger = this.logger.createSubLogger('deliver'); this.deliverQueueWorker - .on('active', (job) => deliverLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('completed', (job, result) => deliverLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) .on('failed', (job, err) => { - deliverLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Deliver: ${err.message}`, { level: 'error', @@ -271,8 +274,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => deliverLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => deliverLogger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -297,13 +300,13 @@ export class QueueProcessorService implements OnApplicationShutdown { }, }); - const inboxLogger = this.logger.createSubLogger('inbox'); + const logger = this.logger.createSubLogger('inbox'); this.inboxQueueWorker - .on('active', (job) => inboxLogger.debug(`active ${getJobInfo(job, true)}`)) - .on('completed', (job, result) => inboxLogger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) + .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)}`)) + .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)}`)) .on('failed', (job, err) => { - inboxLogger.error(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.stack}) ${getJobInfo(job)} activity=${job ? (job.data.activity ? job.data.activity.id : 'none') : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Inbox: ${err.message}`, { level: 'error', @@ -311,21 +314,21 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => inboxLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => inboxLogger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion - //#region webhook deliver + //#region user-webhook deliver { - this.webhookDeliverQueueWorker = new Bull.Worker(QUEUE.WEBHOOK_DELIVER, (job) => { + this.userWebhookDeliverQueueWorker = new Bull.Worker(QUEUE.USER_WEBHOOK_DELIVER, (job) => { if (this.config.sentryForBackend) { - return Sentry.startSpan({ name: 'Queue: WebhookDeliver' }, () => this.webhookDeliverProcessorService.process(job)); + return Sentry.startSpan({ name: 'Queue: UserWebhookDeliver' }, () => this.userWebhookDeliverProcessorService.process(job)); } else { - return this.webhookDeliverProcessorService.process(job); + return this.userWebhookDeliverProcessorService.process(job); } }, { - ...baseQueueOptions(this.config, QUEUE.WEBHOOK_DELIVER), + ...baseQueueOptions(this.config, QUEUE.USER_WEBHOOK_DELIVER), autorun: false, concurrency: 64, limiter: { @@ -337,22 +340,62 @@ export class QueueProcessorService implements OnApplicationShutdown { }, }); - const webhookLogger = this.logger.createSubLogger('webhook'); + const logger = this.logger.createSubLogger('user-webhook'); - this.webhookDeliverQueueWorker - .on('active', (job) => webhookLogger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) - .on('completed', (job, result) => webhookLogger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) + this.userWebhookDeliverQueueWorker + .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) .on('failed', (job, err) => { - webhookLogger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); if (config.sentryForBackend) { - Sentry.captureMessage(`Queue: WebhookDeliver: ${err.message}`, { + Sentry.captureMessage(`Queue: UserWebhookDeliver: ${err.message}`, { level: 'error', extra: { job, err }, }); } }) - .on('error', (err: Error) => webhookLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => webhookLogger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); + } + //#endregion + + //#region system-webhook deliver + { + this.systemWebhookDeliverQueueWorker = new Bull.Worker(QUEUE.SYSTEM_WEBHOOK_DELIVER, (job) => { + if (this.config.sentryForBackend) { + return Sentry.startSpan({ name: 'Queue: SystemWebhookDeliver' }, () => this.systemWebhookDeliverProcessorService.process(job)); + } else { + return this.systemWebhookDeliverProcessorService.process(job); + } + }, { + ...baseQueueOptions(this.config, QUEUE.SYSTEM_WEBHOOK_DELIVER), + autorun: false, + concurrency: 16, + limiter: { + max: 16, + duration: 1000, + }, + settings: { + backoffStrategy: httpRelatedBackoff, + }, + }); + + const logger = this.logger.createSubLogger('system-webhook'); + + this.systemWebhookDeliverQueueWorker + .on('active', (job) => logger.debug(`active ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('completed', (job, result) => logger.debug(`completed(${result}) ${getJobInfo(job, true)} to=${job.data.to}`)) + .on('failed', (job, err) => { + logger.error(`failed(${err.stack}) ${getJobInfo(job)} to=${job ? job.data.to : '-'}`); + if (config.sentryForBackend) { + Sentry.captureMessage(`Queue: SystemWebhookDeliver: ${err.message}`, { + level: 'error', + extra: { job, err }, + }); + } + }) + .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -384,13 +427,13 @@ export class QueueProcessorService implements OnApplicationShutdown { }, }); - const relationshipLogger = this.logger.createSubLogger('relationship'); + const logger = this.logger.createSubLogger('relationship'); this.relationshipQueueWorker - .on('active', (job) => relationshipLogger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => relationshipLogger.debug(`completed(${result}) id=${job.id}`)) + .on('active', (job) => logger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - relationshipLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: Relationship: ${job?.name ?? '?'}: ${err.message}`, { level: 'error', @@ -398,8 +441,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => relationshipLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => relationshipLogger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -425,13 +468,13 @@ export class QueueProcessorService implements OnApplicationShutdown { concurrency: 16, }); - const objectStorageLogger = this.logger.createSubLogger('objectStorage'); + const logger = this.logger.createSubLogger('objectStorage'); this.objectStorageQueueWorker - .on('active', (job) => objectStorageLogger.debug(`active id=${job.id}`)) - .on('completed', (job, result) => objectStorageLogger.debug(`completed(${result}) id=${job.id}`)) + .on('active', (job) => logger.debug(`active id=${job.id}`)) + .on('completed', (job, result) => logger.debug(`completed(${result}) id=${job.id}`)) .on('failed', (job, err) => { - objectStorageLogger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); + logger.error(`failed(${err.stack}) id=${job ? job.id : '-'}`, { job, e: renderError(err) }); if (config.sentryForBackend) { Sentry.captureMessage(`Queue: ObjectStorage: ${job?.name ?? '?'}: ${err.message}`, { level: 'error', @@ -439,8 +482,8 @@ export class QueueProcessorService implements OnApplicationShutdown { }); } }) - .on('error', (err: Error) => objectStorageLogger.error(`error ${err.stack}`, { e: renderError(err) })) - .on('stalled', (jobId) => objectStorageLogger.warn(`stalled id=${jobId}`)); + .on('error', (err: Error) => logger.error(`error ${err.stack}`, { e: renderError(err) })) + .on('stalled', (jobId) => logger.warn(`stalled id=${jobId}`)); } //#endregion @@ -467,7 +510,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.dbQueueWorker.run(), this.deliverQueueWorker.run(), this.inboxQueueWorker.run(), - this.webhookDeliverQueueWorker.run(), + this.userWebhookDeliverQueueWorker.run(), + this.systemWebhookDeliverQueueWorker.run(), this.relationshipQueueWorker.run(), this.objectStorageQueueWorker.run(), this.endedPollNotificationQueueWorker.run(), @@ -481,7 +525,8 @@ export class QueueProcessorService implements OnApplicationShutdown { this.dbQueueWorker.close(), this.deliverQueueWorker.close(), this.inboxQueueWorker.close(), - this.webhookDeliverQueueWorker.close(), + this.userWebhookDeliverQueueWorker.close(), + this.systemWebhookDeliverQueueWorker.close(), this.relationshipQueueWorker.close(), this.objectStorageQueueWorker.close(), this.endedPollNotificationQueueWorker.close(), diff --git a/packages/backend/src/queue/const.ts b/packages/backend/src/queue/const.ts index 132e916612..67f689b618 100644 --- a/packages/backend/src/queue/const.ts +++ b/packages/backend/src/queue/const.ts @@ -14,7 +14,8 @@ export const QUEUE = { DB: 'db', RELATIONSHIP: 'relationship', OBJECT_STORAGE: 'objectStorage', - WEBHOOK_DELIVER: 'webhookDeliver', + USER_WEBHOOK_DELIVER: 'userWebhookDeliver', + SYSTEM_WEBHOOK_DELIVER: 'systemWebhookDeliver', }; export function baseQueueOptions(config: Config, queueName: typeof QUEUE[keyof typeof QUEUE]): Bull.QueueOptions { diff --git a/packages/backend/src/queue/processors/SystemWebhookDeliverProcessorService.ts b/packages/backend/src/queue/processors/SystemWebhookDeliverProcessorService.ts new file mode 100644 index 0000000000..f6bef52684 --- /dev/null +++ b/packages/backend/src/queue/processors/SystemWebhookDeliverProcessorService.ts @@ -0,0 +1,87 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import * as Bull from 'bullmq'; +import { DI } from '@/di-symbols.js'; +import type { SystemWebhooksRepository } from '@/models/_.js'; +import type { Config } from '@/config.js'; +import type Logger from '@/logger.js'; +import { HttpRequestService } from '@/core/HttpRequestService.js'; +import { StatusError } from '@/misc/status-error.js'; +import { bindThis } from '@/decorators.js'; +import { QueueLoggerService } from '../QueueLoggerService.js'; +import { SystemWebhookDeliverJobData } from '../types.js'; + +@Injectable() +export class SystemWebhookDeliverProcessorService { + private logger: Logger; + + constructor( + @Inject(DI.config) + private config: Config, + + @Inject(DI.systemWebhooksRepository) + private systemWebhooksRepository: SystemWebhooksRepository, + + private httpRequestService: HttpRequestService, + private queueLoggerService: QueueLoggerService, + ) { + this.logger = this.queueLoggerService.logger.createSubLogger('webhook'); + } + + @bindThis + public async process(job: Bull.Job): Promise { + try { + this.logger.debug(`delivering ${job.data.webhookId}`); + + const res = await this.httpRequestService.send(job.data.to, { + method: 'POST', + headers: { + 'User-Agent': 'Misskey-Hooks', + 'X-Misskey-Host': this.config.host, + 'X-Misskey-Hook-Id': job.data.webhookId, + 'X-Misskey-Hook-Secret': job.data.secret, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + server: this.config.url, + hookId: job.data.webhookId, + eventId: job.data.eventId, + createdAt: job.data.createdAt, + type: job.data.type, + body: job.data.content, + }), + }); + + this.systemWebhooksRepository.update({ id: job.data.webhookId }, { + latestSentAt: new Date(), + latestStatus: res.status, + }); + + return 'Success'; + } catch (res) { + this.logger.error(res as Error); + + this.systemWebhooksRepository.update({ id: job.data.webhookId }, { + latestSentAt: new Date(), + latestStatus: res instanceof StatusError ? res.statusCode : 1, + }); + + if (res instanceof StatusError) { + // 4xx + if (!res.isRetryable) { + throw new Bull.UnrecoverableError(`${res.statusCode} ${res.statusMessage}`); + } + + // 5xx etc. + throw new Error(`${res.statusCode} ${res.statusMessage}`); + } else { + // DNS error, socket error, timeout ... + throw res; + } + } + } +} diff --git a/packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts b/packages/backend/src/queue/processors/UserWebhookDeliverProcessorService.ts similarity index 92% rename from packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts rename to packages/backend/src/queue/processors/UserWebhookDeliverProcessorService.ts index 8c260c0137..9ec630ef70 100644 --- a/packages/backend/src/queue/processors/WebhookDeliverProcessorService.ts +++ b/packages/backend/src/queue/processors/UserWebhookDeliverProcessorService.ts @@ -13,10 +13,10 @@ import { HttpRequestService } from '@/core/HttpRequestService.js'; import { StatusError } from '@/misc/status-error.js'; import { bindThis } from '@/decorators.js'; import { QueueLoggerService } from '../QueueLoggerService.js'; -import type { WebhookDeliverJobData } from '../types.js'; +import { UserWebhookDeliverJobData } from '../types.js'; @Injectable() -export class WebhookDeliverProcessorService { +export class UserWebhookDeliverProcessorService { private logger: Logger; constructor( @@ -33,7 +33,7 @@ export class WebhookDeliverProcessorService { } @bindThis - public async process(job: Bull.Job): Promise { + public async process(job: Bull.Job): Promise { try { this.logger.debug(`delivering ${job.data.webhookId}`); diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index ce57ba745e..a4077a0547 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -106,7 +106,17 @@ export type EndedPollNotificationJobData = { noteId: MiNote['id']; }; -export type WebhookDeliverJobData = { +export type SystemWebhookDeliverJobData = { + type: string; + content: unknown; + webhookId: MiWebhook['id']; + to: string; + secret: string; + createdAt: number; + eventId: string; +}; + +export type UserWebhookDeliverJobData = { type: string; content: unknown; webhookId: MiWebhook['id']; diff --git a/packages/backend/src/server/api/EndpointsModule.ts b/packages/backend/src/server/api/EndpointsModule.ts index c645f4bcc6..41576bedaa 100644 --- a/packages/backend/src/server/api/EndpointsModule.ts +++ b/packages/backend/src/server/api/EndpointsModule.ts @@ -6,8 +6,13 @@ import { Module } from '@nestjs/common'; import { CoreModule } from '@/core/CoreModule.js'; -import * as ep___admin_meta from './endpoints/admin/meta.js'; +import * as ep___admin_abuseReport_notificationRecipient_list from '@/server/api/endpoints/admin/abuse-report/notification-recipient/list.js'; +import * as ep___admin_abuseReport_notificationRecipient_show from '@/server/api/endpoints/admin/abuse-report/notification-recipient/show.js'; +import * as ep___admin_abuseReport_notificationRecipient_create from '@/server/api/endpoints/admin/abuse-report/notification-recipient/create.js'; +import * as ep___admin_abuseReport_notificationRecipient_update from '@/server/api/endpoints/admin/abuse-report/notification-recipient/update.js'; +import * as ep___admin_abuseReport_notificationRecipient_delete from '@/server/api/endpoints/admin/abuse-report/notification-recipient/delete.js'; import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; +import * as ep___admin_meta from './endpoints/admin/meta.js'; import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js'; import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js'; import * as ep___admin_accounts_findByEmail from './endpoints/admin/accounts/find-by-email.js'; @@ -82,6 +87,11 @@ import * as ep___admin_roles_assign from './endpoints/admin/roles/assign.js'; import * as ep___admin_roles_unassign from './endpoints/admin/roles/unassign.js'; import * as ep___admin_roles_updateDefaultPolicies from './endpoints/admin/roles/update-default-policies.js'; import * as ep___admin_roles_users from './endpoints/admin/roles/users.js'; +import * as ep___admin_systemWebhook_create from './endpoints/admin/system-webhook/create.js'; +import * as ep___admin_systemWebhook_delete from './endpoints/admin/system-webhook/delete.js'; +import * as ep___admin_systemWebhook_list from './endpoints/admin/system-webhook/list.js'; +import * as ep___admin_systemWebhook_show from './endpoints/admin/system-webhook/show.js'; +import * as ep___admin_systemWebhook_update from './endpoints/admin/system-webhook/update.js'; import * as ep___announcements from './endpoints/announcements.js'; import * as ep___announcements_show from './endpoints/announcements/show.js'; import * as ep___antennas_create from './endpoints/antennas/create.js'; @@ -381,6 +391,11 @@ import type { Provider } from '@nestjs/common'; const $admin_meta: Provider = { provide: 'ep:admin/meta', useClass: ep___admin_meta.default }; const $admin_abuseUserReports: Provider = { provide: 'ep:admin/abuse-user-reports', useClass: ep___admin_abuseUserReports.default }; +const $admin_abuseReport_notificationRecipient_list: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/list', useClass: ep___admin_abuseReport_notificationRecipient_list.default }; +const $admin_abuseReport_notificationRecipient_show: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/show', useClass: ep___admin_abuseReport_notificationRecipient_show.default }; +const $admin_abuseReport_notificationRecipient_create: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/create', useClass: ep___admin_abuseReport_notificationRecipient_create.default }; +const $admin_abuseReport_notificationRecipient_update: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/update', useClass: ep___admin_abuseReport_notificationRecipient_update.default }; +const $admin_abuseReport_notificationRecipient_delete: Provider = { provide: 'ep:admin/abuse-report/notification-recipient/delete', useClass: ep___admin_abuseReport_notificationRecipient_delete.default }; const $admin_accounts_create: Provider = { provide: 'ep:admin/accounts/create', useClass: ep___admin_accounts_create.default }; const $admin_accounts_delete: Provider = { provide: 'ep:admin/accounts/delete', useClass: ep___admin_accounts_delete.default }; const $admin_accounts_findByEmail: Provider = { provide: 'ep:admin/accounts/find-by-email', useClass: ep___admin_accounts_findByEmail.default }; @@ -455,6 +470,11 @@ const $admin_roles_assign: Provider = { provide: 'ep:admin/roles/assign', useCla const $admin_roles_unassign: Provider = { provide: 'ep:admin/roles/unassign', useClass: ep___admin_roles_unassign.default }; const $admin_roles_updateDefaultPolicies: Provider = { provide: 'ep:admin/roles/update-default-policies', useClass: ep___admin_roles_updateDefaultPolicies.default }; const $admin_roles_users: Provider = { provide: 'ep:admin/roles/users', useClass: ep___admin_roles_users.default }; +const $admin_systemWebhook_create: Provider = { provide: 'ep:admin/system-webhook/create', useClass: ep___admin_systemWebhook_create.default }; +const $admin_systemWebhook_delete: Provider = { provide: 'ep:admin/system-webhook/delete', useClass: ep___admin_systemWebhook_delete.default }; +const $admin_systemWebhook_list: Provider = { provide: 'ep:admin/system-webhook/list', useClass: ep___admin_systemWebhook_list.default }; +const $admin_systemWebhook_show: Provider = { provide: 'ep:admin/system-webhook/show', useClass: ep___admin_systemWebhook_show.default }; +const $admin_systemWebhook_update: Provider = { provide: 'ep:admin/system-webhook/update', useClass: ep___admin_systemWebhook_update.default }; const $announcements: Provider = { provide: 'ep:announcements', useClass: ep___announcements.default }; const $announcements_show: Provider = { provide: 'ep:announcements/show', useClass: ep___announcements_show.default }; const $antennas_create: Provider = { provide: 'ep:antennas/create', useClass: ep___antennas_create.default }; @@ -758,6 +778,11 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ ApiLoggerService, $admin_meta, $admin_abuseUserReports, + $admin_abuseReport_notificationRecipient_list, + $admin_abuseReport_notificationRecipient_show, + $admin_abuseReport_notificationRecipient_create, + $admin_abuseReport_notificationRecipient_update, + $admin_abuseReport_notificationRecipient_delete, $admin_accounts_create, $admin_accounts_delete, $admin_accounts_findByEmail, @@ -832,6 +857,11 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_roles_unassign, $admin_roles_updateDefaultPolicies, $admin_roles_users, + $admin_systemWebhook_create, + $admin_systemWebhook_delete, + $admin_systemWebhook_list, + $admin_systemWebhook_show, + $admin_systemWebhook_update, $announcements, $announcements_show, $antennas_create, @@ -1129,6 +1159,11 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ exports: [ $admin_meta, $admin_abuseUserReports, + $admin_abuseReport_notificationRecipient_list, + $admin_abuseReport_notificationRecipient_show, + $admin_abuseReport_notificationRecipient_create, + $admin_abuseReport_notificationRecipient_update, + $admin_abuseReport_notificationRecipient_delete, $admin_accounts_create, $admin_accounts_delete, $admin_accounts_findByEmail, @@ -1203,6 +1238,11 @@ const $reversi_verify: Provider = { provide: 'ep:reversi/verify', useClass: ep__ $admin_roles_unassign, $admin_roles_updateDefaultPolicies, $admin_roles_users, + $admin_systemWebhook_create, + $admin_systemWebhook_delete, + $admin_systemWebhook_list, + $admin_systemWebhook_show, + $admin_systemWebhook_update, $announcements, $announcements_show, $antennas_create, diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index a38c62f35a..3dfb7fdad4 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -6,8 +6,18 @@ import { permissions } from 'misskey-js'; import type { KeyOf, Schema } from '@/misc/json-schema.js'; -import * as ep___admin_meta from './endpoints/admin/meta.js'; +import * as ep___admin_abuseReport_notificationRecipient_list + from '@/server/api/endpoints/admin/abuse-report/notification-recipient/list.js'; +import * as ep___admin_abuseReport_notificationRecipient_show + from '@/server/api/endpoints/admin/abuse-report/notification-recipient/show.js'; +import * as ep___admin_abuseReport_notificationRecipient_create + from '@/server/api/endpoints/admin/abuse-report/notification-recipient/create.js'; +import * as ep___admin_abuseReport_notificationRecipient_update + from '@/server/api/endpoints/admin/abuse-report/notification-recipient/update.js'; +import * as ep___admin_abuseReport_notificationRecipient_delete + from '@/server/api/endpoints/admin/abuse-report/notification-recipient/delete.js'; import * as ep___admin_abuseUserReports from './endpoints/admin/abuse-user-reports.js'; +import * as ep___admin_meta from './endpoints/admin/meta.js'; import * as ep___admin_accounts_create from './endpoints/admin/accounts/create.js'; import * as ep___admin_accounts_delete from './endpoints/admin/accounts/delete.js'; import * as ep___admin_accounts_findByEmail from './endpoints/admin/accounts/find-by-email.js'; @@ -44,7 +54,8 @@ import * as ep___admin_emoji_setCategoryBulk from './endpoints/admin/emoji/set-c import * as ep___admin_emoji_setLicenseBulk from './endpoints/admin/emoji/set-license-bulk.js'; import * as ep___admin_emoji_update from './endpoints/admin/emoji/update.js'; import * as ep___admin_federation_deleteAllFiles from './endpoints/admin/federation/delete-all-files.js'; -import * as ep___admin_federation_refreshRemoteInstanceMetadata from './endpoints/admin/federation/refresh-remote-instance-metadata.js'; +import * as ep___admin_federation_refreshRemoteInstanceMetadata + from './endpoints/admin/federation/refresh-remote-instance-metadata.js'; import * as ep___admin_federation_removeAllFollowing from './endpoints/admin/federation/remove-all-following.js'; import * as ep___admin_federation_updateInstance from './endpoints/admin/federation/update-instance.js'; import * as ep___admin_getIndexStats from './endpoints/admin/get-index-stats.js'; @@ -82,6 +93,11 @@ import * as ep___admin_roles_assign from './endpoints/admin/roles/assign.js'; import * as ep___admin_roles_unassign from './endpoints/admin/roles/unassign.js'; import * as ep___admin_roles_updateDefaultPolicies from './endpoints/admin/roles/update-default-policies.js'; import * as ep___admin_roles_users from './endpoints/admin/roles/users.js'; +import * as ep___admin_systemWebhook_create from './endpoints/admin/system-webhook/create.js'; +import * as ep___admin_systemWebhook_delete from './endpoints/admin/system-webhook/delete.js'; +import * as ep___admin_systemWebhook_list from './endpoints/admin/system-webhook/list.js'; +import * as ep___admin_systemWebhook_show from './endpoints/admin/system-webhook/show.js'; +import * as ep___admin_systemWebhook_update from './endpoints/admin/system-webhook/update.js'; import * as ep___announcements from './endpoints/announcements.js'; import * as ep___announcements_show from './endpoints/announcements/show.js'; import * as ep___antennas_create from './endpoints/antennas/create.js'; @@ -379,6 +395,11 @@ import * as ep___reversi_verify from './endpoints/reversi/verify.js'; const eps = [ ['admin/meta', ep___admin_meta], ['admin/abuse-user-reports', ep___admin_abuseUserReports], + ['admin/abuse-report/notification-recipient/list', ep___admin_abuseReport_notificationRecipient_list], + ['admin/abuse-report/notification-recipient/show', ep___admin_abuseReport_notificationRecipient_show], + ['admin/abuse-report/notification-recipient/create', ep___admin_abuseReport_notificationRecipient_create], + ['admin/abuse-report/notification-recipient/update', ep___admin_abuseReport_notificationRecipient_update], + ['admin/abuse-report/notification-recipient/delete', ep___admin_abuseReport_notificationRecipient_delete], ['admin/accounts/create', ep___admin_accounts_create], ['admin/accounts/delete', ep___admin_accounts_delete], ['admin/accounts/find-by-email', ep___admin_accounts_findByEmail], @@ -453,6 +474,11 @@ const eps = [ ['admin/roles/unassign', ep___admin_roles_unassign], ['admin/roles/update-default-policies', ep___admin_roles_updateDefaultPolicies], ['admin/roles/users', ep___admin_roles_users], + ['admin/system-webhook/create', ep___admin_systemWebhook_create], + ['admin/system-webhook/delete', ep___admin_systemWebhook_delete], + ['admin/system-webhook/list', ep___admin_systemWebhook_list], + ['admin/system-webhook/show', ep___admin_systemWebhook_show], + ['admin/system-webhook/update', ep___admin_systemWebhook_update], ['announcements', ep___announcements], ['announcements/show', ep___announcements_show], ['antennas/create', ep___antennas_create], @@ -873,8 +899,12 @@ export interface IEndpoint { const endpoints: IEndpoint[] = (eps as [string, any]).map(([name, ep]) => { return { name: name, - get meta() { return ep.meta ?? {}; }, - get params() { return ep.paramDef; }, + get meta() { + return ep.meta ?? {}; + }, + get params() { + return ep.paramDef; + }, }; }); diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts new file mode 100644 index 0000000000..bdfbcba518 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts @@ -0,0 +1,122 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { ApiError } from '@/server/api/error.js'; +import { + AbuseReportNotificationRecipientEntityService, +} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; +import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; +import { DI } from '@/di-symbols.js'; +import type { UserProfilesRepository } from '@/models/_.js'; + +export const meta = { + tags: ['admin', 'abuse-report', 'notification-recipient'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'write:admin:abuse-report:notification-recipient', + + res: { + type: 'object', + ref: 'AbuseReportNotificationRecipient', + }, + + errors: { + correlationCheckEmail: { + message: 'If "method" is email, "userId" must be set.', + code: 'CORRELATION_CHECK_EMAIL', + id: '348bb8ae-575a-6fe9-4327-5811999def8f', + httpStatusCode: 400, + }, + correlationCheckWebhook: { + message: 'If "method" is webhook, "systemWebhookId" must be set.', + code: 'CORRELATION_CHECK_WEBHOOK', + id: 'b0c15051-de2d-29ef-260c-9585cddd701a', + httpStatusCode: 400, + }, + emailAddressNotSet: { + message: 'Email address is not set.', + code: 'EMAIL_ADDRESS_NOT_SET', + id: '7cc1d85e-2f58-fc31-b644-3de8d0d3421f', + httpStatusCode: 400, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + isActive: { + type: 'boolean', + }, + name: { + type: 'string', + minLength: 1, + maxLength: 255, + }, + method: { + type: 'string', + enum: ['email', 'webhook'], + }, + userId: { + type: 'string', + format: 'misskey:id', + }, + systemWebhookId: { + type: 'string', + format: 'misskey:id', + }, + }, + required: [ + 'isActive', + 'name', + 'method', + ], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + @Inject(DI.userProfilesRepository) + private userProfilesRepository: UserProfilesRepository, + private abuseReportNotificationService: AbuseReportNotificationService, + private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService, + ) { + super(meta, paramDef, async (ps, me) => { + if (ps.method === 'email') { + const userProfile = await this.userProfilesRepository.findOneBy({ userId: ps.userId }); + if (!ps.userId || !userProfile) { + throw new ApiError(meta.errors.correlationCheckEmail); + } + + if (!userProfile.email || !userProfile.emailVerified) { + throw new ApiError(meta.errors.emailAddressNotSet); + } + } + + if (ps.method === 'webhook' && !ps.systemWebhookId) { + throw new ApiError(meta.errors.correlationCheckWebhook); + } + + const userId = ps.method === 'email' ? ps.userId : null; + const systemWebhookId = ps.method === 'webhook' ? ps.systemWebhookId : null; + const result = await this.abuseReportNotificationService.createRecipient( + { + isActive: ps.isActive, + name: ps.name, + method: ps.method, + userId: userId ?? null, + systemWebhookId: systemWebhookId ?? null, + }, + me, + ); + + return this.abuseReportNotificationRecipientEntityService.pack(result); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts new file mode 100644 index 0000000000..b6dc44e09c --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; + +export const meta = { + tags: ['admin', 'abuse-report', 'notification-recipient'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'write:admin:abuse-report:notification-recipient', +} as const; + +export const paramDef = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'misskey:id', + }, + }, + required: [ + 'id', + ], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private abuseReportNotificationService: AbuseReportNotificationService, + ) { + super(meta, paramDef, async (ps, me) => { + await this.abuseReportNotificationService.deleteRecipient( + ps.id, + me, + ); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts new file mode 100644 index 0000000000..dad9161a8a --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts @@ -0,0 +1,55 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { + AbuseReportNotificationRecipientEntityService, +} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; +import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; + +export const meta = { + tags: ['admin', 'abuse-report', 'notification-recipient'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'read:admin:abuse-report:notification-recipient', + + res: { + type: 'array', + items: { + type: 'object', + ref: 'AbuseReportNotificationRecipient', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + method: { + type: 'array', + items: { + type: 'string', + enum: ['email', 'webhook'], + }, + }, + }, + required: [], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private abuseReportNotificationService: AbuseReportNotificationService, + private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService, + ) { + super(meta, paramDef, async (ps) => { + const recipients = await this.abuseReportNotificationService.fetchRecipients({ method: ps.method }); + return this.abuseReportNotificationRecipientEntityService.packMany(recipients); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts new file mode 100644 index 0000000000..557798f946 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts @@ -0,0 +1,64 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { + AbuseReportNotificationRecipientEntityService, +} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; +import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; +import { ApiError } from '@/server/api/error.js'; + +export const meta = { + tags: ['admin', 'abuse-report', 'notification-recipient'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'read:admin:abuse-report:notification-recipient', + + res: { + type: 'object', + ref: 'AbuseReportNotificationRecipient', + }, + + errors: { + noSuchRecipient: { + message: 'No such recipient.', + code: 'NO_SUCH_RECIPIENT', + id: '013de6a8-f757-04cb-4d73-cc2a7e3368e4', + kind: 'server', + httpStatusCode: 404, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'misskey:id', + }, + }, + required: ['id'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private abuseReportNotificationService: AbuseReportNotificationService, + private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService, + ) { + super(meta, paramDef, async (ps) => { + const recipients = await this.abuseReportNotificationService.fetchRecipients({ ids: [ps.id] }); + if (recipients.length === 0) { + throw new ApiError(meta.errors.noSuchRecipient); + } + + return this.abuseReportNotificationRecipientEntityService.pack(recipients[0]); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts new file mode 100644 index 0000000000..bd4b485217 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts @@ -0,0 +1,128 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Inject, Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { ApiError } from '@/server/api/error.js'; +import { + AbuseReportNotificationRecipientEntityService, +} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js'; +import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; +import { DI } from '@/di-symbols.js'; +import type { UserProfilesRepository } from '@/models/_.js'; + +export const meta = { + tags: ['admin', 'abuse-report', 'notification-recipient'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'write:admin:abuse-report:notification-recipient', + + res: { + type: 'object', + ref: 'AbuseReportNotificationRecipient', + }, + + errors: { + correlationCheckEmail: { + message: 'If "method" is email, "userId" must be set.', + code: 'CORRELATION_CHECK_EMAIL', + id: '348bb8ae-575a-6fe9-4327-5811999def8f', + httpStatusCode: 400, + }, + correlationCheckWebhook: { + message: 'If "method" is webhook, "systemWebhookId" must be set.', + code: 'CORRELATION_CHECK_WEBHOOK', + id: 'b0c15051-de2d-29ef-260c-9585cddd701a', + httpStatusCode: 400, + }, + emailAddressNotSet: { + message: 'Email address is not set.', + code: 'EMAIL_ADDRESS_NOT_SET', + id: '7cc1d85e-2f58-fc31-b644-3de8d0d3421f', + httpStatusCode: 400, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'misskey:id', + }, + isActive: { + type: 'boolean', + }, + name: { + type: 'string', + minLength: 1, + maxLength: 255, + }, + method: { + type: 'string', + enum: ['email', 'webhook'], + }, + userId: { + type: 'string', + format: 'misskey:id', + }, + systemWebhookId: { + type: 'string', + format: 'misskey:id', + }, + }, + required: [ + 'id', + 'isActive', + 'name', + 'method', + ], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + @Inject(DI.userProfilesRepository) + private userProfilesRepository: UserProfilesRepository, + private abuseReportNotificationService: AbuseReportNotificationService, + private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService, + ) { + super(meta, paramDef, async (ps, me) => { + if (ps.method === 'email') { + const userProfile = await this.userProfilesRepository.findOneBy({ userId: ps.userId }); + if (!ps.userId || !userProfile) { + throw new ApiError(meta.errors.correlationCheckEmail); + } + + if (!userProfile.email || !userProfile.emailVerified) { + throw new ApiError(meta.errors.emailAddressNotSet); + } + } + + if (ps.method === 'webhook' && !ps.systemWebhookId) { + throw new ApiError(meta.errors.correlationCheckWebhook); + } + + const userId = ps.method === 'email' ? ps.userId : null; + const systemWebhookId = ps.method === 'webhook' ? ps.systemWebhookId : null; + const result = await this.abuseReportNotificationService.updateRecipient( + { + id: ps.id, + isActive: ps.isActive, + name: ps.name, + method: ps.method, + userId: userId ?? null, + systemWebhookId: systemWebhookId ?? null, + }, + me, + ); + + return this.abuseReportNotificationRecipientEntityService.pack(result); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts index 9694b3fa40..d7f9e4eaa3 100644 --- a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts +++ b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts @@ -5,7 +5,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, WebhookDeliverQueue } from '@/core/QueueModule.js'; +import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, UserWebhookDeliverQueue, SystemWebhookDeliverQueue } from '@/core/QueueModule.js'; export const meta = { tags: ['admin'], @@ -53,7 +53,8 @@ export default class extends Endpoint { // eslint- @Inject('queue:inbox') public inboxQueue: InboxQueue, @Inject('queue:db') public dbQueue: DbQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, - @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, + @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, + @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, ) { super(meta, paramDef, async (ps, me) => { const deliverJobCounts = await this.deliverQueue.getJobCounts(); diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts index 8b0456068b..9b79100fcf 100644 --- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts +++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts @@ -5,12 +5,10 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { UsersRepository, AbuseUserReportsRepository } from '@/models/_.js'; -import { InstanceActorService } from '@/core/InstanceActorService.js'; -import { QueueService } from '@/core/QueueService.js'; -import { ApRendererService } from '@/core/activitypub/ApRendererService.js'; +import type { AbuseUserReportsRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; -import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { ApiError } from '@/server/api/error.js'; +import { AbuseReportService } from '@/core/AbuseReportService.js'; export const meta = { tags: ['admin'], @@ -18,6 +16,16 @@ export const meta = { requireCredential: true, requireModerator: true, kind: 'write:admin:resolve-abuse-user-report', + + errors: { + noSuchAbuseReport: { + message: 'No such abuse report.', + code: 'NO_SUCH_ABUSE_REPORT', + id: 'ac3794dd-2ce4-d878-e546-73c60c06b398', + kind: 'server', + httpStatusCode: 404, + }, + }, } as const; export const paramDef = { @@ -29,47 +37,20 @@ export const paramDef = { required: ['reportId'], } as const; -// TODO: ロジックをサービスに切り出す - @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.usersRepository) - private usersRepository: UsersRepository, - @Inject(DI.abuseUserReportsRepository) private abuseUserReportsRepository: AbuseUserReportsRepository, - - private queueService: QueueService, - private instanceActorService: InstanceActorService, - private apRendererService: ApRendererService, - private moderationLogService: ModerationLogService, + private abuseReportService: AbuseReportService, ) { super(meta, paramDef, async (ps, me) => { const report = await this.abuseUserReportsRepository.findOneBy({ id: ps.reportId }); - - if (report == null) { - throw new Error('report not found'); + if (!report) { + throw new ApiError(meta.errors.noSuchAbuseReport); } - if (ps.forward && report.targetUserHost != null) { - const actor = await this.instanceActorService.getInstanceActor(); - const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); - - this.queueService.deliver(actor, this.apRendererService.addContext(this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment)), targetUser.inbox, false); - } - - await this.abuseUserReportsRepository.update(report.id, { - resolved: true, - assigneeId: me.id, - forwarded: ps.forward && report.targetUserHost != null, - }); - - this.moderationLogService.log(me, 'resolveAbuseReport', { - reportId: report.id, - report: report, - forwarded: ps.forward && report.targetUserHost != null, - }); + await this.abuseReportService.resolve([{ reportId: report.id, forward: ps.forward }], me); }); } } diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts new file mode 100644 index 0000000000..28071e7a33 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts @@ -0,0 +1,85 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; +import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; + +export const meta = { + tags: ['admin', 'system-webhook'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'write:admin:system-webhook', + + res: { + type: 'object', + ref: 'SystemWebhook', + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + isActive: { + type: 'boolean', + }, + name: { + type: 'string', + minLength: 1, + maxLength: 255, + }, + on: { + type: 'array', + items: { + type: 'string', + enum: systemWebhookEventTypes, + }, + }, + url: { + type: 'string', + minLength: 1, + maxLength: 1024, + }, + secret: { + type: 'string', + minLength: 1, + maxLength: 1024, + }, + }, + required: [ + 'isActive', + 'name', + 'on', + 'url', + 'secret', + ], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private systemWebhookService: SystemWebhookService, + private systemWebhookEntityService: SystemWebhookEntityService, + ) { + super(meta, paramDef, async (ps, me) => { + const result = await this.systemWebhookService.createSystemWebhook( + { + isActive: ps.isActive, + name: ps.name, + on: ps.on, + url: ps.url, + secret: ps.secret, + }, + me, + ); + + return this.systemWebhookEntityService.pack(result); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts new file mode 100644 index 0000000000..9cdfc7e70f --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts @@ -0,0 +1,44 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; + +export const meta = { + tags: ['admin', 'system-webhook'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'write:admin:system-webhook', +} as const; + +export const paramDef = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'misskey:id', + }, + }, + required: [ + 'id', + ], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private systemWebhookService: SystemWebhookService, + ) { + super(meta, paramDef, async (ps, me) => { + await this.systemWebhookService.deleteSystemWebhook( + ps.id, + me, + ); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts new file mode 100644 index 0000000000..7a440a774e --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts @@ -0,0 +1,60 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; +import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; + +export const meta = { + tags: ['admin', 'system-webhook'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'write:admin:system-webhook', + + res: { + type: 'array', + items: { + type: 'object', + ref: 'SystemWebhook', + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + isActive: { + type: 'boolean', + }, + on: { + type: 'array', + items: { + type: 'string', + enum: systemWebhookEventTypes, + }, + }, + }, + required: [], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private systemWebhookService: SystemWebhookService, + private systemWebhookEntityService: SystemWebhookEntityService, + ) { + super(meta, paramDef, async (ps) => { + const webhooks = await this.systemWebhookService.fetchSystemWebhooks({ + isActive: ps.isActive, + on: ps.on, + }); + return this.systemWebhookEntityService.packMany(webhooks); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts new file mode 100644 index 0000000000..75862c96a7 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; +import { ApiError } from '@/server/api/error.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; + +export const meta = { + tags: ['admin', 'system-webhook'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'write:admin:system-webhook', + + res: { + type: 'object', + ref: 'SystemWebhook', + }, + + errors: { + noSuchSystemWebhook: { + message: 'No such SystemWebhook.', + code: 'NO_SUCH_SYSTEM_WEBHOOK', + id: '38dd1ffe-04b4-6ff5-d8ba-4e6a6ae22c9d', + kind: 'server', + httpStatusCode: 404, + }, + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'misskey:id', + }, + }, + required: ['id'], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private systemWebhookService: SystemWebhookService, + private systemWebhookEntityService: SystemWebhookEntityService, + ) { + super(meta, paramDef, async (ps) => { + const webhooks = await this.systemWebhookService.fetchSystemWebhooks({ ids: [ps.id] }); + if (webhooks.length === 0) { + throw new ApiError(meta.errors.noSuchSystemWebhook); + } + + return this.systemWebhookEntityService.pack(webhooks[0]); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts new file mode 100644 index 0000000000..8d68bb8f87 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts @@ -0,0 +1,91 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Injectable } from '@nestjs/common'; +import { Endpoint } from '@/server/api/endpoint-base.js'; +import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; +import { systemWebhookEventTypes } from '@/models/SystemWebhook.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; + +export const meta = { + tags: ['admin', 'system-webhook'], + + requireCredential: true, + requireModerator: true, + secure: true, + kind: 'write:admin:system-webhook', + + res: { + type: 'object', + ref: 'SystemWebhook', + }, +} as const; + +export const paramDef = { + type: 'object', + properties: { + id: { + type: 'string', + format: 'misskey:id', + }, + isActive: { + type: 'boolean', + }, + name: { + type: 'string', + minLength: 1, + maxLength: 255, + }, + on: { + type: 'array', + items: { + type: 'string', + enum: systemWebhookEventTypes, + }, + }, + url: { + type: 'string', + minLength: 1, + maxLength: 1024, + }, + secret: { + type: 'string', + minLength: 1, + maxLength: 1024, + }, + }, + required: [ + 'id', + 'isActive', + 'name', + 'on', + 'url', + 'secret', + ], +} as const; + +@Injectable() +export default class extends Endpoint { // eslint-disable-line import/no-default-export + constructor( + private systemWebhookService: SystemWebhookService, + private systemWebhookEntityService: SystemWebhookEntityService, + ) { + super(meta, paramDef, async (ps, me) => { + const result = await this.systemWebhookService.updateSystemWebhook( + { + id: ps.id, + isActive: ps.isActive, + name: ps.name, + on: ps.on, + url: ps.url, + secret: ps.secret, + }, + me, + ); + + return this.systemWebhookEntityService.pack(result); + }); + } +} diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts index 48e14b68cc..5ff6de37d2 100644 --- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts +++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts @@ -3,17 +3,11 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import sanitizeHtml from 'sanitize-html'; -import { Inject, Injectable } from '@nestjs/common'; -import type { AbuseUserReportsRepository } from '@/models/_.js'; -import { IdService } from '@/core/IdService.js'; +import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; -import { MetaService } from '@/core/MetaService.js'; -import { EmailService } from '@/core/EmailService.js'; -import { DI } from '@/di-symbols.js'; import { GetterService } from '@/server/api/GetterService.js'; import { RoleService } from '@/core/RoleService.js'; +import { AbuseReportService } from '@/core/AbuseReportService.js'; import { ApiError } from '../../error.js'; export const meta = { @@ -57,60 +51,32 @@ export const paramDef = { @Injectable() export default class extends Endpoint { // eslint-disable-line import/no-default-export constructor( - @Inject(DI.abuseUserReportsRepository) - private abuseUserReportsRepository: AbuseUserReportsRepository, - - private idService: IdService, - private metaService: MetaService, - private emailService: EmailService, private getterService: GetterService, private roleService: RoleService, - private globalEventService: GlobalEventService, + private abuseReportService: AbuseReportService, ) { super(meta, paramDef, async (ps, me) => { // Lookup user - const user = await this.getterService.getUser(ps.userId).catch(err => { + const targetUser = await this.getterService.getUser(ps.userId).catch(err => { if (err.id === '15348ddd-432d-49c2-8a5a-8069753becff') throw new ApiError(meta.errors.noSuchUser); throw err; }); - if (user.id === me.id) { + if (targetUser.id === me.id) { throw new ApiError(meta.errors.cannotReportYourself); } - if (await this.roleService.isAdministrator(user)) { + if (await this.roleService.isAdministrator(targetUser)) { throw new ApiError(meta.errors.cannotReportAdmin); } - const report = await this.abuseUserReportsRepository.insertOne({ - id: this.idService.gen(), - targetUserId: user.id, - targetUserHost: user.host, + await this.abuseReportService.report([{ + targetUserId: targetUser.id, + targetUserHost: targetUser.host, reporterId: me.id, reporterHost: null, comment: ps.comment, - }); - - // Publish event to moderators - setImmediate(async () => { - const moderators = await this.roleService.getModerators(); - - for (const moderator of moderators) { - this.globalEventService.publishAdminStream(moderator.id, 'newAbuseUserReport', { - id: report.id, - targetUserId: report.targetUserId, - reporterId: report.reporterId, - comment: report.comment, - }); - } - - const meta = await this.metaService.fetch(); - if (meta.email) { - this.emailService.sendEmail(meta.email, 'New abuse report', - sanitizeHtml(ps.comment), - sanitizeHtml(ps.comment)); - } - }); + }]); }); } } diff --git a/packages/backend/src/server/web/ClientServerService.ts b/packages/backend/src/server/web/ClientServerService.ts index ab03489c0d..f55790b636 100644 --- a/packages/backend/src/server/web/ClientServerService.ts +++ b/packages/backend/src/server/web/ClientServerService.ts @@ -25,7 +25,16 @@ import { getNoteSummary } from '@/misc/get-note-summary.js'; import { DI } from '@/di-symbols.js'; import * as Acct from '@/misc/acct.js'; import { MetaService } from '@/core/MetaService.js'; -import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, WebhookDeliverQueue } from '@/core/QueueModule.js'; +import type { + DbQueue, + DeliverQueue, + EndedPollNotificationQueue, + InboxQueue, + ObjectStorageQueue, + SystemQueue, + UserWebhookDeliverQueue, + SystemWebhookDeliverQueue, +} from '@/core/QueueModule.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { PageEntityService } from '@/core/entities/PageEntityService.js'; @@ -111,7 +120,8 @@ export class ClientServerService { @Inject('queue:inbox') public inboxQueue: InboxQueue, @Inject('queue:db') public dbQueue: DbQueue, @Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue, - @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue, + @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue, + @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue, ) { //this.createServer = this.createServer.bind(this); } @@ -239,7 +249,8 @@ export class ClientServerService { this.inboxQueue, this.dbQueue, this.objectStorageQueue, - this.webhookDeliverQueue, + this.userWebhookDeliverQueue, + this.systemWebhookDeliverQueue, ].map(q => new BullMQAdapter(q)), serverAdapter, }); diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts index 929070d0d2..ecbbee4eff 100644 --- a/packages/backend/src/types.ts +++ b/packages/backend/src/types.ts @@ -90,6 +90,12 @@ export const moderationLogTypes = [ 'deleteAvatarDecoration', 'unsetUserAvatar', 'unsetUserBanner', + 'createSystemWebhook', + 'updateSystemWebhook', + 'deleteSystemWebhook', + 'createAbuseReportNotificationRecipient', + 'updateAbuseReportNotificationRecipient', + 'deleteAbuseReportNotificationRecipient', ] as const; export type ModerationLogPayloads = { @@ -282,6 +288,32 @@ export type ModerationLogPayloads = { userHost: string | null; fileId: string; }; + createSystemWebhook: { + systemWebhookId: string; + webhook: any; + }; + updateSystemWebhook: { + systemWebhookId: string; + before: any; + after: any; + }; + deleteSystemWebhook: { + systemWebhookId: string; + webhook: any; + }; + createAbuseReportNotificationRecipient: { + recipientId: string; + recipient: any; + }; + updateAbuseReportNotificationRecipient: { + recipientId: string; + before: any; + after: any; + }; + deleteAbuseReportNotificationRecipient: { + recipientId: string; + recipient: any; + }; }; export type Serialized = { diff --git a/packages/backend/test/e2e/synalio/abuse-report.ts b/packages/backend/test/e2e/synalio/abuse-report.ts new file mode 100644 index 0000000000..b0cc3d13ec --- /dev/null +++ b/packages/backend/test/e2e/synalio/abuse-report.ts @@ -0,0 +1,401 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { entities } from 'misskey-js'; +import { beforeEach, describe, test } from '@jest/globals'; +import Fastify from 'fastify'; +import { api, randomString, role, signup, startJobQueue, UserToken } from '../../utils.js'; +import type { INestApplicationContext } from '@nestjs/common'; + +const WEBHOOK_HOST = 'http://localhost:15080'; +const WEBHOOK_PORT = 15080; +process.env.NODE_ENV = 'test'; + +describe('[シナリオ] ユーザ通報', () => { + let queue: INestApplicationContext; + let admin: entities.SignupResponse; + let alice: entities.SignupResponse; + let bob: entities.SignupResponse; + + type SystemWebhookPayload = { + server: string; + hookId: string; + eventId: string; + createdAt: string; + type: string; + body: any; + } + + // ------------------------------------------------------------------------------------------- + + async function captureWebhook(postAction: () => Promise): Promise { + const fastify = Fastify(); + + let timeoutHandle: NodeJS.Timeout | null = null; + const result = await new Promise(async (resolve, reject) => { + fastify.all('/', async (req, res) => { + timeoutHandle && clearTimeout(timeoutHandle); + + const body = JSON.stringify(req.body); + res.status(200).send('ok'); + await fastify.close(); + resolve(body); + }); + + await fastify.listen({ port: WEBHOOK_PORT }); + + timeoutHandle = setTimeout(async () => { + await fastify.close(); + reject(new Error('timeout')); + }, 3000); + + try { + await postAction(); + } catch (e) { + await fastify.close(); + reject(e); + } + }); + + await fastify.close(); + + return JSON.parse(result) as T; + } + + async function createSystemWebhook(args?: Partial, credential?: UserToken): Promise { + const res = await api( + 'admin/system-webhook/create', + { + isActive: true, + name: randomString(), + on: ['abuseReport'], + url: WEBHOOK_HOST, + secret: randomString(), + ...args, + }, + credential ?? admin, + ); + return res.body; + } + + async function createAbuseReportNotificationRecipient(args?: Partial, credential?: UserToken): Promise { + const res = await api( + 'admin/abuse-report/notification-recipient/create', + { + isActive: true, + name: randomString(), + method: 'webhook', + ...args, + }, + credential ?? admin, + ); + return res.body; + } + + async function createAbuseReport(args?: Partial, credential?: UserToken): Promise { + const res = await api( + 'users/report-abuse', + { + userId: alice.id, + comment: randomString(), + ...args, + }, + credential ?? admin, + ); + return res.body; + } + + async function resolveAbuseReport(args?: Partial, credential?: UserToken): Promise { + const res = await api( + 'admin/resolve-abuse-user-report', + { + reportId: admin.id, + ...args, + }, + credential ?? admin, + ); + return res.body; + } + + // ------------------------------------------------------------------------------------------- + + beforeAll(async () => { + queue = await startJobQueue(); + admin = await signup({ username: 'admin' }); + alice = await signup({ username: 'alice' }); + bob = await signup({ username: 'bob' }); + + await role(admin, { isAdministrator: true }); + }, 1000 * 60 * 2); + + afterAll(async () => { + await queue.close(); + }); + + // ------------------------------------------------------------------------------------------- + + describe('SystemWebhook', () => { + beforeEach(async () => { + const webhooks = await api('admin/system-webhook/list', {}, admin); + for (const webhook of webhooks.body) { + await api('admin/system-webhook/delete', { id: webhook.id }, admin); + } + }); + + test('通報を受けた -> abuseReportが送出される', async () => { + const webhook = await createSystemWebhook({ + on: ['abuseReport'], + isActive: true, + }); + await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); + + // 通報(bob -> alice) + const abuse = { + userId: alice.id, + comment: randomString(), + }; + const webhookBody = await captureWebhook(async () => { + await createAbuseReport(abuse, bob); + }); + + console.log(JSON.stringify(webhookBody, null, 2)); + + expect(webhookBody.hookId).toBe(webhook.id); + expect(webhookBody.type).toBe('abuseReport'); + expect(webhookBody.body.targetUserId).toBe(alice.id); + expect(webhookBody.body.reporterId).toBe(bob.id); + expect(webhookBody.body.comment).toBe(abuse.comment); + }); + + test('通報を受けた -> abuseReportが送出される -> 解決 -> abuseReportResolvedが送出される', async () => { + const webhook = await createSystemWebhook({ + on: ['abuseReport', 'abuseReportResolved'], + isActive: true, + }); + await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); + + // 通報(bob -> alice) + const abuse = { + userId: alice.id, + comment: randomString(), + }; + const webhookBody1 = await captureWebhook(async () => { + await createAbuseReport(abuse, bob); + }); + + console.log(JSON.stringify(webhookBody1, null, 2)); + expect(webhookBody1.hookId).toBe(webhook.id); + expect(webhookBody1.type).toBe('abuseReport'); + expect(webhookBody1.body.targetUserId).toBe(alice.id); + expect(webhookBody1.body.reporterId).toBe(bob.id); + expect(webhookBody1.body.assigneeId).toBeNull(); + expect(webhookBody1.body.resolved).toBe(false); + expect(webhookBody1.body.comment).toBe(abuse.comment); + + // 解決 + const webhookBody2 = await captureWebhook(async () => { + await resolveAbuseReport({ + reportId: webhookBody1.body.id, + forward: false, + }, admin); + }); + + console.log(JSON.stringify(webhookBody2, null, 2)); + expect(webhookBody2.hookId).toBe(webhook.id); + expect(webhookBody2.type).toBe('abuseReportResolved'); + expect(webhookBody2.body.targetUserId).toBe(alice.id); + expect(webhookBody2.body.reporterId).toBe(bob.id); + expect(webhookBody2.body.assigneeId).toBe(admin.id); + expect(webhookBody2.body.resolved).toBe(true); + expect(webhookBody2.body.comment).toBe(abuse.comment); + }); + + test('通報を受けた -> abuseReportが未許可の場合は送出されない', async () => { + const webhook = await createSystemWebhook({ + on: [], + isActive: true, + }); + await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); + + // 通報(bob -> alice) + const abuse = { + userId: alice.id, + comment: randomString(), + }; + const webhookBody = await captureWebhook(async () => { + await createAbuseReport(abuse, bob); + }).catch(e => e.message); + + expect(webhookBody).toBe('timeout'); + }); + + test('通報を受けた -> abuseReportが未許可の場合は送出されない -> 解決 -> abuseReportResolvedが送出される', async () => { + const webhook = await createSystemWebhook({ + on: ['abuseReportResolved'], + isActive: true, + }); + await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); + + // 通報(bob -> alice) + const abuse = { + userId: alice.id, + comment: randomString(), + }; + const webhookBody1 = await captureWebhook(async () => { + await createAbuseReport(abuse, bob); + }).catch(e => e.message); + + expect(webhookBody1).toBe('timeout'); + + const abuseReportId = (await api('admin/abuse-user-reports', {}, admin)).body[0].id; + + // 解決 + const webhookBody2 = await captureWebhook(async () => { + await resolveAbuseReport({ + reportId: abuseReportId, + forward: false, + }, admin); + }); + + console.log(JSON.stringify(webhookBody2, null, 2)); + expect(webhookBody2.hookId).toBe(webhook.id); + expect(webhookBody2.type).toBe('abuseReportResolved'); + expect(webhookBody2.body.targetUserId).toBe(alice.id); + expect(webhookBody2.body.reporterId).toBe(bob.id); + expect(webhookBody2.body.assigneeId).toBe(admin.id); + expect(webhookBody2.body.resolved).toBe(true); + expect(webhookBody2.body.comment).toBe(abuse.comment); + }); + + test('通報を受けた -> abuseReportが送出される -> 解決 -> abuseReportResolvedが未許可の場合は送出されない', async () => { + const webhook = await createSystemWebhook({ + on: ['abuseReport'], + isActive: true, + }); + await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); + + // 通報(bob -> alice) + const abuse = { + userId: alice.id, + comment: randomString(), + }; + const webhookBody1 = await captureWebhook(async () => { + await createAbuseReport(abuse, bob); + }); + + console.log(JSON.stringify(webhookBody1, null, 2)); + expect(webhookBody1.hookId).toBe(webhook.id); + expect(webhookBody1.type).toBe('abuseReport'); + expect(webhookBody1.body.targetUserId).toBe(alice.id); + expect(webhookBody1.body.reporterId).toBe(bob.id); + expect(webhookBody1.body.assigneeId).toBeNull(); + expect(webhookBody1.body.resolved).toBe(false); + expect(webhookBody1.body.comment).toBe(abuse.comment); + + // 解決 + const webhookBody2 = await captureWebhook(async () => { + await resolveAbuseReport({ + reportId: webhookBody1.body.id, + forward: false, + }, admin); + }).catch(e => e.message); + + expect(webhookBody2).toBe('timeout'); + }); + + test('通報を受けた -> abuseReportが未許可の場合は送出されない -> 解決 -> abuseReportResolvedが未許可の場合は送出されない', async () => { + const webhook = await createSystemWebhook({ + on: [], + isActive: true, + }); + await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); + + // 通報(bob -> alice) + const abuse = { + userId: alice.id, + comment: randomString(), + }; + const webhookBody1 = await captureWebhook(async () => { + await createAbuseReport(abuse, bob); + }).catch(e => e.message); + + expect(webhookBody1).toBe('timeout'); + + const abuseReportId = (await api('admin/abuse-user-reports', {}, admin)).body[0].id; + + // 解決 + const webhookBody2 = await captureWebhook(async () => { + await resolveAbuseReport({ + reportId: abuseReportId, + forward: false, + }, admin); + }).catch(e => e.message); + + expect(webhookBody2).toBe('timeout'); + }); + + test('通報を受けた -> Webhookが無効の場合は送出されない', async () => { + const webhook = await createSystemWebhook({ + on: ['abuseReport', 'abuseReportResolved'], + isActive: false, + }); + await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id }); + + // 通報(bob -> alice) + const abuse = { + userId: alice.id, + comment: randomString(), + }; + const webhookBody1 = await captureWebhook(async () => { + await createAbuseReport(abuse, bob); + }).catch(e => e.message); + + expect(webhookBody1).toBe('timeout'); + + const abuseReportId = (await api('admin/abuse-user-reports', {}, admin)).body[0].id; + + // 解決 + const webhookBody2 = await captureWebhook(async () => { + await resolveAbuseReport({ + reportId: abuseReportId, + forward: false, + }, admin); + }).catch(e => e.message); + + expect(webhookBody2).toBe('timeout'); + }); + + test('通報を受けた -> 通知設定が無効の場合は送出されない', async () => { + const webhook = await createSystemWebhook({ + on: ['abuseReport', 'abuseReportResolved'], + isActive: true, + }); + await createAbuseReportNotificationRecipient({ systemWebhookId: webhook.id, isActive: false }); + + // 通報(bob -> alice) + const abuse = { + userId: alice.id, + comment: randomString(), + }; + const webhookBody1 = await captureWebhook(async () => { + await createAbuseReport(abuse, bob); + }).catch(e => e.message); + + expect(webhookBody1).toBe('timeout'); + + const abuseReportId = (await api('admin/abuse-user-reports', {}, admin)).body[0].id; + + // 解決 + const webhookBody2 = await captureWebhook(async () => { + await resolveAbuseReport({ + reportId: abuseReportId, + forward: false, + }, admin); + }).catch(e => e.message); + + expect(webhookBody2).toBe('timeout'); + }); + }); +}); diff --git a/packages/backend/test/unit/AbuseReportNotificationService.ts b/packages/backend/test/unit/AbuseReportNotificationService.ts new file mode 100644 index 0000000000..e971659070 --- /dev/null +++ b/packages/backend/test/unit/AbuseReportNotificationService.ts @@ -0,0 +1,343 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { jest } from '@jest/globals'; +import { Test, TestingModule } from '@nestjs/testing'; +import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js'; +import { + AbuseReportNotificationRecipientRepository, + MiAbuseReportNotificationRecipient, + MiSystemWebhook, + MiUser, + SystemWebhooksRepository, + UserProfilesRepository, + UsersRepository, +} from '@/models/_.js'; +import { DI } from '@/di-symbols.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { IdService } from '@/core/IdService.js'; +import { EmailService } from '@/core/EmailService.js'; +import { RoleService } from '@/core/RoleService.js'; +import { MetaService } from '@/core/MetaService.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { RecipientMethod } from '@/models/AbuseReportNotificationRecipient.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; +import { randomString } from '../utils.js'; + +process.env.NODE_ENV = 'test'; + +describe('AbuseReportNotificationService', () => { + let app: TestingModule; + let service: AbuseReportNotificationService; + + // -------------------------------------------------------------------------------------- + + let usersRepository: UsersRepository; + let userProfilesRepository: UserProfilesRepository; + let systemWebhooksRepository: SystemWebhooksRepository; + let abuseReportNotificationRecipientRepository: AbuseReportNotificationRecipientRepository; + let idService: IdService; + let roleService: jest.Mocked; + let emailService: jest.Mocked; + let webhookService: jest.Mocked; + + // -------------------------------------------------------------------------------------- + + let root: MiUser; + let alice: MiUser; + let bob: MiUser; + let systemWebhook1: MiSystemWebhook; + let systemWebhook2: MiSystemWebhook; + + // -------------------------------------------------------------------------------------- + + async function createUser(data: Partial = {}) { + const user = await usersRepository + .insert({ + id: idService.gen(), + ...data, + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + + await userProfilesRepository.insert({ + userId: user.id, + }); + + return user; + } + + async function createWebhook(data: Partial = {}) { + return systemWebhooksRepository + .insert({ + id: idService.gen(), + name: randomString(), + on: ['abuseReport'], + url: 'https://example.com', + secret: randomString(), + ...data, + }) + .then(x => systemWebhooksRepository.findOneByOrFail(x.identifiers[0])); + } + + async function createRecipient(data: Partial = {}) { + return abuseReportNotificationRecipientRepository + .insert({ + id: idService.gen(), + isActive: true, + name: randomString(), + ...data, + }) + .then(x => abuseReportNotificationRecipientRepository.findOneByOrFail(x.identifiers[0])); + } + + // -------------------------------------------------------------------------------------- + + beforeAll(async () => { + app = await Test + .createTestingModule({ + imports: [ + GlobalModule, + ], + providers: [ + AbuseReportNotificationService, + IdService, + { + provide: RoleService, useFactory: () => ({ getModeratorIds: jest.fn() }), + }, + { + provide: SystemWebhookService, useFactory: () => ({ enqueueSystemWebhook: jest.fn() }), + }, + { + provide: EmailService, useFactory: () => ({ sendEmail: jest.fn() }), + }, + { + provide: MetaService, useFactory: () => ({ fetch: jest.fn() }), + }, + { + provide: ModerationLogService, useFactory: () => ({ log: () => Promise.resolve() }), + }, + { + provide: GlobalEventService, useFactory: () => ({ publishAdminStream: jest.fn() }), + }, + ], + }) + .compile(); + + usersRepository = app.get(DI.usersRepository); + userProfilesRepository = app.get(DI.userProfilesRepository); + systemWebhooksRepository = app.get(DI.systemWebhooksRepository); + abuseReportNotificationRecipientRepository = app.get(DI.abuseReportNotificationRecipientRepository); + + service = app.get(AbuseReportNotificationService); + idService = app.get(IdService); + roleService = app.get(RoleService) as jest.Mocked; + emailService = app.get(EmailService) as jest.Mocked; + webhookService = app.get(SystemWebhookService) as jest.Mocked; + + app.enableShutdownHooks(); + }); + + beforeEach(async () => { + root = await createUser({ username: 'root', usernameLower: 'root', isRoot: true }); + alice = await createUser({ username: 'alice', usernameLower: 'alice', isRoot: false }); + bob = await createUser({ username: 'bob', usernameLower: 'bob', isRoot: false }); + systemWebhook1 = await createWebhook(); + systemWebhook2 = await createWebhook(); + + roleService.getModeratorIds.mockResolvedValue([root.id, alice.id, bob.id]); + }); + + afterEach(async () => { + emailService.sendEmail.mockClear(); + webhookService.enqueueSystemWebhook.mockClear(); + + await usersRepository.delete({}); + await userProfilesRepository.delete({}); + await systemWebhooksRepository.delete({}); + await abuseReportNotificationRecipientRepository.delete({}); + }); + + afterAll(async () => { + await app.close(); + }); + + // -------------------------------------------------------------------------------------- + + describe('createRecipient', () => { + test('作成成功1', async () => { + const params = { + isActive: true, + name: randomString(), + method: 'email' as RecipientMethod, + userId: alice.id, + systemWebhookId: null, + }; + + const recipient1 = await service.createRecipient(params, root); + expect(recipient1).toMatchObject(params); + }); + + test('作成成功2', async () => { + const params = { + isActive: true, + name: randomString(), + method: 'webhook' as RecipientMethod, + userId: null, + systemWebhookId: systemWebhook1.id, + }; + + const recipient1 = await service.createRecipient(params, root); + expect(recipient1).toMatchObject(params); + }); + }); + + describe('updateRecipient', () => { + test('更新成功1', async () => { + const recipient1 = await createRecipient({ + method: 'email', + userId: alice.id, + }); + + const params = { + id: recipient1.id, + isActive: false, + name: randomString(), + method: 'email' as RecipientMethod, + userId: bob.id, + systemWebhookId: null, + }; + + const recipient2 = await service.updateRecipient(params, root); + expect(recipient2).toMatchObject(params); + }); + + test('更新成功2', async () => { + const recipient1 = await createRecipient({ + method: 'webhook', + systemWebhookId: systemWebhook1.id, + }); + + const params = { + id: recipient1.id, + isActive: false, + name: randomString(), + method: 'webhook' as RecipientMethod, + userId: null, + systemWebhookId: systemWebhook2.id, + }; + + const recipient2 = await service.updateRecipient(params, root); + expect(recipient2).toMatchObject(params); + }); + }); + + describe('deleteRecipient', () => { + test('削除成功1', async () => { + const recipient1 = await createRecipient({ + method: 'email', + userId: alice.id, + }); + + await service.deleteRecipient(recipient1.id, root); + + await expect(abuseReportNotificationRecipientRepository.findOneBy({ id: recipient1.id })).resolves.toBeNull(); + }); + }); + + describe('fetchRecipients', () => { + async function create() { + const recipient1 = await createRecipient({ + method: 'email', + userId: alice.id, + }); + const recipient2 = await createRecipient({ + method: 'email', + userId: bob.id, + }); + + const recipient3 = await createRecipient({ + method: 'webhook', + systemWebhookId: systemWebhook1.id, + }); + const recipient4 = await createRecipient({ + method: 'webhook', + systemWebhookId: systemWebhook2.id, + }); + + return [recipient1, recipient2, recipient3, recipient4]; + } + + test('フィルタなし', async () => { + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({}); + expect(recipients).toEqual([recipient1, recipient2, recipient3, recipient4]); + }); + + test('フィルタなし(非モデレータは除外される)', async () => { + roleService.getModeratorIds.mockClear(); + roleService.getModeratorIds.mockResolvedValue([root.id, bob.id]); + + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({}); + // aliceはモデレータではないので除外される + expect(recipients).toEqual([recipient2, recipient3, recipient4]); + }); + + test('フィルタなし(非モデレータでも除外されないオプション設定)', async () => { + roleService.getModeratorIds.mockClear(); + roleService.getModeratorIds.mockResolvedValue([root.id, bob.id]); + + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({}, { removeUnauthorized: false }); + expect(recipients).toEqual([recipient1, recipient2, recipient3, recipient4]); + }); + + test('emailのみ', async () => { + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({ method: ['email'] }); + expect(recipients).toEqual([recipient1, recipient2]); + }); + + test('webhookのみ', async () => { + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({ method: ['webhook'] }); + expect(recipients).toEqual([recipient3, recipient4]); + }); + + test('すべて', async () => { + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({ method: ['email', 'webhook'] }); + expect(recipients).toEqual([recipient1, recipient2, recipient3, recipient4]); + }); + + test('ID指定', async () => { + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({ ids: [recipient1.id, recipient3.id] }); + expect(recipients).toEqual([recipient1, recipient3]); + }); + + test('ID指定(method=emailではないIDが混ざりこまない)', async () => { + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({ ids: [recipient1.id, recipient3.id], method: ['email'] }); + expect(recipients).toEqual([recipient1]); + }); + + test('ID指定(method=webhookではないIDが混ざりこまない)', async () => { + const [recipient1, recipient2, recipient3, recipient4] = await create(); + + const recipients = await service.fetchRecipients({ ids: [recipient1.id, recipient3.id], method: ['webhook'] }); + expect(recipients).toEqual([recipient3]); + }); + }); +}); diff --git a/packages/backend/test/unit/RoleService.ts b/packages/backend/test/unit/RoleService.ts index ec441735d7..69fa4162fb 100644 --- a/packages/backend/test/unit/RoleService.ts +++ b/packages/backend/test/unit/RoleService.ts @@ -3,8 +3,6 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { UserEntityService } from '@/core/entities/UserEntityService.js'; - process.env.NODE_ENV = 'test'; import { jest } from '@jest/globals'; @@ -13,7 +11,14 @@ import { Test } from '@nestjs/testing'; import * as lolex from '@sinonjs/fake-timers'; import { GlobalModule } from '@/GlobalModule.js'; import { RoleService } from '@/core/RoleService.js'; -import type { MiRole, MiUser, RoleAssignmentsRepository, RolesRepository, UsersRepository } from '@/models/_.js'; +import { + MiRole, + MiRoleAssignment, + MiUser, + RoleAssignmentsRepository, + RolesRepository, + UsersRepository, +} from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { MetaService } from '@/core/MetaService.js'; import { genAidx } from '@/misc/id/aidx.js'; @@ -23,6 +28,7 @@ import { GlobalEventService } from '@/core/GlobalEventService.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { NotificationService } from '@/core/NotificationService.js'; import { RoleCondFormulaValue } from '@/models/Role.js'; +import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { sleep } from '../utils.js'; import type { TestingModule } from '@nestjs/testing'; import type { MockFunctionMetadata } from 'jest-mock'; @@ -39,27 +45,27 @@ describe('RoleService', () => { let notificationService: jest.Mocked; let clock: lolex.InstalledClock; - function createUser(data: Partial = {}) { + async function createUser(data: Partial = {}) { const un = secureRndstr(16); - return usersRepository.insert({ + const x = await usersRepository.insert({ id: genAidx(Date.now()), username: un, usernameLower: un, ...data, - }) - .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + }); + return await usersRepository.findOneByOrFail(x.identifiers[0]); } - function createRole(data: Partial = {}) { - return rolesRepository.insert({ + async function createRole(data: Partial = {}) { + const x = await rolesRepository.insert({ id: genAidx(Date.now()), updatedAt: new Date(), lastUsedAt: new Date(), name: '', description: '', ...data, - }) - .then(x => rolesRepository.findOneByOrFail(x.identifiers[0])); + }); + return await rolesRepository.findOneByOrFail(x.identifiers[0]); } function createConditionalRole(condFormula: RoleCondFormulaValue, data: Partial = {}) { @@ -71,6 +77,20 @@ describe('RoleService', () => { }); } + async function assignRole(args: Partial) { + const id = genAidx(Date.now()); + const expiresAt = new Date(); + expiresAt.setDate(expiresAt.getDate() + 1); + + await roleAssignmentsRepository.insert({ + id, + expiresAt, + ...args, + }); + + return await roleAssignmentsRepository.findOneByOrFail({ id }); + } + function aidx() { return genAidx(Date.now()); } @@ -265,6 +285,96 @@ describe('RoleService', () => { }); }); + describe('getModeratorIds', () => { + test('includeAdmins = false, excludeExpire = false', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), + ]); + + const role1 = await createRole({ name: 'admin', isAdministrator: true }); + const role2 = await createRole({ name: 'moderator', isModerator: true }); + const role3 = await createRole({ name: 'normal' }); + + await Promise.all([ + assignRole({ userId: adminUser1.id, roleId: role1.id }), + assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: modeUser1.id, roleId: role2.id }), + assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: normalUser1.id, roleId: role3.id }), + assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), + ]); + + const result = await roleService.getModeratorIds(false, false); + expect(result).toEqual([modeUser1.id, modeUser2.id]); + }); + + test('includeAdmins = false, excludeExpire = true', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), + ]); + + const role1 = await createRole({ name: 'admin', isAdministrator: true }); + const role2 = await createRole({ name: 'moderator', isModerator: true }); + const role3 = await createRole({ name: 'normal' }); + + await Promise.all([ + assignRole({ userId: adminUser1.id, roleId: role1.id }), + assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: modeUser1.id, roleId: role2.id }), + assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: normalUser1.id, roleId: role3.id }), + assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), + ]); + + const result = await roleService.getModeratorIds(false, true); + expect(result).toEqual([modeUser1.id]); + }); + + test('includeAdmins = true, excludeExpire = false', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), + ]); + + const role1 = await createRole({ name: 'admin', isAdministrator: true }); + const role2 = await createRole({ name: 'moderator', isModerator: true }); + const role3 = await createRole({ name: 'normal' }); + + await Promise.all([ + assignRole({ userId: adminUser1.id, roleId: role1.id }), + assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: modeUser1.id, roleId: role2.id }), + assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: normalUser1.id, roleId: role3.id }), + assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), + ]); + + const result = await roleService.getModeratorIds(true, false); + expect(result).toEqual([adminUser1.id, adminUser2.id, modeUser1.id, modeUser2.id]); + }); + + test('includeAdmins = true, excludeExpire = true', async () => { + const [adminUser1, adminUser2, modeUser1, modeUser2, normalUser1, normalUser2] = await Promise.all([ + createUser(), createUser(), createUser(), createUser(), createUser(), createUser(), + ]); + + const role1 = await createRole({ name: 'admin', isAdministrator: true }); + const role2 = await createRole({ name: 'moderator', isModerator: true }); + const role3 = await createRole({ name: 'normal' }); + + await Promise.all([ + assignRole({ userId: adminUser1.id, roleId: role1.id }), + assignRole({ userId: adminUser2.id, roleId: role1.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: modeUser1.id, roleId: role2.id }), + assignRole({ userId: modeUser2.id, roleId: role2.id, expiresAt: new Date(Date.now() - 1000) }), + assignRole({ userId: normalUser1.id, roleId: role3.id }), + assignRole({ userId: normalUser2.id, roleId: role3.id, expiresAt: new Date(Date.now() - 1000) }), + ]); + + const result = await roleService.getModeratorIds(true, true); + expect(result).toEqual([adminUser1.id, modeUser1.id]); + }); + }); + describe('conditional role', () => { test('~かつ~', async () => { const [user1, user2, user3, user4] = await Promise.all([ diff --git a/packages/backend/test/unit/SystemWebhookService.ts b/packages/backend/test/unit/SystemWebhookService.ts new file mode 100644 index 0000000000..41b7f977ca --- /dev/null +++ b/packages/backend/test/unit/SystemWebhookService.ts @@ -0,0 +1,515 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { afterEach, beforeEach, describe, expect, jest } from '@jest/globals'; +import { Test, TestingModule } from '@nestjs/testing'; +import { MiUser } from '@/models/User.js'; +import { MiSystemWebhook, SystemWebhookEventType } from '@/models/SystemWebhook.js'; +import { SystemWebhooksRepository, UsersRepository } from '@/models/_.js'; +import { IdService } from '@/core/IdService.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { ModerationLogService } from '@/core/ModerationLogService.js'; +import { GlobalEventService } from '@/core/GlobalEventService.js'; +import { DI } from '@/di-symbols.js'; +import { QueueService } from '@/core/QueueService.js'; +import { LoggerService } from '@/core/LoggerService.js'; +import { SystemWebhookService } from '@/core/SystemWebhookService.js'; +import { randomString, sleep } from '../utils.js'; + +describe('SystemWebhookService', () => { + let app: TestingModule; + let service: SystemWebhookService; + + // -------------------------------------------------------------------------------------- + + let usersRepository: UsersRepository; + let systemWebhooksRepository: SystemWebhooksRepository; + let idService: IdService; + let queueService: jest.Mocked; + + // -------------------------------------------------------------------------------------- + + let root: MiUser; + + // -------------------------------------------------------------------------------------- + + async function createUser(data: Partial = {}) { + return await usersRepository + .insert({ + id: idService.gen(), + ...data, + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + } + + async function createWebhook(data: Partial = {}) { + return systemWebhooksRepository + .insert({ + id: idService.gen(), + name: randomString(), + on: ['abuseReport'], + url: 'https://example.com', + secret: randomString(), + ...data, + }) + .then(x => systemWebhooksRepository.findOneByOrFail(x.identifiers[0])); + } + + // -------------------------------------------------------------------------------------- + + async function beforeAllImpl() { + app = await Test + .createTestingModule({ + imports: [ + GlobalModule, + ], + providers: [ + SystemWebhookService, + IdService, + LoggerService, + GlobalEventService, + { + provide: QueueService, useFactory: () => ({ systemWebhookDeliver: jest.fn() }), + }, + { + provide: ModerationLogService, useFactory: () => ({ log: () => Promise.resolve() }), + }, + ], + }) + .compile(); + + usersRepository = app.get(DI.usersRepository); + systemWebhooksRepository = app.get(DI.systemWebhooksRepository); + + service = app.get(SystemWebhookService); + idService = app.get(IdService); + queueService = app.get(QueueService) as jest.Mocked; + + app.enableShutdownHooks(); + } + + async function afterAllImpl() { + await app.close(); + } + + async function beforeEachImpl() { + root = await createUser({ isRoot: true, username: 'root', usernameLower: 'root' }); + } + + async function afterEachImpl() { + await usersRepository.delete({}); + await systemWebhooksRepository.delete({}); + } + + // -------------------------------------------------------------------------------------- + + describe('アプリを毎回作り直す必要のないグループ', () => { + beforeAll(beforeAllImpl); + afterAll(afterAllImpl); + beforeEach(beforeEachImpl); + afterEach(afterEachImpl); + + describe('fetchSystemWebhooks', () => { + test('フィルタなし', async () => { + const webhook1 = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + const webhook2 = await createWebhook({ + isActive: false, + on: ['abuseReport'], + }); + const webhook3 = await createWebhook({ + isActive: true, + on: ['abuseReportResolved'], + }); + const webhook4 = await createWebhook({ + isActive: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchSystemWebhooks(); + expect(fetchedWebhooks).toEqual([webhook1, webhook2, webhook3, webhook4]); + }); + + test('activeのみ', async () => { + const webhook1 = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + const webhook2 = await createWebhook({ + isActive: false, + on: ['abuseReport'], + }); + const webhook3 = await createWebhook({ + isActive: true, + on: ['abuseReportResolved'], + }); + const webhook4 = await createWebhook({ + isActive: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchSystemWebhooks({ isActive: true }); + expect(fetchedWebhooks).toEqual([webhook1, webhook3]); + }); + + test('特定のイベントのみ', async () => { + const webhook1 = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + const webhook2 = await createWebhook({ + isActive: false, + on: ['abuseReport'], + }); + const webhook3 = await createWebhook({ + isActive: true, + on: ['abuseReportResolved'], + }); + const webhook4 = await createWebhook({ + isActive: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchSystemWebhooks({ on: ['abuseReport'] }); + expect(fetchedWebhooks).toEqual([webhook1, webhook2]); + }); + + test('activeな特定のイベントのみ', async () => { + const webhook1 = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + const webhook2 = await createWebhook({ + isActive: false, + on: ['abuseReport'], + }); + const webhook3 = await createWebhook({ + isActive: true, + on: ['abuseReportResolved'], + }); + const webhook4 = await createWebhook({ + isActive: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchSystemWebhooks({ on: ['abuseReport'], isActive: true }); + expect(fetchedWebhooks).toEqual([webhook1]); + }); + + test('ID指定', async () => { + const webhook1 = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + const webhook2 = await createWebhook({ + isActive: false, + on: ['abuseReport'], + }); + const webhook3 = await createWebhook({ + isActive: true, + on: ['abuseReportResolved'], + }); + const webhook4 = await createWebhook({ + isActive: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchSystemWebhooks({ ids: [webhook1.id, webhook4.id] }); + expect(fetchedWebhooks).toEqual([webhook1, webhook4]); + }); + + test('ID指定(他条件とANDになるか見たい)', async () => { + const webhook1 = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + const webhook2 = await createWebhook({ + isActive: false, + on: ['abuseReport'], + }); + const webhook3 = await createWebhook({ + isActive: true, + on: ['abuseReportResolved'], + }); + const webhook4 = await createWebhook({ + isActive: false, + on: [], + }); + + const fetchedWebhooks = await service.fetchSystemWebhooks({ ids: [webhook1.id, webhook4.id], isActive: false }); + expect(fetchedWebhooks).toEqual([webhook4]); + }); + }); + + describe('createSystemWebhook', () => { + test('作成成功 ', async () => { + const params = { + isActive: true, + name: randomString(), + on: ['abuseReport'] as SystemWebhookEventType[], + url: 'https://example.com', + secret: randomString(), + }; + + const webhook = await service.createSystemWebhook(params, root); + expect(webhook).toMatchObject(params); + }); + }); + + describe('updateSystemWebhook', () => { + test('更新成功', async () => { + const webhook = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + + const params = { + id: webhook.id, + isActive: false, + name: randomString(), + on: ['abuseReport'] as SystemWebhookEventType[], + url: randomString(), + secret: randomString(), + }; + + const updatedWebhook = await service.updateSystemWebhook(params, root); + expect(updatedWebhook).toMatchObject(params); + }); + }); + + describe('deleteSystemWebhook', () => { + test('削除成功', async () => { + const webhook = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + + await service.deleteSystemWebhook(webhook.id, root); + + await expect(systemWebhooksRepository.findOneBy({ id: webhook.id })).resolves.toBeNull(); + }); + }); + }); + + describe('アプリを毎回作り直す必要があるグループ', () => { + beforeEach(async () => { + await beforeAllImpl(); + await beforeEachImpl(); + }); + + afterEach(async () => { + await afterEachImpl(); + await afterAllImpl(); + }); + + describe('enqueueSystemWebhook', () => { + test('キューに追加成功', async () => { + const webhook = await createWebhook({ + isActive: true, + on: ['abuseReport'], + }); + await service.enqueueSystemWebhook(webhook.id, 'abuseReport', { foo: 'bar' }); + + expect(queueService.systemWebhookDeliver).toHaveBeenCalled(); + }); + + test('非アクティブなWebhookはキューに追加されない', async () => { + const webhook = await createWebhook({ + isActive: false, + on: ['abuseReport'], + }); + await service.enqueueSystemWebhook(webhook.id, 'abuseReport', { foo: 'bar' }); + + expect(queueService.systemWebhookDeliver).not.toHaveBeenCalled(); + }); + + test('未許可のイベント種別が渡された場合はWebhookはキューに追加されない', async () => { + const webhook1 = await createWebhook({ + isActive: true, + on: [], + }); + const webhook2 = await createWebhook({ + isActive: true, + on: ['abuseReportResolved'], + }); + await service.enqueueSystemWebhook(webhook1.id, 'abuseReport', { foo: 'bar' }); + await service.enqueueSystemWebhook(webhook2.id, 'abuseReport', { foo: 'bar' }); + + expect(queueService.systemWebhookDeliver).not.toHaveBeenCalled(); + }); + }); + + describe('fetchActiveSystemWebhooks', () => { + describe('systemWebhookCreated', () => { + test('ActiveなWebhookが追加された時、キャッシュに追加されている', async () => { + const webhook = await service.createSystemWebhook( + { + isActive: true, + name: randomString(), + on: ['abuseReport'], + url: 'https://example.com', + secret: randomString(), + }, + root, + ); + + // redisでの配信経由で更新されるのでちょっと待つ + await sleep(500); + + const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); + expect(fetchedWebhooks).toEqual([webhook]); + }); + + test('NotActiveなWebhookが追加された時、キャッシュに追加されていない', async () => { + const webhook = await service.createSystemWebhook( + { + isActive: false, + name: randomString(), + on: ['abuseReport'], + url: 'https://example.com', + secret: randomString(), + }, + root, + ); + + // redisでの配信経由で更新されるのでちょっと待つ + await sleep(500); + + const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); + expect(fetchedWebhooks).toEqual([]); + }); + }); + + describe('systemWebhookUpdated', () => { + test('ActiveなWebhookが編集された時、キャッシュに反映されている', async () => { + const id = idService.gen(); + await createWebhook({ id }); + // キャッシュ作成 + const webhook1 = await service.fetchActiveSystemWebhooks(); + // 読み込まれていることをチェック + expect(webhook1.length).toEqual(1); + expect(webhook1[0].id).toEqual(id); + + const webhook2 = await service.updateSystemWebhook( + { + id, + isActive: true, + name: randomString(), + on: ['abuseReport'], + url: 'https://example.com', + secret: randomString(), + }, + root, + ); + + // redisでの配信経由で更新されるのでちょっと待つ + await sleep(500); + + const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); + expect(fetchedWebhooks).toEqual([webhook2]); + }); + + test('NotActiveなWebhookが編集された時、キャッシュに追加されない', async () => { + const id = idService.gen(); + await createWebhook({ id, isActive: false }); + // キャッシュ作成 + const webhook1 = await service.fetchActiveSystemWebhooks(); + // 読み込まれていないことをチェック + expect(webhook1.length).toEqual(0); + + const webhook2 = await service.updateSystemWebhook( + { + id, + isActive: false, + name: randomString(), + on: ['abuseReport'], + url: 'https://example.com', + secret: randomString(), + }, + root, + ); + + // redisでの配信経由で更新されるのでちょっと待つ + await sleep(500); + + const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); + expect(fetchedWebhooks.length).toEqual(0); + }); + + test('NotActiveなWebhookがActiveにされた時、キャッシュに追加されている', async () => { + const id = idService.gen(); + const baseWebhook = await createWebhook({ id, isActive: false }); + // キャッシュ作成 + const webhook1 = await service.fetchActiveSystemWebhooks(); + // 読み込まれていないことをチェック + expect(webhook1.length).toEqual(0); + + const webhook2 = await service.updateSystemWebhook( + { + ...baseWebhook, + isActive: true, + }, + root, + ); + + // redisでの配信経由で更新されるのでちょっと待つ + await sleep(500); + + const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); + expect(fetchedWebhooks).toEqual([webhook2]); + }); + + test('ActiveなWebhookがNotActiveにされた時、キャッシュから削除されている', async () => { + const id = idService.gen(); + const baseWebhook = await createWebhook({ id, isActive: true }); + // キャッシュ作成 + const webhook1 = await service.fetchActiveSystemWebhooks(); + // 読み込まれていることをチェック + expect(webhook1.length).toEqual(1); + expect(webhook1[0].id).toEqual(id); + + const webhook2 = await service.updateSystemWebhook( + { + ...baseWebhook, + isActive: false, + }, + root, + ); + + // redisでの配信経由で更新されるのでちょっと待つ + await sleep(500); + + const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); + expect(fetchedWebhooks.length).toEqual(0); + }); + }); + + describe('systemWebhookDeleted', () => { + test('キャッシュから削除されている', async () => { + const id = idService.gen(); + const baseWebhook = await createWebhook({ id, isActive: true }); + // キャッシュ作成 + const webhook1 = await service.fetchActiveSystemWebhooks(); + // 読み込まれていることをチェック + expect(webhook1.length).toEqual(1); + expect(webhook1[0].id).toEqual(id); + + const webhook2 = await service.deleteSystemWebhook( + id, + root, + ); + + // redisでの配信経由で更新されるのでちょっと待つ + await sleep(500); + + const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); + expect(fetchedWebhooks.length).toEqual(0); + }); + }); + }); + }); +}); diff --git a/packages/frontend/src/components/MkButton.vue b/packages/frontend/src/components/MkButton.vue index 3489255b91..25b003ba5a 100644 --- a/packages/frontend/src/components/MkButton.vue +++ b/packages/frontend/src/components/MkButton.vue @@ -11,6 +11,7 @@ SPDX-License-Identifier: AGPL-3.0-only :type="type" :name="name" :value="value" + :disabled="disabled" @click="emit('click', $event)" @mousedown="onMousedown" > @@ -55,6 +56,7 @@ const props = defineProps<{ asLike?: boolean; name?: string; value?: string; + disabled?: boolean; }>(); const emit = defineEmits<{ diff --git a/packages/frontend/src/components/MkDivider.vue b/packages/frontend/src/components/MkDivider.vue new file mode 100644 index 0000000000..e4e3af99e4 --- /dev/null +++ b/packages/frontend/src/components/MkDivider.vue @@ -0,0 +1,32 @@ + + + + + + + diff --git a/packages/frontend/src/components/MkSwitch.vue b/packages/frontend/src/components/MkSwitch.vue index a19b45448b..721ac357f4 100644 --- a/packages/frontend/src/components/MkSwitch.vue +++ b/packages/frontend/src/components/MkSwitch.vue @@ -13,7 +13,7 @@ SPDX-License-Identifier: AGPL-3.0-only @keydown.enter="toggle" > - + @@ -34,16 +34,19 @@ const props = defineProps<{ modelValue: boolean | Ref; disabled?: boolean; helpText?: string; + noBody?: boolean; }>(); const emit = defineEmits<{ (ev: 'update:modelValue', v: boolean): void; + (ev: 'change', v: boolean): void; }>(); const checked = toRefs(props).modelValue; const toggle = () => { if (props.disabled) return; emit('update:modelValue', !checked.value); + emit('change', !checked.value); }; diff --git a/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts b/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts new file mode 100644 index 0000000000..1222d3261d --- /dev/null +++ b/packages/frontend/src/components/MkSystemWebhookEditor.impl.ts @@ -0,0 +1,45 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { defineAsyncComponent } from 'vue'; +import * as os from '@/os.js'; + +export type SystemWebhookEventType = 'abuseReport' | 'abuseReportResolved'; + +export type MkSystemWebhookEditorProps = { + mode: 'create' | 'edit'; + id?: string; + requiredEvents?: SystemWebhookEventType[]; +}; + +export type MkSystemWebhookResult = { + id?: string; + isActive: boolean; + name: string; + on: SystemWebhookEventType[]; + url: string; + secret: string; +}; + +export async function showSystemWebhookEditorDialog(props: MkSystemWebhookEditorProps): Promise { + const { dispose, result } = await new Promise<{ dispose: () => void, result: MkSystemWebhookResult | null }>(async resolve => { + const res = await os.popup( + defineAsyncComponent(() => import('@/components/MkSystemWebhookEditor.vue')), + props, + { + submitted: (ev: MkSystemWebhookResult) => { + resolve({ dispose: res.dispose, result: ev }); + }, + closed: () => { + resolve({ dispose: res.dispose, result: null }); + }, + }, + ); + }); + + dispose(); + + return result; +} diff --git a/packages/frontend/src/components/MkSystemWebhookEditor.vue b/packages/frontend/src/components/MkSystemWebhookEditor.vue new file mode 100644 index 0000000000..007d841f00 --- /dev/null +++ b/packages/frontend/src/components/MkSystemWebhookEditor.vue @@ -0,0 +1,217 @@ + + + + + + + diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue new file mode 100644 index 0000000000..ffe9c620d6 --- /dev/null +++ b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.editor.vue @@ -0,0 +1,307 @@ + + + + + + + diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue new file mode 100644 index 0000000000..0b86808faf --- /dev/null +++ b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue @@ -0,0 +1,114 @@ + + + + + + + diff --git a/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue new file mode 100644 index 0000000000..a52f8eb7af --- /dev/null +++ b/packages/frontend/src/pages/admin/abuse-report/notification-recipient.vue @@ -0,0 +1,176 @@ + + + + + + + diff --git a/packages/frontend/src/pages/admin/abuses.vue b/packages/frontend/src/pages/admin/abuses.vue index d2f4a4b531..9a9fa472a5 100644 --- a/packages/frontend/src/pages/admin/abuses.vue +++ b/packages/frontend/src/pages/admin/abuses.vue @@ -7,30 +7,33 @@ SPDX-License-Identifier: AGPL-3.0-only -
-
-
-
- - - - - - - - - - - - - - - - - - -
- - - - -
-
+ + +
@@ -60,6 +61,7 @@ import MkPagination from '@/components/MkPagination.vue'; import XAbuseReport from '@/components/MkAbuseReport.vue'; import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; +import MkButton from '@/components/MkButton.vue'; const reports = shallowRef>(); @@ -80,7 +82,7 @@ const pagination = { }; function resolved(reportId) { - reports.value.removeItem(reportId); + reports.value?.removeItem(reportId); } const headerActions = computed(() => []); @@ -92,3 +94,26 @@ definePageMetadata(() => ({ icon: 'ti ti-exclamation-circle', })); + + diff --git a/packages/frontend/src/pages/admin/index.vue b/packages/frontend/src/pages/admin/index.vue index 794feae202..292f10da1a 100644 --- a/packages/frontend/src/pages/admin/index.vue +++ b/packages/frontend/src/pages/admin/index.vue @@ -214,6 +214,11 @@ const menuDef = computed(() => [{ text: i18n.ts.externalServices, to: '/admin/external-services', active: currentPage.value?.route.name === 'external-services', + }, { + icon: 'ti ti-webhook', + text: 'Webhook', + to: '/admin/system-webhook', + active: currentPage.value?.route.name === 'system-webhook', }, { icon: 'ti ti-adjustments', text: i18n.ts.other, diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue index e33c882721..91f1c7c5e6 100644 --- a/packages/frontend/src/pages/admin/modlog.ModLog.vue +++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue @@ -8,9 +8,35 @@ SPDX-License-Identifier: AGPL-3.0-only + +
raw diff --git a/packages/frontend/src/pages/admin/system-webhook.item.vue b/packages/frontend/src/pages/admin/system-webhook.item.vue new file mode 100644 index 0000000000..0c07122af3 --- /dev/null +++ b/packages/frontend/src/pages/admin/system-webhook.item.vue @@ -0,0 +1,117 @@ + + + + + + + diff --git a/packages/frontend/src/pages/admin/system-webhook.vue b/packages/frontend/src/pages/admin/system-webhook.vue new file mode 100644 index 0000000000..7a40eec944 --- /dev/null +++ b/packages/frontend/src/pages/admin/system-webhook.vue @@ -0,0 +1,96 @@ + + + + + + + diff --git a/packages/frontend/src/router/definition.ts b/packages/frontend/src/router/definition.ts index c12ae0fa57..8a443f627b 100644 --- a/packages/frontend/src/router/definition.ts +++ b/packages/frontend/src/router/definition.ts @@ -471,6 +471,14 @@ const routes: RouteDef[] = [{ path: '/invites', name: 'invites', component: page(() => import('@/pages/admin/invites.vue')), + }, { + path: '/abuse-report-notification-recipient', + name: 'abuse-report-notification-recipient', + component: page(() => import('@/pages/admin/abuse-report/notification-recipient.vue')), + }, { + path: '/system-webhook', + name: 'system-webhook', + component: page(() => import('@/pages/admin/system-webhook.vue')), }, { path: '/', component: page(() => import('@/pages/_empty_.vue')), diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 6ff711cabb..bea89f2a7c 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -6,6 +6,11 @@ import { EventEmitter } from 'eventemitter3'; +// Warning: (ae-forgotten-export) The symbol "components" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +type AbuseReportNotificationRecipient = components['schemas']['AbuseReportNotificationRecipient']; + // @public (undocumented) export type Acct = { username: string; @@ -21,13 +26,38 @@ declare namespace acct { } export { acct } -// Warning: (ae-forgotten-export) The symbol "components" needs to be exported by the entry point index.d.ts -// // @public (undocumented) type Ad = components['schemas']['Ad']; // Warning: (ae-forgotten-export) The symbol "operations" needs to be exported by the entry point index.d.ts // +// @public (undocumented) +type AdminAbuseReportNotificationRecipientCreateRequest = operations['admin___abuse-report___notification-recipient___create']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminAbuseReportNotificationRecipientCreateResponse = operations['admin___abuse-report___notification-recipient___create']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type AdminAbuseReportNotificationRecipientDeleteRequest = operations['admin___abuse-report___notification-recipient___delete']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminAbuseReportNotificationRecipientListRequest = operations['admin___abuse-report___notification-recipient___list']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminAbuseReportNotificationRecipientListResponse = operations['admin___abuse-report___notification-recipient___list']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type AdminAbuseReportNotificationRecipientShowRequest = operations['admin___abuse-report___notification-recipient___show']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminAbuseReportNotificationRecipientShowResponse = operations['admin___abuse-report___notification-recipient___show']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type AdminAbuseReportNotificationRecipientUpdateRequest = operations['admin___abuse-report___notification-recipient___update']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminAbuseReportNotificationRecipientUpdateResponse = operations['admin___abuse-report___notification-recipient___update']['responses']['200']['content']['application/json']; + // @public (undocumented) type AdminAbuseUserReportsRequest = operations['admin___abuse-user-reports']['requestBody']['content']['application/json']; @@ -307,6 +337,33 @@ type AdminShowUsersResponse = operations['admin___show-users']['responses']['200 // @public (undocumented) type AdminSuspendUserRequest = operations['admin___suspend-user']['requestBody']['content']['application/json']; +// @public (undocumented) +type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminSystemWebhookCreateResponse = operations['admin___system-webhook___create']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type AdminSystemWebhookDeleteRequest = operations['admin___system-webhook___delete']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminSystemWebhookListRequest = operations['admin___system-webhook___list']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminSystemWebhookListResponse = operations['admin___system-webhook___list']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type AdminSystemWebhookShowRequest = operations['admin___system-webhook___show']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminSystemWebhookShowResponse = operations['admin___system-webhook___show']['responses']['200']['content']['application/json']; + +// @public (undocumented) +type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___update']['requestBody']['content']['application/json']; + +// @public (undocumented) +type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json']; + // @public (undocumented) type AdminUnsetUserAvatarRequest = operations['admin___unset-user-avatar']['requestBody']['content']['application/json']; @@ -1133,6 +1190,15 @@ declare namespace entities { AdminMetaResponse, AdminAbuseUserReportsRequest, AdminAbuseUserReportsResponse, + AdminAbuseReportNotificationRecipientListRequest, + AdminAbuseReportNotificationRecipientListResponse, + AdminAbuseReportNotificationRecipientShowRequest, + AdminAbuseReportNotificationRecipientShowResponse, + AdminAbuseReportNotificationRecipientCreateRequest, + AdminAbuseReportNotificationRecipientCreateResponse, + AdminAbuseReportNotificationRecipientUpdateRequest, + AdminAbuseReportNotificationRecipientUpdateResponse, + AdminAbuseReportNotificationRecipientDeleteRequest, AdminAccountsCreateRequest, AdminAccountsCreateResponse, AdminAccountsDeleteRequest, @@ -1228,6 +1294,15 @@ declare namespace entities { AdminRolesUpdateDefaultPoliciesRequest, AdminRolesUsersRequest, AdminRolesUsersResponse, + AdminSystemWebhookCreateRequest, + AdminSystemWebhookCreateResponse, + AdminSystemWebhookDeleteRequest, + AdminSystemWebhookListRequest, + AdminSystemWebhookListResponse, + AdminSystemWebhookShowRequest, + AdminSystemWebhookShowResponse, + AdminSystemWebhookUpdateRequest, + AdminSystemWebhookUpdateResponse, AnnouncementsRequest, AnnouncementsResponse, AnnouncementsShowRequest, @@ -1733,7 +1808,9 @@ declare namespace entities { ReversiGameDetailed, MetaLite, MetaDetailedOnly, - MetaDetailed + MetaDetailed, + SystemWebhook, + AbuseReportNotificationRecipient } } export { entities } @@ -2380,8 +2457,23 @@ type ModerationLog = { type: 'unsetUserAvatar'; info: ModerationLogPayloads['unsetUserAvatar']; } | { - type: 'unsetUserBanner'; - info: ModerationLogPayloads['unsetUserBanner']; + type: 'createSystemWebhook'; + info: ModerationLogPayloads['createSystemWebhook']; +} | { + type: 'updateSystemWebhook'; + info: ModerationLogPayloads['updateSystemWebhook']; +} | { + type: 'deleteSystemWebhook'; + info: ModerationLogPayloads['deleteSystemWebhook']; +} | { + type: 'createAbuseReportNotificationRecipient'; + info: ModerationLogPayloads['createAbuseReportNotificationRecipient']; +} | { + type: 'updateAbuseReportNotificationRecipient'; + info: ModerationLogPayloads['updateAbuseReportNotificationRecipient']; +} | { + type: 'deleteAbuseReportNotificationRecipient'; + info: ModerationLogPayloads['deleteAbuseReportNotificationRecipient']; }); // @public (undocumented) @@ -2921,6 +3013,9 @@ type SwUpdateRegistrationRequest = operations['sw___update-registration']['reque // @public (undocumented) type SwUpdateRegistrationResponse = operations['sw___update-registration']['responses']['200']['content']['application/json']; +// @public (undocumented) +type SystemWebhook = components['schemas']['SystemWebhook']; + // @public (undocumented) type TestRequest = operations['test']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/apiClientJSDoc.ts b/packages/misskey-js/src/autogen/apiClientJSDoc.ts index 181f7274b7..e799d4a0c5 100644 --- a/packages/misskey-js/src/autogen/apiClientJSDoc.ts +++ b/packages/misskey-js/src/autogen/apiClientJSDoc.ts @@ -25,6 +25,66 @@ declare module '../api.js' { credential?: string | null, ): Promise>; + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + /** * No description provided. * @@ -840,6 +900,66 @@ declare module '../api.js' { credential?: string | null, ): Promise>; + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + + /** + * No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + request( + endpoint: E, + params: P, + credential?: string | null, + ): Promise>; + /** * No description provided. * diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index ab3baf1670..20c8509d4c 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -4,6 +4,15 @@ import type { AdminMetaResponse, AdminAbuseUserReportsRequest, AdminAbuseUserReportsResponse, + AdminAbuseReportNotificationRecipientListRequest, + AdminAbuseReportNotificationRecipientListResponse, + AdminAbuseReportNotificationRecipientShowRequest, + AdminAbuseReportNotificationRecipientShowResponse, + AdminAbuseReportNotificationRecipientCreateRequest, + AdminAbuseReportNotificationRecipientCreateResponse, + AdminAbuseReportNotificationRecipientUpdateRequest, + AdminAbuseReportNotificationRecipientUpdateResponse, + AdminAbuseReportNotificationRecipientDeleteRequest, AdminAccountsCreateRequest, AdminAccountsCreateResponse, AdminAccountsDeleteRequest, @@ -99,6 +108,15 @@ import type { AdminRolesUpdateDefaultPoliciesRequest, AdminRolesUsersRequest, AdminRolesUsersResponse, + AdminSystemWebhookCreateRequest, + AdminSystemWebhookCreateResponse, + AdminSystemWebhookDeleteRequest, + AdminSystemWebhookListRequest, + AdminSystemWebhookListResponse, + AdminSystemWebhookShowRequest, + AdminSystemWebhookShowResponse, + AdminSystemWebhookUpdateRequest, + AdminSystemWebhookUpdateResponse, AnnouncementsRequest, AnnouncementsResponse, AnnouncementsShowRequest, @@ -558,6 +576,11 @@ import type { export type Endpoints = { 'admin/meta': { req: EmptyRequest; res: AdminMetaResponse }; 'admin/abuse-user-reports': { req: AdminAbuseUserReportsRequest; res: AdminAbuseUserReportsResponse }; + 'admin/abuse-report/notification-recipient/list': { req: AdminAbuseReportNotificationRecipientListRequest; res: AdminAbuseReportNotificationRecipientListResponse }; + 'admin/abuse-report/notification-recipient/show': { req: AdminAbuseReportNotificationRecipientShowRequest; res: AdminAbuseReportNotificationRecipientShowResponse }; + 'admin/abuse-report/notification-recipient/create': { req: AdminAbuseReportNotificationRecipientCreateRequest; res: AdminAbuseReportNotificationRecipientCreateResponse }; + 'admin/abuse-report/notification-recipient/update': { req: AdminAbuseReportNotificationRecipientUpdateRequest; res: AdminAbuseReportNotificationRecipientUpdateResponse }; + 'admin/abuse-report/notification-recipient/delete': { req: AdminAbuseReportNotificationRecipientDeleteRequest; res: EmptyResponse }; 'admin/accounts/create': { req: AdminAccountsCreateRequest; res: AdminAccountsCreateResponse }; 'admin/accounts/delete': { req: AdminAccountsDeleteRequest; res: EmptyResponse }; 'admin/accounts/find-by-email': { req: AdminAccountsFindByEmailRequest; res: AdminAccountsFindByEmailResponse }; @@ -632,6 +655,11 @@ export type Endpoints = { 'admin/roles/unassign': { req: AdminRolesUnassignRequest; res: EmptyResponse }; 'admin/roles/update-default-policies': { req: AdminRolesUpdateDefaultPoliciesRequest; res: EmptyResponse }; 'admin/roles/users': { req: AdminRolesUsersRequest; res: AdminRolesUsersResponse }; + 'admin/system-webhook/create': { req: AdminSystemWebhookCreateRequest; res: AdminSystemWebhookCreateResponse }; + 'admin/system-webhook/delete': { req: AdminSystemWebhookDeleteRequest; res: EmptyResponse }; + 'admin/system-webhook/list': { req: AdminSystemWebhookListRequest; res: AdminSystemWebhookListResponse }; + 'admin/system-webhook/show': { req: AdminSystemWebhookShowRequest; res: AdminSystemWebhookShowResponse }; + 'admin/system-webhook/update': { req: AdminSystemWebhookUpdateRequest; res: AdminSystemWebhookUpdateResponse }; 'announcements': { req: AnnouncementsRequest; res: AnnouncementsResponse }; 'announcements/show': { req: AnnouncementsShowRequest; res: AnnouncementsShowResponse }; 'antennas/create': { req: AntennasCreateRequest; res: AntennasCreateResponse }; diff --git a/packages/misskey-js/src/autogen/entities.ts b/packages/misskey-js/src/autogen/entities.ts index 02ca932d8a..357b5e9eaf 100644 --- a/packages/misskey-js/src/autogen/entities.ts +++ b/packages/misskey-js/src/autogen/entities.ts @@ -7,6 +7,15 @@ export type EmptyResponse = Record | undefined; export type AdminMetaResponse = operations['admin___meta']['responses']['200']['content']['application/json']; export type AdminAbuseUserReportsRequest = operations['admin___abuse-user-reports']['requestBody']['content']['application/json']; export type AdminAbuseUserReportsResponse = operations['admin___abuse-user-reports']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientListRequest = operations['admin___abuse-report___notification-recipient___list']['requestBody']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientListResponse = operations['admin___abuse-report___notification-recipient___list']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientShowRequest = operations['admin___abuse-report___notification-recipient___show']['requestBody']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientShowResponse = operations['admin___abuse-report___notification-recipient___show']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientCreateRequest = operations['admin___abuse-report___notification-recipient___create']['requestBody']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientCreateResponse = operations['admin___abuse-report___notification-recipient___create']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientUpdateRequest = operations['admin___abuse-report___notification-recipient___update']['requestBody']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientUpdateResponse = operations['admin___abuse-report___notification-recipient___update']['responses']['200']['content']['application/json']; +export type AdminAbuseReportNotificationRecipientDeleteRequest = operations['admin___abuse-report___notification-recipient___delete']['requestBody']['content']['application/json']; export type AdminAccountsCreateRequest = operations['admin___accounts___create']['requestBody']['content']['application/json']; export type AdminAccountsCreateResponse = operations['admin___accounts___create']['responses']['200']['content']['application/json']; export type AdminAccountsDeleteRequest = operations['admin___accounts___delete']['requestBody']['content']['application/json']; @@ -102,6 +111,15 @@ export type AdminRolesUnassignRequest = operations['admin___roles___unassign'][' export type AdminRolesUpdateDefaultPoliciesRequest = operations['admin___roles___update-default-policies']['requestBody']['content']['application/json']; export type AdminRolesUsersRequest = operations['admin___roles___users']['requestBody']['content']['application/json']; export type AdminRolesUsersResponse = operations['admin___roles___users']['responses']['200']['content']['application/json']; +export type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json']; +export type AdminSystemWebhookCreateResponse = operations['admin___system-webhook___create']['responses']['200']['content']['application/json']; +export type AdminSystemWebhookDeleteRequest = operations['admin___system-webhook___delete']['requestBody']['content']['application/json']; +export type AdminSystemWebhookListRequest = operations['admin___system-webhook___list']['requestBody']['content']['application/json']; +export type AdminSystemWebhookListResponse = operations['admin___system-webhook___list']['responses']['200']['content']['application/json']; +export type AdminSystemWebhookShowRequest = operations['admin___system-webhook___show']['requestBody']['content']['application/json']; +export type AdminSystemWebhookShowResponse = operations['admin___system-webhook___show']['responses']['200']['content']['application/json']; +export type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___update']['requestBody']['content']['application/json']; +export type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json']; export type AnnouncementsRequest = operations['announcements']['requestBody']['content']['application/json']; export type AnnouncementsResponse = operations['announcements']['responses']['200']['content']['application/json']; export type AnnouncementsShowRequest = operations['announcements___show']['requestBody']['content']['application/json']; diff --git a/packages/misskey-js/src/autogen/models.ts b/packages/misskey-js/src/autogen/models.ts index a6e5fbe689..04574849d4 100644 --- a/packages/misskey-js/src/autogen/models.ts +++ b/packages/misskey-js/src/autogen/models.ts @@ -51,3 +51,5 @@ export type ReversiGameDetailed = components['schemas']['ReversiGameDetailed']; export type MetaLite = components['schemas']['MetaLite']; export type MetaDetailedOnly = components['schemas']['MetaDetailedOnly']; export type MetaDetailed = components['schemas']['MetaDetailed']; +export type SystemWebhook = components['schemas']['SystemWebhook']; +export type AbuseReportNotificationRecipient = components['schemas']['AbuseReportNotificationRecipient']; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 2c80676f3e..bdcc1dfd77 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -30,6 +30,56 @@ export type paths = { */ post: operations['admin___abuse-user-reports']; }; + '/admin/abuse-report/notification-recipient/list': { + /** + * admin/abuse-report/notification-recipient/list + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* + */ + post: operations['admin___abuse-report___notification-recipient___list']; + }; + '/admin/abuse-report/notification-recipient/show': { + /** + * admin/abuse-report/notification-recipient/show + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* + */ + post: operations['admin___abuse-report___notification-recipient___show']; + }; + '/admin/abuse-report/notification-recipient/create': { + /** + * admin/abuse-report/notification-recipient/create + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + post: operations['admin___abuse-report___notification-recipient___create']; + }; + '/admin/abuse-report/notification-recipient/update': { + /** + * admin/abuse-report/notification-recipient/update + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + post: operations['admin___abuse-report___notification-recipient___update']; + }; + '/admin/abuse-report/notification-recipient/delete': { + /** + * admin/abuse-report/notification-recipient/delete + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + post: operations['admin___abuse-report___notification-recipient___delete']; + }; '/admin/accounts/create': { /** * admin/accounts/create @@ -697,6 +747,56 @@ export type paths = { */ post: operations['admin___roles___users']; }; + '/admin/system-webhook/create': { + /** + * admin/system-webhook/create + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + post: operations['admin___system-webhook___create']; + }; + '/admin/system-webhook/delete': { + /** + * admin/system-webhook/delete + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + post: operations['admin___system-webhook___delete']; + }; + '/admin/system-webhook/list': { + /** + * admin/system-webhook/list + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + post: operations['admin___system-webhook___list']; + }; + '/admin/system-webhook/show': { + /** + * admin/system-webhook/show + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + post: operations['admin___system-webhook___show']; + }; + '/admin/system-webhook/update': { + /** + * admin/system-webhook/update + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + post: operations['admin___system-webhook___update']; + }; '/announcements': { /** * announcements @@ -4859,6 +4959,32 @@ export type components = { cacheRemoteSensitiveFiles: boolean; }; MetaDetailed: components['schemas']['MetaLite'] & components['schemas']['MetaDetailedOnly']; + SystemWebhook: { + id: string; + isActive: boolean; + /** Format: date-time */ + updatedAt: string; + /** Format: date-time */ + latestSentAt: string | null; + latestStatus: number | null; + name: string; + on: ('abuseReport' | 'abuseReportResolved')[]; + url: string; + secret: string; + }; + AbuseReportNotificationRecipient: { + id: string; + isActive: boolean; + /** Format: date-time */ + updatedAt: string; + name: string; + /** @enum {string} */ + method: 'email' | 'webhook'; + userId?: string; + user?: components['schemas']['UserLite']; + systemWebhookId?: string; + systemWebhook?: components['schemas']['SystemWebhook']; + }; }; responses: never; parameters: never; @@ -5125,6 +5251,292 @@ export type operations = { }; }; }; + /** + * admin/abuse-report/notification-recipient/list + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* + */ + 'admin___abuse-report___notification-recipient___list': { + requestBody: { + content: { + 'application/json': { + method?: ('email' | 'webhook')[]; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['AbuseReportNotificationRecipient'][]; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/abuse-report/notification-recipient/show + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *read:admin:abuse-report:notification-recipient* + */ + 'admin___abuse-report___notification-recipient___show': { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + id: string; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['AbuseReportNotificationRecipient']; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/abuse-report/notification-recipient/create + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + 'admin___abuse-report___notification-recipient___create': { + requestBody: { + content: { + 'application/json': { + isActive: boolean; + name: string; + /** @enum {string} */ + method: 'email' | 'webhook'; + /** Format: misskey:id */ + userId?: string; + /** Format: misskey:id */ + systemWebhookId?: string; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['AbuseReportNotificationRecipient']; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/abuse-report/notification-recipient/update + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + 'admin___abuse-report___notification-recipient___update': { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + id: string; + isActive: boolean; + name: string; + /** @enum {string} */ + method: 'email' | 'webhook'; + /** Format: misskey:id */ + userId?: string; + /** Format: misskey:id */ + systemWebhookId?: string; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['AbuseReportNotificationRecipient']; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/abuse-report/notification-recipient/delete + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:abuse-report:notification-recipient* + */ + 'admin___abuse-report___notification-recipient___delete': { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + id: string; + }; + }; + }; + responses: { + /** @description OK (without any results) */ + 204: { + content: never; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; /** * admin/accounts/create * @description No description provided. @@ -9615,6 +10027,287 @@ export type operations = { }; }; }; + /** + * admin/system-webhook/create + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + 'admin___system-webhook___create': { + requestBody: { + content: { + 'application/json': { + isActive: boolean; + name: string; + on: ('abuseReport' | 'abuseReportResolved')[]; + url: string; + secret: string; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['SystemWebhook']; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/system-webhook/delete + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + 'admin___system-webhook___delete': { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + id: string; + }; + }; + }; + responses: { + /** @description OK (without any results) */ + 204: { + content: never; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/system-webhook/list + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + 'admin___system-webhook___list': { + requestBody: { + content: { + 'application/json': { + isActive?: boolean; + on?: ('abuseReport' | 'abuseReportResolved')[]; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['SystemWebhook'][]; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/system-webhook/show + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + 'admin___system-webhook___show': { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + id: string; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['SystemWebhook']; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; + /** + * admin/system-webhook/update + * @description No description provided. + * + * **Internal Endpoint**: This endpoint is an API for the misskey mainframe and is not intended for use by third parties. + * **Credential required**: *Yes* / **Permission**: *write:admin:system-webhook* + */ + 'admin___system-webhook___update': { + requestBody: { + content: { + 'application/json': { + /** Format: misskey:id */ + id: string; + isActive: boolean; + name: string; + on: ('abuseReport' | 'abuseReportResolved')[]; + url: string; + secret: string; + }; + }; + }; + responses: { + /** @description OK (with results) */ + 200: { + content: { + 'application/json': components['schemas']['SystemWebhook']; + }; + }; + /** @description Client error */ + 400: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Authentication error */ + 401: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Forbidden error */ + 403: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description I'm Ai */ + 418: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + /** @description Internal server error */ + 500: { + content: { + 'application/json': components['schemas']['Error']; + }; + }; + }; + }; /** * announcements * @description No description provided. diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts index fd6ef4d68d..03b9069290 100644 --- a/packages/misskey-js/src/consts.ts +++ b/packages/misskey-js/src/consts.ts @@ -325,4 +325,30 @@ export type ModerationLogPayloads = { userHost: string | null; fileId: string; }; + createSystemWebhook: { + systemWebhookId: string; + webhook: any; + }; + updateSystemWebhook: { + systemWebhookId: string; + before: any; + after: any; + }; + deleteSystemWebhook: { + systemWebhookId: string; + webhook: any; + }; + createAbuseReportNotificationRecipient: { + recipientId: string; + recipient: any; + }; + updateAbuseReportNotificationRecipient: { + recipientId: string; + before: any; + after: any; + }; + deleteAbuseReportNotificationRecipient: { + recipientId: string; + recipient: any; + }; }; diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index 35503d6d6f..7a84cb6a1a 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -132,8 +132,23 @@ export type ModerationLog = { type: 'unsetUserAvatar'; info: ModerationLogPayloads['unsetUserAvatar']; } | { - type: 'unsetUserBanner'; - info: ModerationLogPayloads['unsetUserBanner']; + type: 'createSystemWebhook'; + info: ModerationLogPayloads['createSystemWebhook']; +} | { + type: 'updateSystemWebhook'; + info: ModerationLogPayloads['updateSystemWebhook']; +} | { + type: 'deleteSystemWebhook'; + info: ModerationLogPayloads['deleteSystemWebhook']; +} | { + type: 'createAbuseReportNotificationRecipient'; + info: ModerationLogPayloads['createAbuseReportNotificationRecipient']; +} | { + type: 'updateAbuseReportNotificationRecipient'; + info: ModerationLogPayloads['updateAbuseReportNotificationRecipient']; +} | { + type: 'deleteAbuseReportNotificationRecipient'; + info: ModerationLogPayloads['deleteAbuseReportNotificationRecipient']; }); export type ServerStats = { From 9849aab40283cbde2184e74d4795aec8ef8ccba3 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Sat, 8 Jun 2024 18:00:54 +0900 Subject: [PATCH 018/246] test(#10336): add `components/MkC.*` stories (#13830) * test(storybook): add `components/MkC.*` stories * test(storybook): add some tests * test: add sleep * test: comment-out flaky test * test(storybook): add test for `MkChannelFollowButton` * chore(storybook): tweak sleep duration in `MkChannelFollowButton` story test * fix(chromatic): add delay to `MkChannelList` * chore: replace `mswDecorator` with `mswLoader` * fix(storybook): tweak some parameters * chore: serve static files * fix(chromatic): add delay to `MkCwButton` * chore: delete logging for debug * fix: add right click in `MkContextMenu` play * refactor: remove unused imports --- packages/frontend/.storybook/fakes.ts | 60 +++++++++ packages/frontend/.storybook/generate.tsx | 2 +- packages/frontend/.storybook/main.ts | 1 + packages/frontend/.storybook/preview.ts | 4 +- packages/frontend/package.json | 2 + .../MkChannelFollowButton.stories.impl.ts | 77 ++++++++++++ .../src/components/MkChannelFollowButton.vue | 5 +- .../components/MkChannelList.stories.impl.ts | 65 ++++++++++ .../MkChannelPreview.stories.impl.ts | 43 +++++++ .../src/components/MkChart.stories.impl.ts | 117 ++++++++++++++++++ packages/frontend/src/components/MkChart.vue | 90 ++++++++------ .../components/MkChartLegend.stories.impl.ts | 7 ++ .../components/MkChartTooltip.stories.impl.ts | 7 ++ .../components/MkClickerGame.stories.impl.ts | 79 ++++++++++++ .../frontend/src/components/MkClickerGame.vue | 2 +- .../components/MkClipPreview.stories.impl.ts | 43 +++++++ .../components/MkCode.core.stories.impl.ts | 7 ++ .../src/components/MkCode.stories.impl.ts | 44 +++++++ .../components/MkCodeEditor.stories.impl.ts | 62 ++++++++++ .../components/MkCodeInline.stories.impl.ts | 37 ++++++ .../components/MkColorInput.stories.impl.ts | 50 ++++++++ .../components/MkContainer.stories.impl.ts | 7 ++ .../components/MkContextMenu.stories.impl.ts | 58 +++++++++ .../MkCropperDialog.stories.impl.ts | 75 +++++++++++ ...kCustomEmojiDetailedDialog.stories.impl.ts | 38 ++++++ .../src/components/MkCwButton.stories.impl.ts | 89 +++++++++++++ packages/frontend/src/scripts/test-utils.ts | 10 ++ pnpm-lock.yaml | 88 +++++++------ 28 files changed, 1083 insertions(+), 86 deletions(-) create mode 100644 packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts create mode 100644 packages/frontend/src/components/MkChannelList.stories.impl.ts create mode 100644 packages/frontend/src/components/MkChannelPreview.stories.impl.ts create mode 100644 packages/frontend/src/components/MkChart.stories.impl.ts create mode 100644 packages/frontend/src/components/MkChartLegend.stories.impl.ts create mode 100644 packages/frontend/src/components/MkChartTooltip.stories.impl.ts create mode 100644 packages/frontend/src/components/MkClickerGame.stories.impl.ts create mode 100644 packages/frontend/src/components/MkClipPreview.stories.impl.ts create mode 100644 packages/frontend/src/components/MkCode.core.stories.impl.ts create mode 100644 packages/frontend/src/components/MkCode.stories.impl.ts create mode 100644 packages/frontend/src/components/MkCodeEditor.stories.impl.ts create mode 100644 packages/frontend/src/components/MkCodeInline.stories.impl.ts create mode 100644 packages/frontend/src/components/MkColorInput.stories.impl.ts create mode 100644 packages/frontend/src/components/MkContainer.stories.impl.ts create mode 100644 packages/frontend/src/components/MkContextMenu.stories.impl.ts create mode 100644 packages/frontend/src/components/MkCropperDialog.stories.impl.ts create mode 100644 packages/frontend/src/components/MkCustomEmojiDetailedDialog.stories.impl.ts create mode 100644 packages/frontend/src/components/MkCwButton.stories.impl.ts diff --git a/packages/frontend/.storybook/fakes.ts b/packages/frontend/.storybook/fakes.ts index 3a24ccb248..fdb155261b 100644 --- a/packages/frontend/.storybook/fakes.ts +++ b/packages/frontend/.storybook/fakes.ts @@ -22,6 +22,66 @@ export function abuseUserReport() { }; } +export function channel(id = 'somechannelid', name = 'Some Channel', bannerUrl: string | null = 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/fedi.jpg?raw=true'): entities.Channel { + return { + id, + createdAt: '2016-12-28T22:49:51.000Z', + lastNotedAt: '2016-12-28T22:49:51.000Z', + name, + description: null, + userId: null, + bannerUrl, + pinnedNoteIds: [], + color: '#000', + isArchived: false, + usersCount: 1, + notesCount: 1, + isSensitive: false, + allowRenoteToExternal: false, + }; +} + +export function clip(id = 'someclipid', name = 'Some Clip'): entities.Clip { + return { + id, + createdAt: '2016-12-28T22:49:51.000Z', + lastClippedAt: null, + userId: 'someuserid', + user: { + id: 'someuserid', + name: 'Misskey User', + username: 'miskist', + host: 'misskey-hub.net', + avatarUrl: 'https://github.com/misskey-dev/misskey/blob/master/packages/frontend/assets/about-icon.png?raw=true', + avatarBlurhash: 'eQFRshof5NWBRi},juayfPju53WB?0ofs;s*a{ofjuay^SoMEJR%ay', + avatarDecorations: [], + emojis: {}, + badgeRoles: [], + onlineStatus: 'unknown', + }, + notesCount: undefined, + name, + description: 'Some clip description', + isPublic: false, + favoritedCount: 0, + }; +} + +export function emojiDetailed(id = 'someemojiid', name = 'some_emoji'): entities.EmojiDetailed { + return { + id, + aliases: ['alias1', 'alias2'], + name, + category: 'emojiCategory', + host: null, + url: '/client-assets/about-icon.png', + license: null, + isSensitive: false, + localOnly: false, + roleIdsThatCanBeUsedThisEmojiAsReaction: ['roleId1', 'roleId2'], + }; +} + export function galleryPost(isSensitive = false) { return { id: 'somepostid', diff --git a/packages/frontend/.storybook/generate.tsx b/packages/frontend/.storybook/generate.tsx index d74c83a500..d21eea9d17 100644 --- a/packages/frontend/.storybook/generate.tsx +++ b/packages/frontend/.storybook/generate.tsx @@ -397,7 +397,7 @@ function toStories(component: string): Promise { const globs = await Promise.all([ glob('src/components/global/Mk*.vue'), glob('src/components/global/RouterView.vue'), - glob('src/components/Mk{A,B}*.vue'), + glob('src/components/Mk[A-C]*.vue'), glob('src/components/MkDigitalClock.vue'), glob('src/components/MkGalleryPostPreview.vue'), glob('src/components/MkSignupServerRules.vue'), diff --git a/packages/frontend/.storybook/main.ts b/packages/frontend/.storybook/main.ts index d3822942cd..9f318cf449 100644 --- a/packages/frontend/.storybook/main.ts +++ b/packages/frontend/.storybook/main.ts @@ -15,6 +15,7 @@ const _dirname = fileURLToPath(new URL('.', import.meta.url)); const config = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], + staticDirs: [{ from: '../assets', to: '/client-assets' }], addons: [ getAbsolutePath('@storybook/addon-essentials'), getAbsolutePath('@storybook/addon-interactions'), diff --git a/packages/frontend/.storybook/preview.ts b/packages/frontend/.storybook/preview.ts index 982a2979ac..73ee007fb8 100644 --- a/packages/frontend/.storybook/preview.ts +++ b/packages/frontend/.storybook/preview.ts @@ -7,7 +7,7 @@ import { FORCE_REMOUNT } from '@storybook/core-events'; import { addons } from '@storybook/preview-api'; import { type Preview, setup } from '@storybook/vue3'; import isChromatic from 'chromatic/isChromatic'; -import { initialize, mswDecorator } from 'msw-storybook-addon'; +import { initialize, mswLoader } from 'msw-storybook-addon'; import { userDetailed } from './fakes.js'; import locale from './locale.js'; import { commonHandlers, onUnhandledRequest } from './mocks.js'; @@ -122,7 +122,6 @@ const preview = { } return story; }, - mswDecorator, (Story, context) => { return { setup() { @@ -137,6 +136,7 @@ const preview = { }; }, ], + loaders: [mswLoader], parameters: { controls: { exclude: /^__/, diff --git a/packages/frontend/package.json b/packages/frontend/package.json index 56b824c0c5..66940a1601 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -104,6 +104,7 @@ "@types/node": "20.12.7", "@types/punycode": "2.1.4", "@types/sanitize-html": "2.11.0", + "@types/seedrandom": "3.0.8", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", "@types/uuid": "9.0.8", @@ -128,6 +129,7 @@ "prettier": "3.2.5", "react": "18.3.1", "react-dom": "18.3.1", + "seedrandom": "3.0.5", "start-server-and-test": "2.0.3", "storybook": "8.0.9", "storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme", diff --git a/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts b/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts new file mode 100644 index 0000000000..b99620da22 --- /dev/null +++ b/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts @@ -0,0 +1,77 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +/* eslint-disable import/no-default-export */ +import { StoryObj } from '@storybook/vue3'; +import { HttpResponse, http } from 'msw'; +import { action } from '@storybook/addon-actions'; +import { expect, userEvent, within } from '@storybook/test'; +import { channel } from '../../.storybook/fakes.js'; +import { commonHandlers } from '../../.storybook/mocks.js'; +import MkChannelFollowButton from './MkChannelFollowButton.vue'; +import { semaphore } from '@/scripts/test-utils.js'; +import { i18n } from '@/i18n.js'; + +function sleep(ms: number) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + +const s = semaphore(); +export const Default = { + render(args) { + return { + components: { + MkChannelFollowButton, + }, + setup() { + return { + args, + }; + }, + computed: { + props() { + return { + ...this.args, + }; + }, + }, + template: '', + }; + }, + args: { + channel: channel(), + full: true, + }, + async play({ canvasElement }) { + await s.acquire(); + await sleep(1000); + const canvas = within(canvasElement); + const buttonElement = canvas.getByRole('button'); + await expect(buttonElement).toHaveTextContent(i18n.ts.follow); + await userEvent.click(buttonElement); + await sleep(1000); + await expect(buttonElement).toHaveTextContent(i18n.ts.unfollow); + await sleep(100); + await userEvent.click(buttonElement); + s.release(); + }, + parameters: { + layout: 'centered', + msw: { + handlers: [ + ...commonHandlers, + http.post('/api/channels/follow', async ({ request }) => { + action('POST /api/channels/follow')(await request.json()); + return HttpResponse.json({}); + }), + http.post('/api/channels/unfollow', async ({ request }) => { + action('POST /api/channels/unfollow')(await request.json()); + return HttpResponse.json({}); + }), + ], + }, + }, +} satisfies StoryObj; diff --git a/packages/frontend/src/components/MkChannelFollowButton.vue b/packages/frontend/src/components/MkChannelFollowButton.vue index 6b1b380e41..841d37a568 100644 --- a/packages/frontend/src/components/MkChannelFollowButton.vue +++ b/packages/frontend/src/components/MkChannelFollowButton.vue @@ -26,17 +26,18 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/widgets/WidgetProfile.vue b/packages/frontend/src/widgets/WidgetProfile.vue index a5578d4de6..ae39098305 100644 --- a/packages/frontend/src/widgets/WidgetProfile.vue +++ b/packages/frontend/src/widgets/WidgetProfile.vue @@ -82,16 +82,19 @@ defineExpose({ .body { text-overflow: ellipsis; overflow: clip; + margin-left: -10px; + padding: 10px; } .name { color: #fff; - filter: drop-shadow(0 0 4px #000); + filter: drop-shadow(0 0 4px #000) drop-shadow(0 0 0.1px rgba(0, 0, 0, 0.5)); font-weight: bold; } .username { color: #fff; - filter: drop-shadow(0 0 4px #000); + filter: drop-shadow(0 0 4px #000) drop-shadow(0 0 0.1px rgba(0, 0, 0, 0.5)); + font-weight: normal; } From ac12ab8629f0a0172250f949a98ee1efb1d0890d Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Sat, 22 Jun 2024 12:51:02 +0900 Subject: [PATCH 050/246] =?UTF-8?q?fix(backend):=20=E3=83=95=E3=82=A3?= =?UTF-8?q?=E3=83=BC=E3=83=89=E3=81=AE=E3=83=8E=E3=83=BC=E3=83=88=E3=81=AE?= =?UTF-8?q?MFM=E3=81=AFHTML=E3=81=AB=E3=83=AC=E3=83=B3=E3=83=80=E3=83=BC?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=81=8B=E3=82=89=E8=BF=94=E3=81=99=20(#1400?= =?UTF-8?q?6)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(backend): フィードのノートのMFMはHTMLにレンダーしてから返す (test wip) * chore: beforeEachを使う? * fix: プレーンテキストにフォールバックしてMFMが含まれていないか調べる方針を実装 * fix: application/jsonだとパースされるのでその作用をキャンセル * build: fix lint error * docs: update CHANGELOG.md --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 1 + packages/backend/src/server/web/FeedService.ts | 6 +++++- packages/backend/test/e2e/fetch-resource.ts | 17 +++++++++++++++++ packages/backend/test/utils.ts | 5 +++-- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c5eb698385..ab9f5f8000 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Server - チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 - Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949) +- Fix: ユーザーのフィードページのMFMをHTMLに展開するように (#14006) - Fix: アンテナ・クリップ・リスト・ウェブフックがロールポリシーの上限より一つ多く作れてしまうのを修正 (#14036) - Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059) - Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正 diff --git a/packages/backend/src/server/web/FeedService.ts b/packages/backend/src/server/web/FeedService.ts index 10e3ed2682..9d810ddc84 100644 --- a/packages/backend/src/server/web/FeedService.ts +++ b/packages/backend/src/server/web/FeedService.ts @@ -14,6 +14,8 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { bindThis } from '@/decorators.js'; import { IdService } from '@/core/IdService.js'; +import { MfmService } from "@/core/MfmService.js"; +import { parse as mfmParse } from 'mfm-js'; @Injectable() export class FeedService { @@ -33,6 +35,7 @@ export class FeedService { private userEntityService: UserEntityService, private driveFileEntityService: DriveFileEntityService, private idService: IdService, + private mfmService: MfmService, ) { } @@ -76,13 +79,14 @@ export class FeedService { id: In(note.fileIds), }) : []; const file = files.find(file => file.type.startsWith('image/')); + const text = note.text; feed.addItem({ title: `New note by ${author.name}`, link: `${this.config.url}/notes/${note.id}`, date: this.idService.parse(note.id).date, description: note.cw ?? undefined, - content: note.text ?? undefined, + content: text ? this.mfmService.toHtml(mfmParse(text), JSON.parse(note.mentionedRemoteUsers)) ?? undefined : undefined, image: file ? this.driveFileEntityService.getPublicUrl(file) : undefined, }); } diff --git a/packages/backend/test/e2e/fetch-resource.ts b/packages/backend/test/e2e/fetch-resource.ts index 4851ed14be..7efd688ec2 100644 --- a/packages/backend/test/e2e/fetch-resource.ts +++ b/packages/backend/test/e2e/fetch-resource.ts @@ -153,6 +153,23 @@ describe('Webリソース', () => { path: path('nonexisting'), status: 404, })); + + describe(' has entry such ', () => { + beforeEach(() => { + post(alice, { text: "**a**" }) + }); + + test('MFMを含まない。', async () => { + const content = await simpleGet(path(alice.username), "*/*", undefined, res => res.text()); + const _body: unknown = content.body; + // JSONフィードのときは改めて文字列化する + const body: string = typeof (_body) === "object" ? JSON.stringify(_body) : _body as string; + + if (body.includes("**a**")) { + throw new Error("MFM shouldn't be included"); + } + }); + }) }); describe.each([{ path: '/api/foo' }])('$path', ({ path }) => { diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index 86814fffe0..aad4ab37c9 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -17,6 +17,7 @@ import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/val import { entities } from '../src/postgres.js'; import { loadConfig } from '../src/config.js'; import type * as misskey from 'misskey-js'; +import { type Response } from 'node-fetch'; export { server as startServer, jobQueue as startJobQueue } from '@/boot/common.js'; @@ -454,7 +455,7 @@ export type SimpleGetResponse = { type: string | null, location: string | null }; -export const simpleGet = async (path: string, accept = '*/*', cookie: any = undefined): Promise => { +export const simpleGet = async (path: string, accept = '*/*', cookie: any = undefined, bodyExtractor: (res: Response) => Promise = _ => Promise.resolve(null)): Promise => { const res = await relativeFetch(path, { headers: { Accept: accept, @@ -482,7 +483,7 @@ export const simpleGet = async (path: string, accept = '*/*', cookie: any = unde const body = jsonTypes.includes(res.headers.get('content-type') ?? '') ? await res.json() : htmlTypes.includes(res.headers.get('content-type') ?? '') ? new JSDOM(await res.text()) : - null; + await bodyExtractor(res); return { status: res.status, From b50eb511b0cf6fb05d37c3370726f940c1438a99 Mon Sep 17 00:00:00 2001 From: yupix Date: Sat, 22 Jun 2024 14:52:27 +0900 Subject: [PATCH 051/246] =?UTF-8?q?refactor:=20api/*/update=E7=B3=BB?= =?UTF-8?q?=E3=81=AE=E5=BF=85=E9=A0=88=E3=82=AD=E3=83=BC=E3=82=92=E6=9C=80?= =?UTF-8?q?=E4=BD=8E=E9=99=90=E3=81=AB=20(#13824)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: clips/updateの必須キーをclipIdのみに * refactor: admin/roles/update の必須キーをroleIdのみに * feat: pages/update の必須キーをpageIdのみに * refactor: gallery/posts/update の必須キーをpostidのみに * feat: misskey-jsの型を更新 * feat: i/webhooks/updateの必須キーをwebhookIdのみに * feat: admin/ad/updateの必須キーをidのみに * feat: misskey-jsの型を更新 * chore: update CHANGELOG.md * docs: update CHANGELOG.md * fix: secretが更新できなくなる場合がある Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com> * Update packages/backend/src/server/api/endpoints/gallery/posts/update.ts --------- Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 6 ++ .../server/api/endpoints/admin/ad/update.ts | 6 +- .../api/endpoints/admin/roles/update.ts | 14 ---- .../src/server/api/endpoints/clips/update.ts | 4 +- .../api/endpoints/gallery/posts/update.ts | 24 ++++--- .../server/api/endpoints/i/webhooks/update.ts | 6 +- .../src/server/api/endpoints/pages/update.ts | 23 ++---- packages/misskey-js/src/autogen/types.ts | 71 +++++++++---------- 8 files changed, 70 insertions(+), 84 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab9f5f8000..c1af63ad23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,12 @@ - Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949) - Fix: ユーザーのフィードページのMFMをHTMLに展開するように (#14006) - Fix: アンテナ・クリップ・リスト・ウェブフックがロールポリシーの上限より一つ多く作れてしまうのを修正 (#14036) +- Enhance: エンドポイント`clips/update`の必須項目を`clipId`のみに +- Enhance: エンドポイント`admin/roles/update`の必須項目を`roleId`のみに +- Enhance: エンドポイント`pages/update`の必須項目を`pageId`のみに +- Enhance: エンドポイント`gallery/posts/update`の必須項目を`postId`のみに +- Enhance: エンドポイント`i/webhook/update`の必須項目を`webhookId`のみに +- Enhance: エンドポイント`admin/ad/update`の必須項目を`id`のみに - Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059) - Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正 diff --git a/packages/backend/src/server/api/endpoints/admin/ad/update.ts b/packages/backend/src/server/api/endpoints/admin/ad/update.ts index 62358457ff..4e3d731aca 100644 --- a/packages/backend/src/server/api/endpoints/admin/ad/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/ad/update.ts @@ -40,7 +40,7 @@ export const paramDef = { startsAt: { type: 'integer' }, dayOfWeek: { type: 'integer' }, }, - required: ['id', 'memo', 'url', 'imageUrl', 'place', 'priority', 'ratio', 'expiresAt', 'startsAt', 'dayOfWeek'], + required: ['id'], } as const; @Injectable() @@ -63,8 +63,8 @@ export default class extends Endpoint { // eslint- ratio: ps.ratio, memo: ps.memo, imageUrl: ps.imageUrl, - expiresAt: new Date(ps.expiresAt), - startsAt: new Date(ps.startsAt), + expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : undefined, + startsAt: ps.startsAt ? new Date(ps.startsAt) : undefined, dayOfWeek: ps.dayOfWeek, }); diff --git a/packages/backend/src/server/api/endpoints/admin/roles/update.ts b/packages/backend/src/server/api/endpoints/admin/roles/update.ts index 5242e0be2f..465ad7aaaf 100644 --- a/packages/backend/src/server/api/endpoints/admin/roles/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/roles/update.ts @@ -6,7 +6,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import type { RolesRepository } from '@/models/_.js'; -import { GlobalEventService } from '@/core/GlobalEventService.js'; import { DI } from '@/di-symbols.js'; import { ApiError } from '@/server/api/error.js'; import { RoleService } from '@/core/RoleService.js'; @@ -50,19 +49,6 @@ export const paramDef = { }, required: [ 'roleId', - 'name', - 'description', - 'color', - 'iconUrl', - 'target', - 'condFormula', - 'isPublic', - 'isModerator', - 'isAdministrator', - 'asBadge', - 'canEditMembersByModerator', - 'displayOrder', - 'policies', ], } as const; diff --git a/packages/backend/src/server/api/endpoints/clips/update.ts b/packages/backend/src/server/api/endpoints/clips/update.ts index 3b44ba81b3..603a3ccf3d 100644 --- a/packages/backend/src/server/api/endpoints/clips/update.ts +++ b/packages/backend/src/server/api/endpoints/clips/update.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { Inject, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { Endpoint } from '@/server/api/endpoint-base.js'; import { ClipEntityService } from '@/core/entities/ClipEntityService.js'; import { ClipService } from '@/core/ClipService.js'; @@ -41,7 +41,7 @@ export const paramDef = { isPublic: { type: 'boolean' }, description: { type: 'string', nullable: true, minLength: 1, maxLength: 2048 }, }, - required: ['clipId', 'name'], + required: ['clipId'], } as const; @Injectable() diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts index 2f977784ec..5243ee9603 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts @@ -47,7 +47,7 @@ export const paramDef = { } }, isSensitive: { type: 'boolean', default: false }, }, - required: ['postId', 'title', 'fileIds'], + required: ['postId'], } as const; @Injectable() @@ -62,15 +62,19 @@ export default class extends Endpoint { // eslint- private galleryPostEntityService: GalleryPostEntityService, ) { super(meta, paramDef, async (ps, me) => { - const files = (await Promise.all(ps.fileIds.map(fileId => - this.driveFilesRepository.findOneBy({ - id: fileId, - userId: me.id, - }), - ))).filter(x => x != null); + let files: Array | undefined; - if (files.length === 0) { - throw new Error(); + if (ps.fileIds) { + files = (await Promise.all(ps.fileIds.map(fileId => + this.driveFilesRepository.findOneBy({ + id: fileId, + userId: me.id, + }), + ))).filter(x => x != null); + + if (files.length === 0) { + throw new Error(); + } } await this.galleryPostsRepository.update({ @@ -81,7 +85,7 @@ export default class extends Endpoint { // eslint- title: ps.title, description: ps.description, isSensitive: ps.isSensitive, - fileIds: files.map(file => file.id), + fileIds: files ? files.map(file => file.id) : undefined, }); const post = await this.galleryPostsRepository.findOneByOrFail({ id: ps.postId }); diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/update.ts b/packages/backend/src/server/api/endpoints/i/webhooks/update.ts index 6e380d76f8..07a25bd82a 100644 --- a/packages/backend/src/server/api/endpoints/i/webhooks/update.ts +++ b/packages/backend/src/server/api/endpoints/i/webhooks/update.ts @@ -34,13 +34,13 @@ export const paramDef = { webhookId: { type: 'string', format: 'misskey:id' }, name: { type: 'string', minLength: 1, maxLength: 100 }, url: { type: 'string', minLength: 1, maxLength: 1024 }, - secret: { type: 'string', maxLength: 1024, default: '' }, + secret: { type: 'string', nullable: true, maxLength: 1024 }, on: { type: 'array', items: { type: 'string', enum: webhookEventTypes, } }, active: { type: 'boolean' }, }, - required: ['webhookId', 'name', 'url', 'on', 'active'], + required: ['webhookId'], } as const; // TODO: ロジックをサービスに切り出す @@ -66,7 +66,7 @@ export default class extends Endpoint { // eslint- await this.webhooksRepository.update(webhook.id, { name: ps.name, url: ps.url, - secret: ps.secret, + secret: ps.secret === null ? '' : ps.secret, on: ps.on, active: ps.active, }); diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts index b8e5e70a25..f11bbbcb1a 100644 --- a/packages/backend/src/server/api/endpoints/pages/update.ts +++ b/packages/backend/src/server/api/endpoints/pages/update.ts @@ -70,7 +70,7 @@ export const paramDef = { alignCenter: { type: 'boolean' }, hideTitleWhenPinned: { type: 'boolean' }, }, - required: ['pageId', 'title', 'name', 'content', 'variables', 'script'], + required: ['pageId'], } as const; @Injectable() @@ -91,9 +91,8 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.accessDenied); } - let eyeCatchingImage = null; if (ps.eyeCatchingImageId != null) { - eyeCatchingImage = await this.driveFilesRepository.findOneBy({ + const eyeCatchingImage = await this.driveFilesRepository.findOneBy({ id: ps.eyeCatchingImageId, userId: me.id, }); @@ -116,23 +115,15 @@ export default class extends Endpoint { // eslint- await this.pagesRepository.update(page.id, { updatedAt: new Date(), title: ps.title, - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - name: ps.name === undefined ? page.name : ps.name, + name: ps.name, summary: ps.summary === undefined ? page.summary : ps.summary, content: ps.content, variables: ps.variables, script: ps.script, - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - alignCenter: ps.alignCenter === undefined ? page.alignCenter : ps.alignCenter, - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - hideTitleWhenPinned: ps.hideTitleWhenPinned === undefined ? page.hideTitleWhenPinned : ps.hideTitleWhenPinned, - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - font: ps.font === undefined ? page.font : ps.font, - eyeCatchingImageId: ps.eyeCatchingImageId === null - ? null - : ps.eyeCatchingImageId === undefined - ? page.eyeCatchingImageId - : eyeCatchingImage!.id, + alignCenter: ps.alignCenter, + hideTitleWhenPinned: ps.hideTitleWhenPinned, + font: ps.font, + eyeCatchingImageId: ps.eyeCatchingImageId, }); }); } diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index bdcc1dfd77..72aca4dee2 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -5881,15 +5881,15 @@ export type operations = { 'application/json': { /** Format: misskey:id */ id: string; - memo: string; - url: string; - imageUrl: string; - place: string; - priority: string; - ratio: number; - expiresAt: number; - startsAt: number; - dayOfWeek: number; + memo?: string; + url?: string; + imageUrl?: string; + place?: string; + priority?: string; + ratio?: number; + expiresAt?: number; + startsAt?: number; + dayOfWeek?: number; }; }; }; @@ -9744,21 +9744,21 @@ export type operations = { 'application/json': { /** Format: misskey:id */ roleId: string; - name: string; - description: string; - color: string | null; - iconUrl: string | null; + name?: string; + description?: string; + color?: string | null; + iconUrl?: string | null; /** @enum {string} */ - target: 'manual' | 'conditional'; - condFormula: Record; - isPublic: boolean; - isModerator: boolean; - isAdministrator: boolean; + target?: 'manual' | 'conditional'; + condFormula?: Record; + isPublic?: boolean; + isModerator?: boolean; + isAdministrator?: boolean; isExplorable?: boolean; - asBadge: boolean; - canEditMembersByModerator: boolean; - displayOrder: number; - policies: Record; + asBadge?: boolean; + canEditMembersByModerator?: boolean; + displayOrder?: number; + policies?: Record; }; }; }; @@ -13400,7 +13400,7 @@ export type operations = { 'application/json': { /** Format: misskey:id */ clipId: string; - name: string; + name?: string; isPublic?: boolean; description?: string | null; }; @@ -16247,9 +16247,9 @@ export type operations = { 'application/json': { /** Format: misskey:id */ postId: string; - title: string; + title?: string; description?: string | null; - fileIds: string[]; + fileIds?: string[]; /** @default false */ isSensitive?: boolean; }; @@ -20030,12 +20030,11 @@ export type operations = { 'application/json': { /** Format: misskey:id */ webhookId: string; - name: string; - url: string; - /** @default */ - secret?: string; - on: ('mention' | 'unfollow' | 'follow' | 'followed' | 'note' | 'reply' | 'renote' | 'reaction')[]; - active: boolean; + name?: string; + url?: string; + secret?: string | null; + on?: ('mention' | 'unfollow' | 'follow' | 'followed' | 'note' | 'reply' | 'renote' | 'reaction')[]; + active?: boolean; }; }; }; @@ -23404,16 +23403,16 @@ export type operations = { 'application/json': { /** Format: misskey:id */ pageId: string; - title: string; - name: string; + title?: string; + name?: string; summary?: string | null; - content: { + content?: { [key: string]: unknown; }[]; - variables: { + variables?: { [key: string]: unknown; }[]; - script: string; + script?: string; /** Format: misskey:id */ eyeCatchingImageId?: string | null; /** @enum {string} */ From faeab96e01c7c7be5dfc85716b4a0b05b93f50ab Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Sat, 22 Jun 2024 14:55:24 +0900 Subject: [PATCH 052/246] ci: add quote (#13990) --- .github/workflows/storybook.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/storybook.yml b/.github/workflows/storybook.yml index c52883ffdd..daa76509c8 100644 --- a/.github/workflows/storybook.yml +++ b/.github/workflows/storybook.yml @@ -88,7 +88,7 @@ jobs: if [ "$BRANCH" = "misskey-dev:$HEAD_REF" ]; then BRANCH="$HEAD_REF" fi - pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name $BRANCH $(echo "$CHROMATIC_PARAMETER") + pnpm --filter frontend chromatic --exit-once-uploaded -d storybook-static --branch-name "$BRANCH" $(echo "$CHROMATIC_PARAMETER") env: HEAD_REF: ${{ github.event.pull_request.head.ref }} CHROMATIC_PROJECT_TOKEN: ${{ secrets.CHROMATIC_PROJECT_TOKEN }} From bf403aa656627fc4b29aed329aa044d42a791acf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 22 Jun 2024 15:35:54 +0900 Subject: [PATCH 053/246] =?UTF-8?q?fix(frontend):=20=E3=83=99=E3=83=BC?= =?UTF-8?q?=E3=82=B9=E3=83=AD=E3=83=BC=E3=83=AB=E3=82=92=E7=B7=A8=E9=9B=86?= =?UTF-8?q?=E3=81=97=E3=81=A6=E3=82=82UI=E4=B8=8A=E3=81=A7=E3=81=AF?= =?UTF-8?q?=E5=A4=89=E6=9B=B4=E3=81=8C=E5=8F=8D=E6=98=A0=E3=81=95=E3=82=8C?= =?UTF-8?q?=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=E3=82=92=E4=BF=AE=E6=AD=A3?= =?UTF-8?q?=20(#13995)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): ベースロールを変更してもUI上では変更が反映されない問題を修正 * Update CHANGELOG.md --- CHANGELOG.md | 1 + packages/frontend/src/pages/admin/roles.vue | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c1af63ad23..a913e42500 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ - Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正 - Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968) - Fix: リバーシの対局を正しく共有できないことがある問題を修正 +- Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正 ### Server - チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 diff --git a/packages/frontend/src/pages/admin/roles.vue b/packages/frontend/src/pages/admin/roles.vue index 9753d9f6cb..50323e3de5 100644 --- a/packages/frontend/src/pages/admin/roles.vue +++ b/packages/frontend/src/pages/admin/roles.vue @@ -243,7 +243,7 @@ import * as os from '@/os.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; -import { instance } from '@/instance.js'; +import { instance, fetchInstance } from '@/instance.js'; import MkFoldableSection from '@/components/MkFoldableSection.vue'; import { ROLE_POLICIES } from '@/const.js'; import { useRouter } from '@/router/supplier.js'; @@ -267,6 +267,7 @@ async function updateBaseRole() { await os.apiWithDialog('admin/roles/update-default-policies', { policies, }); + fetchInstance(true); } function create() { From 7c22a64b8c505f6e6c9da0fec16902fcd9af773f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sat, 22 Jun 2024 16:52:27 +0900 Subject: [PATCH 054/246] =?UTF-8?q?fix(backend):=20=E8=87=AA=E5=88=86?= =?UTF-8?q?=E4=BB=A5=E5=A4=96=E3=81=AE=E3=82=AF=E3=83=AA=E3=83=83=E3=83=97?= =?UTF-8?q?=E5=86=85=E3=81=AE=E3=83=8E=E3=83=BC=E3=83=88=E5=80=8B=E6=95=B0?= =?UTF-8?q?=E3=81=8C=E8=A6=8B=E3=81=88=E3=82=8B=E3=81=AE=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=20(#14065)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(backend): 自分以外のクリップ内のノート個数が見えることがあるのを修正 * Update Changelog * fix --- CHANGELOG.md | 1 + packages/backend/src/core/entities/ClipEntityService.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a913e42500..e4c4cfe1f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ - Enhance: エンドポイント`admin/ad/update`の必須項目を`id`のみに - Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059) - Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正 +- Fix: 自分以外のクリップ内のノート個数が見えることがあるのを修正 ## 2024.5.0 diff --git a/packages/backend/src/core/entities/ClipEntityService.ts b/packages/backend/src/core/entities/ClipEntityService.ts index 3855a28436..d915645906 100644 --- a/packages/backend/src/core/entities/ClipEntityService.ts +++ b/packages/backend/src/core/entities/ClipEntityService.ts @@ -53,7 +53,7 @@ export class ClipEntityService { isPublic: clip.isPublic, favoritedCount: await this.clipFavoritesRepository.countBy({ clipId: clip.id }), isFavorited: meId ? await this.clipFavoritesRepository.exists({ where: { clipId: clip.id, userId: meId } }) : undefined, - notesCount: meId ? await this.clipNotesRepository.countBy({ clipId: clip.id }) : undefined, + notesCount: (meId === clip.userId) ? await this.clipNotesRepository.countBy({ clipId: clip.id }) : undefined, }); } From 9368eb3038d5f655b924d53800daaa7e54e08c47 Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Sat, 22 Jun 2024 19:40:55 +0900 Subject: [PATCH 055/246] refactor: say bye to the weird groupBy friends (#13975) * refactor(frontend): say bye to the weird groupBy friends * refactor(backend): say bye to the weird groupBy friends --- packages/backend/src/misc/prelude/array.ts | 38 ---------------------- packages/frontend/src/scripts/array.ts | 38 ---------------------- 2 files changed, 76 deletions(-) diff --git a/packages/backend/src/misc/prelude/array.ts b/packages/backend/src/misc/prelude/array.ts index dbfe1fff18..f741a0c913 100644 --- a/packages/backend/src/misc/prelude/array.ts +++ b/packages/backend/src/misc/prelude/array.ts @@ -65,44 +65,6 @@ export function maximum(xs: number[]): number { return Math.max(...xs); } -/** - * Splits an array based on the equivalence relation. - * The concatenation of the result is equal to the argument. - */ -export function groupBy(f: EndoRelation, xs: T[]): T[][] { - const groups = [] as T[][]; - for (const x of xs) { - const lastGroup = groups.at(-1); - if (lastGroup !== undefined && f(lastGroup[0], x)) { - lastGroup.push(x); - } else { - groups.push([x]); - } - } - return groups; -} - -/** - * Splits an array based on the equivalence relation induced by the function. - * The concatenation of the result is equal to the argument. - */ -export function groupOn(f: (x: T) => S, xs: T[]): T[][] { - return groupBy((a, b) => f(a) === f(b), xs); -} - -export function groupByX(collections: T[], keySelector: (x: T) => string) { - return collections.reduce((obj: Record, item: T) => { - const key = keySelector(item); - if (!Object.prototype.hasOwnProperty.call(obj, key)) { - obj[key] = []; - } - - obj[key].push(item); - - return obj; - }, {}); -} - /** * Compare two arrays by lexicographical order */ diff --git a/packages/frontend/src/scripts/array.ts b/packages/frontend/src/scripts/array.ts index b3d76e149f..f2feb29dfc 100644 --- a/packages/frontend/src/scripts/array.ts +++ b/packages/frontend/src/scripts/array.ts @@ -77,44 +77,6 @@ export function maximum(xs: number[]): number { return Math.max(...xs); } -/** - * Splits an array based on the equivalence relation. - * The concatenation of the result is equal to the argument. - */ -export function groupBy(f: EndoRelation, xs: T[]): T[][] { - const groups = [] as T[][]; - for (const x of xs) { - const lastGroup = groups.at(-1); - if (lastGroup !== undefined && f(lastGroup[0], x)) { - lastGroup.push(x); - } else { - groups.push([x]); - } - } - return groups; -} - -/** - * Splits an array based on the equivalence relation induced by the function. - * The concatenation of the result is equal to the argument. - */ -export function groupOn(f: (x: T) => S, xs: T[]): T[][] { - return groupBy((a, b) => f(a) === f(b), xs); -} - -export function groupByX(collections: T[], keySelector: (x: T) => string) { - return collections.reduce((obj: Record, item: T) => { - const key = keySelector(item); - if (typeof obj[key] === 'undefined') { - obj[key] = []; - } - - obj[key].push(item); - - return obj; - }, {}); -} - /** * Compare two arrays by lexicographical order */ From b8b4dc50384aa3f146d90b10d7f13f87a4a2232c Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sat, 22 Jun 2024 19:45:08 +0900 Subject: [PATCH 056/246] build: install pnpm with corepack on docker build (#13926) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build: install pnpm with corepack on build * docs(changelog): Dockerコンテナの立ち上げ時に`pnpm`のインストールで固まることがある問題 --- CHANGELOG.md | 1 + Dockerfile | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4c4cfe1f0..ca74d71719 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ### General - Feat: 通報を受けた際、または解決した際に、予め登録した宛先に通知を飛ばせるように(mail or webhook) #13705 - Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正 +- Fix: Dockerコンテナの立ち上げ時に`pnpm`のインストールで固まることがある問題 ### Client - Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正 diff --git a/Dockerfile b/Dockerfile index 9fc2d611cd..d6ca6b8cdf 100644 --- a/Dockerfile +++ b/Dockerfile @@ -82,6 +82,10 @@ RUN apt-get update \ USER misskey WORKDIR /misskey +# add package.json to add pnpm +COPY --chown=misskey:misskey ./package.json ./package.json +RUN corepack install + COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/node_modules ./packages/backend/node_modules COPY --chown=misskey:misskey --from=target-builder /misskey/packages/misskey-js/node_modules ./packages/misskey-js/node_modules From 00b213373bd3f60a6144344ab8cbda08418ca1e4 Mon Sep 17 00:00:00 2001 From: woxtu Date: Sat, 22 Jun 2024 19:46:29 +0900 Subject: [PATCH 057/246] Remove @types/node-fetch (#13948) --- packages/backend/package.json | 1 - pnpm-lock.yaml | 11 ----------- 2 files changed, 12 deletions(-) diff --git a/packages/backend/package.json b/packages/backend/package.json index 15134b1ca8..0467ab0bee 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -207,7 +207,6 @@ "@types/mime-types": "2.1.4", "@types/ms": "0.7.34", "@types/node": "20.12.7", - "@types/node-fetch": "3.0.3", "@types/nodemailer": "6.4.15", "@types/oauth": "0.9.4", "@types/oauth2orize": "1.11.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1281f7eefe..09df15853b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -586,9 +586,6 @@ importers: '@types/node': specifier: 20.12.7 version: 20.12.7 - '@types/node-fetch': - specifier: 3.0.3 - version: 3.0.3 '@types/nodemailer': specifier: 6.4.15 version: 6.4.15 @@ -4625,10 +4622,6 @@ packages: '@types/node-fetch@2.6.4': resolution: {integrity: sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==} - '@types/node-fetch@3.0.3': - resolution: {integrity: sha512-HhggYPH5N+AQe/OmN6fmhKmRRt2XuNJow+R3pQwJxOOF9GuwM7O2mheyGeIrs5MOIeNjDEdgdoyHBOrFeJBR3g==} - deprecated: This is a stub types definition. node-fetch provides its own type definitions, so you do not need this installed. - '@types/node@18.17.15': resolution: {integrity: sha512-2yrWpBk32tvV/JAd3HNHWuZn/VDN1P+72hWirHnvsvTGSqbANi+kSeuQR9yAHnbvaBvHDsoTdXV0Fe+iRtHLKA==} @@ -16025,10 +16018,6 @@ snapshots: '@types/node': 20.12.7 form-data: 3.0.1 - '@types/node-fetch@3.0.3': - dependencies: - node-fetch: 3.3.2 - '@types/node@18.17.15': {} '@types/node@20.11.5': From 961cb6c5eeb7745dc156327d2041241b70098b70 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Sat, 22 Jun 2024 19:49:38 +0900 Subject: [PATCH 058/246] fix(backend): fix creating reactions bugs (#13901) * fix(backend): add fallback for empty string when creating reaction * fix(backend): prohibit reactions to Renote * test(backend): add some tests for `notes/reactions/create` endpoint * Update CHANGELOG.md * lint * Update CHANGELOG.md --------- Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 2 + packages/backend/src/core/ReactionService.ts | 8 ++- .../api/endpoints/notes/reactions/create.ts | 7 +++ packages/backend/test/e2e/endpoints.ts | 61 +++++++++++++++++++ 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca74d71719..354bbd20fd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ - Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059) - Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正 - Fix: 自分以外のクリップ内のノート個数が見えることがあるのを修正 +- Fix: 空文字列のリアクションはフォールバックされるように +- Fix: リノートにリアクションできないように ## 2024.5.0 diff --git a/packages/backend/src/core/ReactionService.ts b/packages/backend/src/core/ReactionService.ts index cb0b079df0..64c7b2ed03 100644 --- a/packages/backend/src/core/ReactionService.ts +++ b/packages/backend/src/core/ReactionService.ts @@ -29,6 +29,7 @@ import { CustomEmojiService } from '@/core/CustomEmojiService.js'; import { RoleService } from '@/core/RoleService.js'; import { FeaturedService } from '@/core/FeaturedService.js'; import { trackPromise } from '@/misc/promise-tracker.js'; +import { isQuote, isRenote } from '@/misc/is-renote.js'; const FALLBACK = '\u2764'; const PER_NOTE_REACTION_USER_PAIR_CACHE_MAX = 16; @@ -117,11 +118,16 @@ export class ReactionService { throw new IdentifiableError('68e9d2d1-48bf-42c2-b90a-b20e09fd3d48', 'Note not accessible for you.'); } + // Check if note is Renote + if (isRenote(note) && !isQuote(note)) { + throw new IdentifiableError('12c35529-3c79-4327-b1cc-e2cf63a71925', 'You cannot react to Renote.'); + } + let reaction = _reaction ?? FALLBACK; if (note.reactionAcceptance === 'likeOnly' || ((note.reactionAcceptance === 'likeOnlyForRemote' || note.reactionAcceptance === 'nonSensitiveOnlyForLocalLikeOnlyForRemote') && (user.host != null))) { reaction = '\u2764'; - } else if (_reaction) { + } else if (_reaction != null) { const custom = reaction.match(isCustomEmojiRegexp); if (custom) { const reacterHost = this.utilityService.toPunyNullable(user.host); diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/create.ts b/packages/backend/src/server/api/endpoints/notes/reactions/create.ts index b9899608bf..0f0dcca605 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions/create.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions/create.ts @@ -36,6 +36,12 @@ export const meta = { code: 'YOU_HAVE_BEEN_BLOCKED', id: '20ef5475-9f38-4e4c-bd33-de6d979498ec', }, + + cannotReactToRenote: { + message: 'You cannot react to Renote.', + code: 'CANNOT_REACT_TO_RENOTE', + id: 'eaccdc08-ddef-43fe-908f-d108faad57f5', + }, }, } as const; @@ -62,6 +68,7 @@ export default class extends Endpoint { // eslint- await this.reactionService.create(me, note, ps.reaction).catch(err => { if (err.id === '51c42bb4-931a-456b-bff7-e5a8a70dd298') throw new ApiError(meta.errors.alreadyReacted); if (err.id === 'e70412a4-7197-4726-8e74-f3e0deb92aa7') throw new ApiError(meta.errors.youHaveBeenBlocked); + if (err.id === '12c35529-3c79-4327-b1cc-e2cf63a71925') throw new ApiError(meta.errors.cannotReactToRenote); throw err; }); return; diff --git a/packages/backend/test/e2e/endpoints.ts b/packages/backend/test/e2e/endpoints.ts index bc89dc37f4..de5e8ba95e 100644 --- a/packages/backend/test/e2e/endpoints.ts +++ b/packages/backend/test/e2e/endpoints.ts @@ -266,6 +266,67 @@ describe('Endpoints', () => { assert.strictEqual(res.status, 400); }); + test('リノートにリアクションできない', async () => { + const bobNote = await post(bob, { text: 'hi' }); + const bobRenote = await post(bob, { renoteId: bobNote.id }); + + const res = await api('notes/reactions/create', { + noteId: bobRenote.id, + reaction: '🚀', + }, alice); + + assert.strictEqual(res.status, 400); + assert.strictEqual(res.body.error.code, 'CANNOT_REACT_TO_RENOTE'); + }); + + test('引用にリアクションできる', async () => { + const bobNote = await post(bob, { text: 'hi' }); + const bobRenote = await post(bob, { text: 'hi again', renoteId: bobNote.id }); + + const res = await api('notes/reactions/create', { + noteId: bobRenote.id, + reaction: '🚀', + }, alice); + + assert.strictEqual(res.status, 204); + }); + + test('空文字列のリアクションは\u2764にフォールバックされる', async () => { + const bobNote = await post(bob, { text: 'hi' }); + + const res = await api('notes/reactions/create', { + noteId: bobNote.id, + reaction: '', + }, alice); + + assert.strictEqual(res.status, 204); + + const reaction = await api('notes/reactions', { + noteId: bobNote.id, + }); + + assert.strictEqual(reaction.body.length, 1); + assert.strictEqual(reaction.body[0].type, '\u2764'); + }); + + test('絵文字ではない文字列のリアクションは\u2764にフォールバックされる', async () => { + const bobNote = await post(bob, { text: 'hi' }); + + const res = await api('notes/reactions/create', { + noteId: bobNote.id, + reaction: 'Hello!', + }, alice); + + assert.strictEqual(res.status, 204); + + const reaction = await api('notes/reactions', { + noteId: bobNote.id, + }); + + assert.strictEqual(reaction.body.length, 1); + assert.strictEqual(reaction.body[0].type, '\u2764'); + }); + test('空のパラメータで怒られる', async () => { // @ts-expect-error param must not be empty const res = await api('notes/reactions/create', {}, alice); From 2acbec6891a94dc9291b3e0c3d2e24d13367ba1c Mon Sep 17 00:00:00 2001 From: Ibuki Sugiyama Date: Sat, 22 Jun 2024 19:50:32 +0900 Subject: [PATCH 059/246] enhance: update datasaver switch titles (#12834) --- locales/ja-JP.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 3ac1ce82a3..0d89d33abe 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2599,16 +2599,16 @@ _externalResourceInstaller: _dataSaver: _media: - title: "メディアの読み込み" + title: "メディアの読み込みを無効化" description: "画像・動画が自動で読み込まれるのを防止します。隠れている画像・動画はタップすると読み込まれます。" _avatar: - title: "アイコン画像" + title: "アイコン画像のアニメーションを無効化" description: "アイコン画像のアニメーションが停止します。アニメーション画像は通常の画像よりファイルサイズが大きいことがあるので、データ通信量をさらに削減できます。" _urlPreview: - title: "URLプレビューのサムネイル" + title: "URLプレビューのサムネイルを非表示" description: "URLプレビューのサムネイル画像が読み込まれなくなります。" _code: - title: "コードハイライト" + title: "コードハイライトを非表示" description: "MFMなどでコードハイライト記法が使われている場合、タップするまで読み込まれなくなります。コードハイライトではハイライトする言語ごとにその定義ファイルを読み込む必要がありますが、それらが自動で読み込まれなくなるため、通信量の削減が見込めます。" _hemisphere: From b269c431686b04fbfc256c5a1fe621bc70f7ea06 Mon Sep 17 00:00:00 2001 From: woxtu Date: Sun, 23 Jun 2024 01:00:12 +0900 Subject: [PATCH 060/246] Fix type annotations (#14071) --- packages/frontend/src/filters/user.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/filters/user.ts b/packages/frontend/src/filters/user.ts index b713d41789..a87766764d 100644 --- a/packages/frontend/src/filters/user.ts +++ b/packages/frontend/src/filters/user.ts @@ -6,7 +6,7 @@ import * as Misskey from 'misskey-js'; import { url } from '@/config.js'; -export const acct = (user: misskey.Acct) => { +export const acct = (user: Misskey.Acct) => { return Misskey.acct.toString(user); }; @@ -14,6 +14,6 @@ export const userName = (user: Misskey.entities.User) => { return user.name || user.username; }; -export const userPage = (user: misskey.Acct, path?, absolute = false) => { +export const userPage = (user: Misskey.Acct, path?: string, absolute = false) => { return `${absolute ? url : ''}/@${acct(user)}${(path ? `/${path}` : '')}`; }; From b95a0457a94b135df9b9511ef77558d1a81962f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 23 Jun 2024 19:04:01 +0900 Subject: [PATCH 061/246] fix(frontend): run `pnpm build-assets` (#14077) --- locales/index.d.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index acdc1fc421..ebd980ed85 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -9761,7 +9761,7 @@ export interface Locale extends ILocale { "_dataSaver": { "_media": { /** - * メディアの読み込み + * メディアの読み込みを無効化 */ "title": string; /** @@ -9771,7 +9771,7 @@ export interface Locale extends ILocale { }; "_avatar": { /** - * アイコン画像 + * アイコン画像のアニメーションを無効化 */ "title": string; /** @@ -9781,7 +9781,7 @@ export interface Locale extends ILocale { }; "_urlPreview": { /** - * URLプレビューのサムネイル + * URLプレビューのサムネイルを非表示 */ "title": string; /** @@ -9791,7 +9791,7 @@ export interface Locale extends ILocale { }; "_code": { /** - * コードハイライト + * コードハイライトを非表示 */ "title": string; /** From 634764e1a6e06ea9c117b720d58685fe99cae81a Mon Sep 17 00:00:00 2001 From: woxtu Date: Mon, 24 Jun 2024 21:32:12 +0900 Subject: [PATCH 062/246] refactor(frontend): Remove unused directives (#14085) --- packages/frontend/src/components/MkCaptcha.vue | 1 - packages/frontend/src/i18n.ts | 1 - 2 files changed, 2 deletions(-) diff --git a/packages/frontend/src/components/MkCaptcha.vue b/packages/frontend/src/components/MkCaptcha.vue index c64bb47e77..c5b6e0caed 100644 --- a/packages/frontend/src/components/MkCaptcha.vue +++ b/packages/frontend/src/components/MkCaptcha.vue @@ -104,7 +104,6 @@ async function requestRender() { }); } else if (props.provider === 'mcaptcha' && props.instanceUrl && props.sitekey) { const { default: Widget } = await import('@mcaptcha/vanilla-glue'); - // @ts-expect-error avoid typecheck error new Widget({ siteKey: { instanceUrl: new URL(props.instanceUrl), diff --git a/packages/frontend/src/i18n.ts b/packages/frontend/src/i18n.ts index cc9faddb20..10d6adbcd0 100644 --- a/packages/frontend/src/i18n.ts +++ b/packages/frontend/src/i18n.ts @@ -11,6 +11,5 @@ import { I18n } from '@/scripts/i18n.js'; export const i18n = markRaw(new I18n(locale)); export function updateI18n(newLocale: Locale) { - // @ts-expect-error -- private field i18n.locale = newLocale; } From 1c5d0cf5364ed841bd181b75682503a648a90bd6 Mon Sep 17 00:00:00 2001 From: yupix Date: Wed, 26 Jun 2024 10:25:18 +0900 Subject: [PATCH 063/246] =?UTF-8?q?feat:=20=E3=82=A2=E3=83=B3=E3=83=86?= =?UTF-8?q?=E3=83=8A=E3=81=AE=E7=B7=A8=E9=9B=86=E7=94=BB=E9=9D=A2=E3=81=AE?= =?UTF-8?q?=E3=83=9C=E3=82=BF=E3=83=B3=E3=81=ABgap=E3=82=92=E8=BF=BD?= =?UTF-8?q?=E5=8A=A0=20(#14091)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 1 + packages/frontend/src/pages/my-antennas/editor.vue | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 354bbd20fd..290b13ab36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968) - Fix: リバーシの対局を正しく共有できないことがある問題を修正 - Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正 +- Fix: アンテナの編集画面のボタンに隙間を追加 ### Server - チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 diff --git a/packages/frontend/src/pages/my-antennas/editor.vue b/packages/frontend/src/pages/my-antennas/editor.vue index 2949bfc02c..02e8f98265 100644 --- a/packages/frontend/src/pages/my-antennas/editor.vue +++ b/packages/frontend/src/pages/my-antennas/editor.vue @@ -41,8 +41,10 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts.withFileAntenna }}
- {{ i18n.ts.save }} - {{ i18n.ts.delete }} +
+ {{ i18n.ts.save }} + {{ i18n.ts.delete }} +
From 77012f2f2925c93978a3a5844d1adddd330d777b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AC=E3=82=8B=E3=81=8D=E3=82=83=E3=81=A3=E3=81=A8?= Date: Thu, 27 Jun 2024 10:40:46 +0900 Subject: [PATCH 064/246] =?UTF-8?q?fix(frontend):=20=E3=83=86=E3=83=BC?= =?UTF-8?q?=E3=83=9E=E3=83=97=E3=83=AC=E3=83=93=E3=83=A5=E3=83=BC=E3=81=8C?= =?UTF-8?q?=E8=A6=8B=E3=82=8C=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20(#14097)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): テーマプレビューが見れない問題を修正 * fix: MkPreview.vue, preview.vue --- .../frontend/src/components/MkPreview.vue | 150 ++++++++++++++++++ packages/frontend/src/pages/preview.vue | 26 +++ packages/frontend/src/router/definition.ts | 3 + 3 files changed, 179 insertions(+) create mode 100644 packages/frontend/src/components/MkPreview.vue create mode 100644 packages/frontend/src/pages/preview.vue diff --git a/packages/frontend/src/components/MkPreview.vue b/packages/frontend/src/components/MkPreview.vue new file mode 100644 index 0000000000..d950d66c6e --- /dev/null +++ b/packages/frontend/src/components/MkPreview.vue @@ -0,0 +1,150 @@ + + + + + + + diff --git a/packages/frontend/src/pages/preview.vue b/packages/frontend/src/pages/preview.vue new file mode 100644 index 0000000000..8e07b190aa --- /dev/null +++ b/packages/frontend/src/pages/preview.vue @@ -0,0 +1,26 @@ + + + + + diff --git a/packages/frontend/src/router/definition.ts b/packages/frontend/src/router/definition.ts index 8a443f627b..12ab633af1 100644 --- a/packages/frontend/src/router/definition.ts +++ b/packages/frontend/src/router/definition.ts @@ -251,6 +251,9 @@ const routes: RouteDef[] = [{ }, { path: '/scratchpad', component: page(() => import('@/pages/scratchpad.vue')), +}, { + path: '/preview', + component: page(() => import('@/pages/preview.vue')), }, { path: '/auth/:token', component: page(() => import('@/pages/auth.vue')), From 0e512d4ff6d2a7c56ac6295bf26d1101a3b6a317 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AC=E3=82=8B=E3=81=8D=E3=82=83=E3=81=A3=E3=81=A8?= Date: Thu, 27 Jun 2024 18:23:47 +0900 Subject: [PATCH 065/246] update: CHANGELOG.md for #14097 (#14099) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 290b13ab36..3a28c9ef64 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Fix: リバーシの対局を正しく共有できないことがある問題を修正 - Fix: コントロールパネルでベースロールのポリシーを編集してもUI上では変更が反映されない問題を修正 - Fix: アンテナの編集画面のボタンに隙間を追加 +- Fix: テーマプレビューが見れない問題を修正 ### Server - チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 From 4096dabe1e4b6ebb43e47fbee19954fb92adbdc7 Mon Sep 17 00:00:00 2001 From: woxtu Date: Thu, 27 Jun 2024 21:59:19 +0900 Subject: [PATCH 066/246] Add null checking (#14089) --- packages/frontend/src/components/MkFollowButton.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/frontend/src/components/MkFollowButton.vue b/packages/frontend/src/components/MkFollowButton.vue index 636e61db8f..6a4081079c 100644 --- a/packages/frontend/src/components/MkFollowButton.vue +++ b/packages/frontend/src/components/MkFollowButton.vue @@ -121,6 +121,8 @@ async function onClick() { }); hasPendingFollowRequestFromYou.value = true; + if ($i == null) return; + claimAchievement('following1'); if ($i.followingCount >= 10) { From a6edd50a5d292e29e6292754a7be95205ac7dbc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=AC=E3=82=8B=E3=81=8D=E3=82=83=E3=81=A3=E3=81=A8?= Date: Fri, 28 Jun 2024 11:16:12 +0900 Subject: [PATCH 067/246] =?UTF-8?q?chore(docker-compose):=20=E6=8E=A8?= =?UTF-8?q?=E5=A5=A8=E3=81=AE=E5=90=8D=E5=89=8D=E3=81=AB=E3=81=99=E3=82=8B?= =?UTF-8?q?=20(#14096)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore(docker-compose): 推奨の名前にする https://github.com/compose-spec/compose-spec/blob/5c18e329d5a15a15e4b636ed093b256b96615e33/spec.md#compose-file * yaml to yml * fix * fix --- .devcontainer/{docker-compose.yml => compose.yml} | 2 -- .devcontainer/devcontainer.json | 2 +- .dockerignore | 4 ++-- .github/workflows/dockle.yml | 2 +- .gitignore | 4 ++-- CONTRIBUTING.md | 2 +- docker-compose.local-db.yml => compose.local-db.yml | 2 -- docker-compose_example.yml => compose_example.yml | 2 -- packages/backend/test/{docker-compose.yml => compose.yml} | 2 -- 9 files changed, 7 insertions(+), 15 deletions(-) rename .devcontainer/{docker-compose.yml => compose.yml} (98%) rename docker-compose.local-db.yml => compose.local-db.yml (98%) rename docker-compose_example.yml => compose_example.yml (99%) rename packages/backend/test/{docker-compose.yml => compose.yml} (94%) diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/compose.yml similarity index 98% rename from .devcontainer/docker-compose.yml rename to .devcontainer/compose.yml index a52d086fb6..d02d2a8f4a 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/compose.yml @@ -1,5 +1,3 @@ -version: '3.8' - services: app: build: diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 344edbd65d..7ea23e314e 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,6 +1,6 @@ { "name": "Misskey", - "dockerComposeFile": "docker-compose.yml", + "dockerComposeFile": "compose.yml", "service": "app", "workspaceFolder": "/workspace", "features": { diff --git a/.dockerignore b/.dockerignore index 1de0c7982b..7dbb06e1d0 100644 --- a/.dockerignore +++ b/.dockerignore @@ -7,7 +7,7 @@ Dockerfile build/ built/ db/ -docker-compose.yml +.devcontainer/compose.yml node_modules/ packages/*/node_modules redis/ @@ -28,4 +28,4 @@ fluent-emojis/ .idea/ packages/*/.vscode/ -packages/backend/test/docker-compose.yml +packages/backend/test/compose.yml diff --git a/.github/workflows/dockle.yml b/.github/workflows/dockle.yml index 968971dd8d..c3dba4213d 100644 --- a/.github/workflows/dockle.yml +++ b/.github/workflows/dockle.yml @@ -22,7 +22,7 @@ jobs: sudo dpkg -i dockle.deb - run: | cp .config/docker_example.env .config/docker.env - cp ./docker-compose_example.yml ./docker-compose.yml + cp ./compose_example.yml ./compose.yml - run: | docker compose up -d web docker tag "$(docker compose images web | awk 'OFS=":" {print $4}' | tail -n +2)" misskey-web:latest diff --git a/.gitignore b/.gitignore index bdc14fea0a..3466984cf6 100644 --- a/.gitignore +++ b/.gitignore @@ -35,8 +35,8 @@ coverage !/.config/example.yml !/.config/docker_example.yml !/.config/docker_example.env -docker-compose.yml -!/.devcontainer/docker-compose.yml +.devcontainer/compose.yml +!/.devcontainer/compose.yml # misskey /build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dcb625626d..06c2d2f21d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,7 +165,7 @@ cp .github/misskey/test.yml .config/ ``` Prepare DB/Redis for testing. ``` -docker compose -f packages/backend/test/docker-compose.yml up +docker compose -f packages/backend/test/compose.yaml up ``` Alternatively, prepare an empty (data can be erased) DB and edit `.config/test.yml`. diff --git a/docker-compose.local-db.yml b/compose.local-db.yml similarity index 98% rename from docker-compose.local-db.yml rename to compose.local-db.yml index 16ba4b49e1..3835cb23db 100644 --- a/docker-compose.local-db.yml +++ b/compose.local-db.yml @@ -1,5 +1,3 @@ -version: "3" - # このconfigは、 dockerでMisskey本体を起動せず、 redisとpostgresql などだけを起動します services: diff --git a/docker-compose_example.yml b/compose_example.yml similarity index 99% rename from docker-compose_example.yml rename to compose_example.yml index 5cebbe4164..75d0d3a59c 100644 --- a/docker-compose_example.yml +++ b/compose_example.yml @@ -1,5 +1,3 @@ -version: "3" - services: web: build: . diff --git a/packages/backend/test/docker-compose.yml b/packages/backend/test/compose.yml similarity index 94% rename from packages/backend/test/docker-compose.yml rename to packages/backend/test/compose.yml index f2d8990758..6593fc33dd 100644 --- a/packages/backend/test/docker-compose.yml +++ b/packages/backend/test/compose.yml @@ -1,5 +1,3 @@ -version: "3" - services: redistest: image: redis:7 From f1b1e2a7cca3d69eb6162d4c16746968d855ea40 Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Tue, 2 Jul 2024 10:57:20 +0900 Subject: [PATCH 068/246] fix(storybook): prevent infinite remount of component (#14101) * fix(storybook): prevent infinite remount of component * fix: disable flaky `.toMatch()` test --- packages/frontend/.storybook/preview.ts | 6 +- .../MkChannelFollowButton.stories.impl.ts | 6 -- .../components/MkClickerGame.stories.impl.ts | 12 ++- .../src/components/MkCwButton.stories.impl.ts | 10 --- .../src/components/global/MkA.stories.impl.ts | 2 - .../components/global/MkAd.stories.impl.ts | 87 +++++++------------ packages/frontend/src/scripts/test-utils.ts | 10 --- 7 files changed, 41 insertions(+), 92 deletions(-) diff --git a/packages/frontend/.storybook/preview.ts b/packages/frontend/.storybook/preview.ts index 73ee007fb8..d000a28232 100644 --- a/packages/frontend/.storybook/preview.ts +++ b/packages/frontend/.storybook/preview.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { FORCE_REMOUNT } from '@storybook/core-events'; +import { FORCE_RE_RENDER, FORCE_REMOUNT } from '@storybook/core-events'; import { addons } from '@storybook/preview-api'; import { type Preview, setup } from '@storybook/vue3'; import isChromatic from 'chromatic/isChromatic'; @@ -16,7 +16,7 @@ import '../src/style.scss'; const appInitialized = Symbol(); -let lastStory = null; +let lastStory: string | null = null; let moduleInitialized = false; let unobserve = () => {}; let misskeyOS = null; @@ -110,7 +110,7 @@ const preview = { }).catch(() => {}); Promise.all([resetIndexedDBPromise, resetDefaultStorePromise]).then(() => { initLocalStorage(); - channel.emit(FORCE_REMOUNT, { storyId: context.id }); + channel.emit(FORCE_RE_RENDER, { storyId: context.id }); }); } const story = Story(); diff --git a/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts b/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts index b99620da22..b9770670dc 100644 --- a/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts +++ b/packages/frontend/src/components/MkChannelFollowButton.stories.impl.ts @@ -12,14 +12,12 @@ import { expect, userEvent, within } from '@storybook/test'; import { channel } from '../../.storybook/fakes.js'; import { commonHandlers } from '../../.storybook/mocks.js'; import MkChannelFollowButton from './MkChannelFollowButton.vue'; -import { semaphore } from '@/scripts/test-utils.js'; import { i18n } from '@/i18n.js'; function sleep(ms: number) { return new Promise(resolve => setTimeout(resolve, ms)); } -const s = semaphore(); export const Default = { render(args) { return { @@ -46,17 +44,13 @@ export const Default = { full: true, }, async play({ canvasElement }) { - await s.acquire(); - await sleep(1000); const canvas = within(canvasElement); const buttonElement = canvas.getByRole('button'); await expect(buttonElement).toHaveTextContent(i18n.ts.follow); await userEvent.click(buttonElement); await sleep(1000); await expect(buttonElement).toHaveTextContent(i18n.ts.unfollow); - await sleep(100); await userEvent.click(buttonElement); - s.release(); }, parameters: { layout: 'centered', diff --git a/packages/frontend/src/components/MkClickerGame.stories.impl.ts b/packages/frontend/src/components/MkClickerGame.stories.impl.ts index 8378010f8b..36313f965d 100644 --- a/packages/frontend/src/components/MkClickerGame.stories.impl.ts +++ b/packages/frontend/src/components/MkClickerGame.stories.impl.ts @@ -8,7 +8,7 @@ import { StoryObj } from '@storybook/vue3'; import { HttpResponse, http } from 'msw'; import { action } from '@storybook/addon-actions'; -import { expect, within } from '@storybook/test'; +import { expect, userEvent, within } from '@storybook/test'; import { commonHandlers } from '../../.storybook/mocks.js'; import MkClickerGame from './MkClickerGame.vue'; @@ -41,12 +41,10 @@ export const Default = { await sleep(1000); const canvas = within(canvasElement); const count = canvas.getByTestId('count'); - // NOTE: flaky なので N/A も通しておく - await expect(count).toHaveTextContent(/^(0|N\/A)$/); - // FIXME: flaky - // const buttonElement = canvas.getByRole('button'); - // await userEvent.click(buttonElement); - // await expect(count).toHaveTextContent('1'); + await expect(count).toHaveTextContent('0'); + const buttonElement = canvas.getByRole('button'); + await userEvent.click(buttonElement); + await expect(count).toHaveTextContent('1'); }, parameters: { layout: 'centered', diff --git a/packages/frontend/src/components/MkCwButton.stories.impl.ts b/packages/frontend/src/components/MkCwButton.stories.impl.ts index 05c6001552..5d6ea56da9 100644 --- a/packages/frontend/src/components/MkCwButton.stories.impl.ts +++ b/packages/frontend/src/components/MkCwButton.stories.impl.ts @@ -11,13 +11,6 @@ import { expect, userEvent, within } from '@storybook/test'; import { file } from '../../.storybook/fakes.js'; import MkCwButton from './MkCwButton.vue'; import { i18n } from '@/i18n.js'; -import { semaphore } from '@/scripts/test-utils.js'; - -function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -const s = semaphore(); export const Default = { render(args) { @@ -54,8 +47,6 @@ export const Default = { text: 'Some CW content', }, async play({ canvasElement }) { - await s.acquire(); - await sleep(1000); const canvas = within(canvasElement); const buttonElement = canvas.getByRole('button'); await expect(buttonElement).toHaveTextContent(i18n.ts._cw.show); @@ -63,7 +54,6 @@ export const Default = { await userEvent.click(buttonElement); await expect(buttonElement).toHaveTextContent(i18n.ts._cw.hide); await userEvent.click(buttonElement); - s.release(); }, parameters: { chromatic: { diff --git a/packages/frontend/src/components/global/MkA.stories.impl.ts b/packages/frontend/src/components/global/MkA.stories.impl.ts index c1d8cf0ca6..02e5a7f98c 100644 --- a/packages/frontend/src/components/global/MkA.stories.impl.ts +++ b/packages/frontend/src/components/global/MkA.stories.impl.ts @@ -35,12 +35,10 @@ export const Default = { // FIXME: 通るけどその後落ちるのでコメントアウト // await expect(a.href).toMatch(/^https?:\/\/.*#test$/); await userEvent.pointer({ keys: '[MouseRight]', target: a }); - await tick(); const menu = canvas.getByRole('menu'); await expect(menu).toBeInTheDocument(); await userEvent.click(a); a.blur(); - await tick(); await expect(menu).not.toBeInTheDocument(); }, args: { diff --git a/packages/frontend/src/components/global/MkAd.stories.impl.ts b/packages/frontend/src/components/global/MkAd.stories.impl.ts index aef26ab92d..8c0b7ef52f 100644 --- a/packages/frontend/src/components/global/MkAd.stories.impl.ts +++ b/packages/frontend/src/components/global/MkAd.stories.impl.ts @@ -9,12 +9,6 @@ import { StoryObj } from '@storybook/vue3'; import MkAd from './MkAd.vue'; import { i18n } from '@/i18n.js'; -let lock: Promise | undefined; - -function sleep(ms: number) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - const common = { render(args) { return { @@ -37,56 +31,41 @@ const common = { }; }, async play({ canvasElement, args }) { - if (lock) { - console.warn('This test is unexpectedly running twice in parallel, fix it!'); - console.warn('See also: https://github.com/misskey-dev/misskey/issues/11267'); - await lock; + const canvas = within(canvasElement); + const a = canvas.getByRole('link'); + // FIXME: 通るけどその後落ちるのでコメントアウト + // await expect(a.href).toMatch(/^https?:\/\/.*#test$/); + const img = within(a).getByRole('img'); + await expect(img).toBeInTheDocument(); + let buttons = canvas.getAllByRole('button'); + await expect(buttons).toHaveLength(1); + const i = buttons[0]; + await expect(i).toBeInTheDocument(); + await userEvent.click(i); + await expect(canvasElement).toHaveTextContent(i18n.ts._ad.back); + await expect(a).not.toBeInTheDocument(); + await expect(i).not.toBeInTheDocument(); + buttons = canvas.getAllByRole('button'); + const hasReduceFrequency = args.specify?.ratio !== 0; + await expect(buttons).toHaveLength(hasReduceFrequency ? 2 : 1); + const reduce = hasReduceFrequency ? buttons[0] : null; + const back = buttons[hasReduceFrequency ? 1 : 0]; + if (reduce) { + await expect(reduce).toBeInTheDocument(); + await expect(reduce).toHaveTextContent(i18n.ts._ad.reduceFrequencyOfThisAd); } - - let resolve: (value?: any) => void; - lock = new Promise(r => resolve = r); - - try { - // NOTE: sleep しないと何故か落ちる - await sleep(100); - const canvas = within(canvasElement); - const a = canvas.getByRole('link'); - // await expect(a.href).toMatch(/^https?:\/\/.*#test$/); - const img = within(a).getByRole('img'); - await expect(img).toBeInTheDocument(); - let buttons = canvas.getAllByRole('button'); - await expect(buttons).toHaveLength(1); - const i = buttons[0]; - await expect(i).toBeInTheDocument(); - await userEvent.click(i); - await expect(canvasElement).toHaveTextContent(i18n.ts._ad.back); - await expect(a).not.toBeInTheDocument(); - await expect(i).not.toBeInTheDocument(); - buttons = canvas.getAllByRole('button'); - const hasReduceFrequency = args.specify?.ratio !== 0; - await expect(buttons).toHaveLength(hasReduceFrequency ? 2 : 1); - const reduce = hasReduceFrequency ? buttons[0] : null; - const back = buttons[hasReduceFrequency ? 1 : 0]; - if (reduce) { - await expect(reduce).toBeInTheDocument(); - await expect(reduce).toHaveTextContent(i18n.ts._ad.reduceFrequencyOfThisAd); - } - await expect(back).toBeInTheDocument(); - await expect(back).toHaveTextContent(i18n.ts._ad.back); - await userEvent.click(back); - await waitFor(() => expect(canvas.queryByRole('img')).toBeTruthy()); - if (reduce) { - await expect(reduce).not.toBeInTheDocument(); - } - await expect(back).not.toBeInTheDocument(); - const aAgain = canvas.getByRole('link'); - await expect(aAgain).toBeInTheDocument(); - const imgAgain = within(aAgain).getByRole('img'); - await expect(imgAgain).toBeInTheDocument(); - } finally { - resolve!(); - lock = undefined; + await expect(back).toBeInTheDocument(); + await expect(back).toHaveTextContent(i18n.ts._ad.back); + await userEvent.click(back); + await waitFor(() => expect(canvas.queryByRole('img')).toBeTruthy()); + if (reduce) { + await expect(reduce).not.toBeInTheDocument(); } + await expect(back).not.toBeInTheDocument(); + const aAgain = canvas.getByRole('link'); + await expect(aAgain).toBeInTheDocument(); + const imgAgain = within(aAgain).getByRole('img'); + await expect(imgAgain).toBeInTheDocument(); }, args: { prefer: [], diff --git a/packages/frontend/src/scripts/test-utils.ts b/packages/frontend/src/scripts/test-utils.ts index a32315f4df..52bb2d94e0 100644 --- a/packages/frontend/src/scripts/test-utils.ts +++ b/packages/frontend/src/scripts/test-utils.ts @@ -7,13 +7,3 @@ export async function tick(): Promise { // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition await new Promise((globalThis.requestIdleCallback ?? setTimeout) as never); } - -/** - * @see https://github.com/misskey-dev/misskey/issues/11267 - */ -export function semaphore(counter = 0, waiting: (() => void)[] = []) { - return { - acquire: () => ++counter > 1 && new Promise(resolve => waiting.push(resolve)), - release: () => --counter && waiting.pop()?.(), - }; -} From 427648c4b8c5b7699c92afa95a14097bb9329ee8 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Tue, 2 Jul 2024 11:38:34 +0900 Subject: [PATCH 069/246] update deps (#14057) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * locales/index.jsのymlファイル取得ロジックを調節 * regenerate pnpm-lock.yaml * fix(backend): typecheck fails * chore(deps): bump ip-cidr from 4.0.0 to 4.0.1 in /packages/backend * chore: migrate ESLint configs to flat config (#14094) * chore: migrate ESLint configs to flat config * fix: update paths * fix: frontend lint fails * refactor(misskey-js): lint build.js * update deps --------- Co-authored-by: samunohito <46447427+samunohito@users.noreply.github.com> Co-authored-by: zyoshoka Co-authored-by: zyoshoka <107108195+zyoshoka@users.noreply.github.com> --- .github/workflows/lint.yml | 4 +- locales/index.js | 6 +- package.json | 20 +- packages/backend/.eslintignore | 4 - packages/backend/.eslintrc.cjs | 32 - packages/backend/eslint.config.js | 46 + packages/backend/package.json | 98 +- packages/backend/test-server/.eslintrc.cjs | 32 - packages/backend/test-server/eslint.config.js | 43 + packages/backend/test/.eslintrc.cjs | 11 - packages/backend/test/eslint.config.js | 22 + packages/frontend/.eslintrc.cjs | 82 - packages/frontend/eslint.config.js | 95 + packages/frontend/package.json | 116 +- packages/frontend/tsconfig.json | 1 - packages/misskey-bubble-game/.eslintignore | 8 - packages/misskey-bubble-game/.eslintrc.cjs | 9 - packages/misskey-bubble-game/eslint.config.js | 27 + packages/misskey-bubble-game/package.json | 4 +- packages/misskey-js/.eslintignore | 8 - packages/misskey-js/.eslintrc.cjs | 9 - packages/misskey-js/build.js | 32 +- packages/misskey-js/eslint.config.js | 28 + packages/misskey-js/generator/.eslintrc.cjs | 9 - .../misskey-js/generator/eslint.config.js | 17 + packages/misskey-js/generator/package.json | 4 +- packages/misskey-js/package.json | 24 +- packages/misskey-reversi/.eslintignore | 8 - packages/misskey-reversi/.eslintrc.cjs | 10 - packages/misskey-reversi/eslint.config.js | 23 + packages/misskey-reversi/package.json | 4 +- packages/shared/.eslintrc.js | 7 - packages/shared/eslint.config.js | 28 + packages/shared/package.json | 3 + packages/sw/.eslintrc.cjs | 20 - packages/sw/eslint.config.js | 32 + packages/sw/package.json | 10 +- pnpm-lock.yaml | 9005 +++++++++-------- scripts/changelog-checker/.eslintrc.cjs | 9 - scripts/changelog-checker/eslint.config.js | 17 + 40 files changed, 5556 insertions(+), 4411 deletions(-) delete mode 100644 packages/backend/.eslintignore delete mode 100644 packages/backend/.eslintrc.cjs create mode 100644 packages/backend/eslint.config.js delete mode 100644 packages/backend/test-server/.eslintrc.cjs create mode 100644 packages/backend/test-server/eslint.config.js delete mode 100644 packages/backend/test/.eslintrc.cjs create mode 100644 packages/backend/test/eslint.config.js delete mode 100644 packages/frontend/.eslintrc.cjs create mode 100644 packages/frontend/eslint.config.js delete mode 100644 packages/misskey-bubble-game/.eslintignore delete mode 100644 packages/misskey-bubble-game/.eslintrc.cjs create mode 100644 packages/misskey-bubble-game/eslint.config.js delete mode 100644 packages/misskey-js/.eslintignore delete mode 100644 packages/misskey-js/.eslintrc.cjs create mode 100644 packages/misskey-js/eslint.config.js delete mode 100644 packages/misskey-js/generator/.eslintrc.cjs create mode 100644 packages/misskey-js/generator/eslint.config.js delete mode 100644 packages/misskey-reversi/.eslintignore delete mode 100644 packages/misskey-reversi/.eslintrc.cjs create mode 100644 packages/misskey-reversi/eslint.config.js delete mode 100644 packages/shared/.eslintrc.js create mode 100644 packages/shared/eslint.config.js create mode 100644 packages/shared/package.json delete mode 100644 packages/sw/.eslintrc.cjs create mode 100644 packages/sw/eslint.config.js delete mode 100644 scripts/changelog-checker/.eslintrc.cjs create mode 100644 scripts/changelog-checker/eslint.config.js diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 76616ec5a7..1a1b30168a 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -10,14 +10,14 @@ on: - packages/frontend/** - packages/sw/** - packages/misskey-js/** - - packages/shared/.eslintrc.js + - packages/shared/eslint.config.js pull_request: paths: - packages/backend/** - packages/frontend/** - packages/sw/** - packages/misskey-js/** - - packages/shared/.eslintrc.js + - packages/shared/eslint.config.js jobs: pnpm_install: diff --git a/locales/index.js b/locales/index.js index 650e552337..c2738884eb 100644 --- a/locales/index.js +++ b/locales/index.js @@ -52,7 +52,11 @@ const primaries = { const clean = (text) => text.replace(new RegExp(String.fromCodePoint(0x08), 'g'), ''); export function build() { - const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, import.meta.url), 'utf-8'))) || {}, a), {}); + // vitestの挙動を調整するため、一度ローカル変数化する必要がある + // https://github.com/vitest-dev/vitest/issues/3988#issuecomment-1686599577 + // https://github.com/misskey-dev/misskey/pull/14057#issuecomment-2192833785 + const metaUrl = import.meta.url; + const locales = languages.reduce((a, c) => (a[c] = yaml.load(clean(fs.readFileSync(new URL(`${c}.yml`, metaUrl), 'utf-8'))) || {}, a), {}); // 空文字列が入ることがあり、フォールバックが動作しなくなるのでプロパティごと消す const removeEmpty = (obj) => { diff --git a/package.json b/package.json index 5adce65415..bf8415d212 100644 --- a/package.json +++ b/package.json @@ -55,20 +55,22 @@ "js-yaml": "4.1.0", "postcss": "8.4.38", "tar": "6.2.1", - "terser": "5.30.3", - "typescript": "5.5.2", - "esbuild": "0.20.2", + "terser": "5.31.1", + "typescript": "5.5.3", + "esbuild": "0.22.0", "glob": "10.3.12" }, "devDependencies": { - "@types/node": "20.12.7", - "@typescript-eslint/eslint-plugin": "7.7.1", - "@typescript-eslint/parser": "7.7.1", + "@misskey-dev/eslint-plugin": "2.0.2", + "@types/node": "20.14.9", + "@typescript-eslint/eslint-plugin": "7.15.0", + "@typescript-eslint/parser": "7.15.0", "cross-env": "7.0.3", - "cypress": "13.7.3", - "eslint": "8.57.0", + "cypress": "13.13.0", + "eslint": "9.6.0", + "globals": "15.7.0", "ncp": "2.0.0", - "start-server-and-test": "2.0.3" + "start-server-and-test": "2.0.4" }, "optionalDependencies": { "@tensorflow/tfjs-core": "4.4.0" diff --git a/packages/backend/.eslintignore b/packages/backend/.eslintignore deleted file mode 100644 index 790eb90145..0000000000 --- a/packages/backend/.eslintignore +++ /dev/null @@ -1,4 +0,0 @@ -node_modules -/built -/.eslintrc.js -/@types/**/* diff --git a/packages/backend/.eslintrc.cjs b/packages/backend/.eslintrc.cjs deleted file mode 100644 index f9fe4814e6..0000000000 --- a/packages/backend/.eslintrc.cjs +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json', './test/tsconfig.json'], - }, - extends: [ - '../shared/.eslintrc.js', - ], - rules: { - 'import/order': ['warn', { - 'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], - 'pathGroups': [ - { - 'pattern': '@/**', - 'group': 'external', - 'position': 'after' - } - ], - }], - 'no-restricted-globals': [ - 'error', - { - 'name': '__dirname', - 'message': 'Not in ESModule. Use `import.meta.url` instead.' - }, - { - 'name': '__filename', - 'message': 'Not in ESModule. Use `import.meta.url` instead.' - } - ] - }, -}; diff --git a/packages/backend/eslint.config.js b/packages/backend/eslint.config.js new file mode 100644 index 0000000000..318b7fd340 --- /dev/null +++ b/packages/backend/eslint.config.js @@ -0,0 +1,46 @@ +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + ignores: ['**/node_modules', 'built', '@types/**/*'], + }, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json', './test/tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + 'import/order': ['warn', { + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + 'object', + 'type', + ], + pathGroups: [{ + pattern: '@/**', + group: 'external', + position: 'after', + }], + }], + 'no-restricted-globals': ['error', { + name: '__dirname', + message: 'Not in ESModule. Use `import.meta.url` instead.', + }, { + name: '__filename', + message: 'Not in ESModule. Use `import.meta.url` instead.', + }], + }, + }, +]; diff --git a/packages/backend/package.json b/packages/backend/package.json index 0467ab0bee..22fdc5cf16 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -65,43 +65,43 @@ "utf-8-validate": "6.0.3" }, "dependencies": { - "@aws-sdk/client-s3": "3.412.0", - "@aws-sdk/lib-storage": "3.412.0", - "@bull-board/api": "5.17.0", - "@bull-board/fastify": "5.17.0", - "@bull-board/ui": "5.17.0", + "@aws-sdk/client-s3": "3.600.0", + "@aws-sdk/lib-storage": "3.600.0", + "@bull-board/api": "5.20.5", + "@bull-board/fastify": "5.20.5", + "@bull-board/ui": "5.20.5", "@discordapp/twemoji": "15.0.3", "@fastify/accepts": "4.3.0", "@fastify/cookie": "9.3.1", "@fastify/cors": "9.0.1", "@fastify/express": "3.0.0", "@fastify/http-proxy": "9.5.0", - "@fastify/multipart": "8.2.0", - "@fastify/static": "7.0.3", + "@fastify/multipart": "8.3.0", + "@fastify/static": "7.0.4", "@fastify/view": "9.1.0", "@misskey-dev/sharp-read-bmp": "1.2.0", "@misskey-dev/summaly": "5.1.0", - "@napi-rs/canvas": "^0.1.52", - "@nestjs/common": "10.3.8", - "@nestjs/core": "10.3.8", - "@nestjs/testing": "10.3.8", + "@napi-rs/canvas": "^0.1.53", + "@nestjs/common": "10.3.10", + "@nestjs/core": "10.3.10", + "@nestjs/testing": "10.3.10", "@peertube/http-signature": "1.7.0", - "@sentry/node": "^8.5.0", - "@sentry/profiling-node": "^8.5.0", + "@sentry/node": "8.13.0", + "@sentry/profiling-node": "8.13.0", "@simplewebauthn/server": "10.0.0", "@sinonjs/fake-timers": "11.2.2", "@smithy/node-http-handler": "2.5.0", "@swc/cli": "0.3.12", - "@swc/core": "1.4.17", + "@swc/core": "1.6.6", "@twemoji/parser": "15.1.1", "accepts": "1.3.8", - "ajv": "8.13.0", + "ajv": "8.16.0", "archiver": "7.0.1", "async-mutex": "0.5.0", "bcryptjs": "2.4.3", "blurhash": "2.0.5", "body-parser": "1.20.2", - "bullmq": "5.7.8", + "bullmq": "5.8.3", "cacheable-lookup": "7.0.0", "cbor": "9.0.2", "chalk": "5.3.0", @@ -112,27 +112,27 @@ "content-disposition": "0.5.4", "date-fns": "2.30.0", "deep-email-validator": "0.1.21", - "fastify": "4.26.2", + "fastify": "4.28.1", "fastify-raw-body": "4.3.0", "feed": "4.2.2", "file-type": "19.0.0", - "fluent-ffmpeg": "2.1.2", + "fluent-ffmpeg": "2.1.3", "form-data": "4.0.0", - "got": "14.2.1", + "got": "14.4.1", "happy-dom": "10.0.3", "hpagent": "1.2.0", "htmlescape": "1.1.1", "http-link-header": "1.1.3", "ioredis": "5.4.1", - "ip-cidr": "3.1.0", + "ip-cidr": "4.0.1", "ipaddr.js": "2.2.0", - "is-svg": "5.0.0", + "is-svg": "5.0.1", "js-yaml": "4.1.0", - "jsdom": "24.0.0", + "jsdom": "24.1.0", "json5": "2.2.3", "jsonld": "8.3.2", "jsrsasign": "11.1.0", - "meilisearch": "0.38.0", + "meilisearch": "0.41.0", "mfm-js": "0.24.0", "microformats-parser": "2.0.2", "mime-types": "2.1.35", @@ -142,24 +142,24 @@ "nanoid": "5.0.7", "nested-property": "4.0.0", "node-fetch": "3.3.2", - "nodemailer": "6.9.13", + "nodemailer": "6.9.14", "nsfwjs": "2.4.2", "oauth": "0.10.0", "oauth2orize": "1.12.0", "oauth2orize-pkce": "0.1.2", "os-utils": "0.0.14", - "otpauth": "9.2.3", + "otpauth": "9.3.1", "parse5": "7.1.2", - "pg": "8.11.5", + "pg": "8.12.0", "pkce-challenge": "4.1.0", "probe-image-size": "7.2.3", "promise-limit": "2.7.0", - "pug": "3.0.2", + "pug": "3.0.3", "punycode": "2.3.1", "qrcode": "1.5.3", "random-seed": "0.3.0", "ratelimiter": "3.4.1", - "re2": "1.21.2", + "re2": "1.21.3", "redis-lock": "0.1.4", "reflect-metadata": "0.2.2", "rename": "1.0.4", @@ -167,27 +167,26 @@ "rxjs": "7.8.1", "sanitize-html": "2.13.0", "secure-json-parse": "2.7.0", - "sharp": "0.33.3", + "sharp": "0.33.4", "slacc": "0.0.10", "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", - "systeminformation": "5.22.7", + "systeminformation": "5.22.11", "tinycolor2": "1.6.0", "tmp": "0.2.3", - "tsc-alias": "1.8.8", + "tsc-alias": "1.8.10", "tsconfig-paths": "4.2.0", "typeorm": "0.3.20", - "typescript": "5.5.2", + "typescript": "5.5.3", "ulid": "2.3.0", "vary": "1.1.2", "web-push": "3.6.7", - "ws": "8.17.0", + "ws": "8.17.1", "xev": "3.0.2" }, "devDependencies": { "@jest/globals": "29.7.0", - "@misskey-dev/eslint-plugin": "1.0.0", - "@nestjs/platform-express": "10.3.8", + "@nestjs/platform-express": "10.3.10", "@simplewebauthn/types": "10.0.0", "@swc/jest": "0.2.36", "@types/accepts": "1.3.7", @@ -197,21 +196,21 @@ "@types/color-convert": "2.0.3", "@types/content-disposition": "0.5.8", "@types/fluent-ffmpeg": "2.1.24", - "@types/htmlescape": "^1.1.3", - "@types/http-link-header": "1.0.5", + "@types/htmlescape": "1.1.3", + "@types/http-link-header": "1.0.7", "@types/jest": "29.5.12", "@types/js-yaml": "4.0.9", - "@types/jsdom": "21.1.6", - "@types/jsonld": "1.5.13", + "@types/jsdom": "21.1.7", + "@types/jsonld": "1.5.14", "@types/jsrsasign": "10.5.14", "@types/mime-types": "2.1.4", "@types/ms": "0.7.34", - "@types/node": "20.12.7", + "@types/node": "20.14.9", "@types/nodemailer": "6.4.15", - "@types/oauth": "0.9.4", + "@types/oauth": "0.9.5", "@types/oauth2orize": "1.11.5", "@types/oauth2orize-pkce": "0.1.2", - "@types/pg": "8.11.5", + "@types/pg": "8.11.6", "@types/pug": "2.0.10", "@types/punycode": "2.1.4", "@types/qrcode": "1.5.5", @@ -227,18 +226,17 @@ "@types/vary": "1.1.3", "@types/web-push": "3.6.3", "@types/ws": "8.5.10", - "@typescript-eslint/eslint-plugin": "7.7.1", - "@typescript-eslint/parser": "7.7.1", - "aws-sdk-client-mock": "3.0.1", + "@typescript-eslint/eslint-plugin": "7.15.0", + "@typescript-eslint/parser": "7.15.0", + "aws-sdk-client-mock": "4.0.1", "cross-env": "7.0.3", - "eslint": "8.57.0", "eslint-plugin-import": "2.29.1", - "execa": "8.0.1", - "fkill": "^9.0.0", + "execa": "9.2.0", + "fkill": "9.0.0", "jest": "29.7.0", "jest-mock": "29.7.0", - "nodemon": "3.1.0", + "nodemon": "3.1.4", "pid-port": "1.0.0", - "simple-oauth2": "5.0.0" + "simple-oauth2": "5.0.1" } } diff --git a/packages/backend/test-server/.eslintrc.cjs b/packages/backend/test-server/.eslintrc.cjs deleted file mode 100644 index c261741a36..0000000000 --- a/packages/backend/test-server/.eslintrc.cjs +++ /dev/null @@ -1,32 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: [ - '../../shared/.eslintrc.js', - ], - rules: { - 'import/order': ['warn', { - 'groups': ['builtin', 'external', 'internal', 'parent', 'sibling', 'index', 'object', 'type'], - 'pathGroups': [ - { - 'pattern': '@/**', - 'group': 'external', - 'position': 'after' - } - ], - }], - 'no-restricted-globals': [ - 'error', - { - 'name': '__dirname', - 'message': 'Not in ESModule. Use `import.meta.url` instead.' - }, - { - 'name': '__filename', - 'message': 'Not in ESModule. Use `import.meta.url` instead.' - } - ] - }, -}; diff --git a/packages/backend/test-server/eslint.config.js b/packages/backend/test-server/eslint.config.js new file mode 100644 index 0000000000..b9c16d469f --- /dev/null +++ b/packages/backend/test-server/eslint.config.js @@ -0,0 +1,43 @@ +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + 'import/order': ['warn', { + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + 'object', + 'type', + ], + pathGroups: [{ + pattern: '@/**', + group: 'external', + position: 'after', + }], + }], + 'no-restricted-globals': ['error', { + name: '__dirname', + message: 'Not in ESModule. Use `import.meta.url` instead.', + }, { + name: '__filename', + message: 'Not in ESModule. Use `import.meta.url` instead.', + }], + }, + }, +]; diff --git a/packages/backend/test/.eslintrc.cjs b/packages/backend/test/.eslintrc.cjs deleted file mode 100644 index 41ecea0c3f..0000000000 --- a/packages/backend/test/.eslintrc.cjs +++ /dev/null @@ -1,11 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: ['../.eslintrc.cjs'], - env: { - node: true, - jest: true, - }, -}; diff --git a/packages/backend/test/eslint.config.js b/packages/backend/test/eslint.config.js new file mode 100644 index 0000000000..a0f43babad --- /dev/null +++ b/packages/backend/test/eslint.config.js @@ -0,0 +1,22 @@ +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + globals: { + ...globals.node, + ...globals.jest, + }, + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, +]; diff --git a/packages/frontend/.eslintrc.cjs b/packages/frontend/.eslintrc.cjs deleted file mode 100644 index fd562e1c40..0000000000 --- a/packages/frontend/.eslintrc.cjs +++ /dev/null @@ -1,82 +0,0 @@ -module.exports = { - root: true, - env: { - 'node': false, - }, - parser: 'vue-eslint-parser', - parserOptions: { - 'parser': '@typescript-eslint/parser', - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - extraFileExtensions: ['.vue'], - }, - extends: [ - '../shared/.eslintrc.js', - 'plugin:vue/vue3-recommended', - ], - rules: { - '@typescript-eslint/no-empty-interface': [ - 'error', - { - 'allowSingleExtends': true, - }, - ], - // window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため - // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため - 'id-denylist': ['error', 'window', 'e'], - 'no-shadow': ['warn'], - 'vue/attributes-order': ['error', { - 'alphabetical': false, - }], - 'vue/no-use-v-if-with-v-for': ['error', { - 'allowUsingIterationVar': false, - }], - 'vue/no-ref-as-operand': 'error', - 'vue/no-multi-spaces': ['error', { - 'ignoreProperties': false, - }], - 'vue/no-v-html': 'warn', - 'vue/order-in-components': 'error', - 'vue/html-indent': ['warn', 'tab', { - 'attribute': 1, - 'baseIndent': 0, - 'closeBracket': 0, - 'alignAttributesVertically': true, - 'ignores': [], - }], - 'vue/html-closing-bracket-spacing': ['warn', { - 'startTag': 'never', - 'endTag': 'never', - 'selfClosingTag': 'never', - }], - 'vue/multi-word-component-names': 'warn', - 'vue/require-v-for-key': 'warn', - 'vue/no-unused-components': 'warn', - 'vue/no-unused-vars': 'warn', - 'vue/no-dupe-keys': 'warn', - 'vue/valid-v-for': 'warn', - 'vue/return-in-computed-property': 'warn', - 'vue/no-setup-props-reactivity-loss': 'warn', - 'vue/max-attributes-per-line': 'off', - 'vue/html-self-closing': 'off', - 'vue/singleline-html-element-content-newline': 'off', - 'vue/v-on-event-hyphenation': ['error', 'never', { autofix: true }], - 'vue/attribute-hyphenation': ['error', 'never'], - }, - globals: { - // Node.js - 'module': false, - 'require': false, - '__dirname': false, - - // Misskey - '_DEV_': false, - '_LANGS_': false, - '_VERSION_': false, - '_ENV_': false, - '_PERF_PREFIX_': false, - '_DATA_TRANSFER_DRIVE_FILE_': false, - '_DATA_TRANSFER_DRIVE_FOLDER_': false, - '_DATA_TRANSFER_DECK_COLUMN_': false, - }, -}; diff --git a/packages/frontend/eslint.config.js b/packages/frontend/eslint.config.js new file mode 100644 index 0000000000..dd8f03dac5 --- /dev/null +++ b/packages/frontend/eslint.config.js @@ -0,0 +1,95 @@ +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import parser from 'vue-eslint-parser'; +import pluginVue from 'eslint-plugin-vue'; +import pluginMisskey from '@misskey-dev/eslint-plugin'; +import sharedConfig from '../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + files: ['src/**/*.vue'], + ...pluginMisskey.configs.typescript, + }, + ...pluginVue.configs['flat/recommended'], + { + files: ['src/**/*.{ts,vue}'], + languageOptions: { + globals: { + ...Object.fromEntries(Object.entries(globals.node).map(([key]) => [key, 'off'])), + ...globals.browser, + + // Node.js + module: false, + require: false, + __dirname: false, + + // Misskey + _DEV_: false, + _LANGS_: false, + _VERSION_: false, + _ENV_: false, + _PERF_PREFIX_: false, + _DATA_TRANSFER_DRIVE_FILE_: false, + _DATA_TRANSFER_DRIVE_FOLDER_: false, + _DATA_TRANSFER_DECK_COLUMN_: false, + }, + parser, + parserOptions: { + extraFileExtensions: ['.vue'], + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + rules: { + '@typescript-eslint/no-empty-interface': ['error', { + allowSingleExtends: true, + }], + // window の禁止理由: グローバルスコープと衝突し、予期せぬ結果を招くため + // e の禁止理由: error や event など、複数のキーワードの頭文字であり分かりにくいため + 'id-denylist': ['error', 'window', 'e'], + 'no-shadow': ['warn'], + 'vue/attributes-order': ['error', { + alphabetical: false, + }], + 'vue/no-use-v-if-with-v-for': ['error', { + allowUsingIterationVar: false, + }], + 'vue/no-ref-as-operand': 'error', + 'vue/no-multi-spaces': ['error', { + ignoreProperties: false, + }], + 'vue/no-v-html': 'warn', + 'vue/order-in-components': 'error', + 'vue/html-indent': ['warn', 'tab', { + attribute: 1, + baseIndent: 0, + closeBracket: 0, + alignAttributesVertically: true, + ignores: [], + }], + 'vue/html-closing-bracket-spacing': ['warn', { + startTag: 'never', + endTag: 'never', + selfClosingTag: 'never', + }], + 'vue/multi-word-component-names': 'warn', + 'vue/require-v-for-key': 'warn', + 'vue/no-unused-components': 'warn', + 'vue/no-unused-vars': 'warn', + 'vue/no-dupe-keys': 'warn', + 'vue/valid-v-for': 'warn', + 'vue/return-in-computed-property': 'warn', + 'vue/no-setup-props-reactivity-loss': 'warn', + 'vue/max-attributes-per-line': 'off', + 'vue/html-self-closing': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/v-on-event-hyphenation': ['error', 'never', { + autofix: true, + }], + 'vue/attribute-hyphenation': ['error', 'never'], + }, + }, +]; diff --git a/packages/frontend/package.json b/packages/frontend/package.json index a63d97658b..743722c231 100644 --- a/packages/frontend/package.json +++ b/packages/frontend/package.json @@ -22,24 +22,24 @@ "@mcaptcha/vanilla-glue": "0.1.0-alpha-3", "@misskey-dev/browser-image-resizer": "2024.1.0", "@rollup/plugin-json": "6.1.0", - "@rollup/plugin-replace": "5.0.5", + "@rollup/plugin-replace": "5.0.7", "@rollup/pluginutils": "5.1.0", "@syuilo/aiscript": "0.18.0", "@tabler/icons-webfont": "3.3.0", "@twemoji/parser": "15.1.1", - "@vitejs/plugin-vue": "5.0.4", - "@vue/compiler-sfc": "3.4.26", + "@vitejs/plugin-vue": "5.0.5", + "@vue/compiler-sfc": "3.4.31", "aiscript-vscode": "github:aiscript-dev/aiscript-vscode#v0.1.9", "astring": "1.8.6", "broadcast-channel": "7.0.0", "buraha": "0.0.1", "canvas-confetti": "1.9.3", - "chart.js": "4.4.2", + "chart.js": "4.4.3", "chartjs-adapter-date-fns": "3.0.0", "chartjs-chart-matrix": "2.0.1", "chartjs-plugin-gradient": "0.6.1", "chartjs-plugin-zoom": "2.0.1", - "chromatic": "11.3.0", + "chromatic": "11.5.4", "compare-versions": "6.1.0", "cropperjs": "2.0.0-beta.5", "date-fns": "2.30.0", @@ -55,89 +55,87 @@ "misskey-bubble-game": "workspace:*", "misskey-js": "workspace:*", "misskey-reversi": "workspace:*", - "photoswipe": "5.4.3", + "photoswipe": "5.4.4", "punycode": "2.3.1", - "rollup": "4.17.2", + "rollup": "4.18.0", "sanitize-html": "2.13.0", - "sass": "1.76.0", - "shiki": "1.4.0", + "sass": "1.77.6", + "shiki": "1.10.0", "strict-event-emitter-types": "2.0.0", "textarea-caret": "3.1.0", - "three": "0.164.1", - "throttle-debounce": "5.0.0", + "three": "0.165.0", + "throttle-debounce": "5.0.2", "tinycolor2": "1.6.0", - "tsc-alias": "1.8.8", + "tsc-alias": "1.8.10", "tsconfig-paths": "4.2.0", - "typescript": "5.5.2", - "uuid": "9.0.1", - "v-code-diff": "1.11.0", - "vite": "5.2.11", - "vue": "3.4.26", + "typescript": "5.5.3", + "uuid": "10.0.0", + "v-code-diff": "1.12.0", + "vite": "5.3.2", + "vue": "3.4.31", "vuedraggable": "next" }, "devDependencies": { - "@misskey-dev/eslint-plugin": "1.0.0", "@misskey-dev/summaly": "5.1.0", - "@storybook/addon-actions": "8.0.9", - "@storybook/addon-essentials": "8.0.9", - "@storybook/addon-interactions": "8.0.9", - "@storybook/addon-links": "8.0.9", - "@storybook/addon-mdx-gfm": "8.0.9", - "@storybook/addon-storysource": "8.0.9", - "@storybook/blocks": "8.0.9", - "@storybook/components": "8.0.9", - "@storybook/core-events": "8.0.9", - "@storybook/manager-api": "8.0.9", - "@storybook/preview-api": "8.0.9", - "@storybook/react": "8.0.9", - "@storybook/react-vite": "8.0.9", - "@storybook/test": "8.0.9", - "@storybook/theming": "8.0.9", - "@storybook/types": "8.0.9", - "@storybook/vue3": "8.0.9", - "@storybook/vue3-vite": "8.0.9", - "@testing-library/vue": "8.0.3", + "@storybook/addon-actions": "8.1.11", + "@storybook/addon-essentials": "8.1.11", + "@storybook/addon-interactions": "8.1.11", + "@storybook/addon-links": "8.1.11", + "@storybook/addon-mdx-gfm": "8.1.11", + "@storybook/addon-storysource": "8.1.11", + "@storybook/blocks": "8.1.11", + "@storybook/components": "8.1.11", + "@storybook/core-events": "8.1.11", + "@storybook/manager-api": "8.1.11", + "@storybook/preview-api": "8.1.11", + "@storybook/react": "8.1.11", + "@storybook/react-vite": "8.1.11", + "@storybook/test": "8.1.11", + "@storybook/theming": "8.1.11", + "@storybook/types": "8.1.11", + "@storybook/vue3": "8.1.11", + "@storybook/vue3-vite": "8.1.11", + "@testing-library/vue": "8.1.0", "@types/escape-regexp": "0.0.3", "@types/estree": "1.0.5", "@types/matter-js": "0.19.6", - "@types/micromatch": "4.0.7", - "@types/node": "20.12.7", + "@types/micromatch": "4.0.9", + "@types/node": "20.14.9", "@types/punycode": "2.1.4", "@types/sanitize-html": "2.11.0", "@types/seedrandom": "3.0.8", "@types/throttle-debounce": "5.0.2", "@types/tinycolor2": "1.4.6", - "@types/uuid": "9.0.8", + "@types/uuid": "10.0.0", "@types/ws": "8.5.10", - "@typescript-eslint/eslint-plugin": "7.7.1", - "@typescript-eslint/parser": "7.7.1", - "@vitest/coverage-v8": "0.34.6", - "@vue/runtime-core": "3.4.26", - "acorn": "8.11.3", + "@typescript-eslint/eslint-plugin": "7.15.0", + "@typescript-eslint/parser": "7.15.0", + "@vitest/coverage-v8": "1.6.0", + "@vue/runtime-core": "3.4.31", + "acorn": "8.12.0", "cross-env": "7.0.3", - "cypress": "13.8.1", - "eslint": "8.57.0", + "cypress": "13.13.0", "eslint-plugin-import": "2.29.1", - "eslint-plugin-vue": "9.25.0", + "eslint-plugin-vue": "9.26.0", "fast-glob": "3.3.2", "happy-dom": "10.0.3", "intersection-observer": "0.12.2", - "micromatch": "4.0.5", - "msw": "2.2.14", - "msw-storybook-addon": "2.0.1", - "nodemon": "3.1.0", - "prettier": "3.2.5", + "micromatch": "4.0.7", + "msw": "2.3.1", + "msw-storybook-addon": "2.0.2", + "nodemon": "3.1.4", + "prettier": "3.3.2", "react": "18.3.1", "react-dom": "18.3.1", "seedrandom": "3.0.5", - "start-server-and-test": "2.0.3", - "storybook": "8.0.9", + "start-server-and-test": "2.0.4", + "storybook": "8.1.11", "storybook-addon-misskey-theme": "github:misskey-dev/storybook-addon-misskey-theme", "vite-plugin-turbosnap": "1.0.3", - "vitest": "0.34.6", + "vitest": "1.6.0", "vitest-fetch-mock": "0.2.2", - "vue-component-type-helpers": "2.0.16", - "vue-eslint-parser": "9.4.2", - "vue-tsc": "2.0.16" + "vue-component-type-helpers": "2.0.24", + "vue-eslint-parser": "9.4.3", + "vue-tsc": "2.0.24" } } diff --git a/packages/frontend/tsconfig.json b/packages/frontend/tsconfig.json index 187a2473ba..fe4d202894 100644 --- a/packages/frontend/tsconfig.json +++ b/packages/frontend/tsconfig.json @@ -44,7 +44,6 @@ }, "compileOnSave": false, "include": [ - ".eslintrc.js", "./**/*.ts", "./**/*.vue" ], diff --git a/packages/misskey-bubble-game/.eslintignore b/packages/misskey-bubble-game/.eslintignore deleted file mode 100644 index 52ea8b3362..0000000000 --- a/packages/misskey-bubble-game/.eslintignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -/built -/coverage -/.eslintrc.js -/jest.config.ts -/test -/test-d -build.js diff --git a/packages/misskey-bubble-game/.eslintrc.cjs b/packages/misskey-bubble-game/.eslintrc.cjs deleted file mode 100644 index e2e31e9e33..0000000000 --- a/packages/misskey-bubble-game/.eslintrc.cjs +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: [ - '../shared/.eslintrc.js', - ], -}; diff --git a/packages/misskey-bubble-game/eslint.config.js b/packages/misskey-bubble-game/eslint.config.js new file mode 100644 index 0000000000..86c21a22a3 --- /dev/null +++ b/packages/misskey-bubble-game/eslint.config.js @@ -0,0 +1,27 @@ +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + ignores: [ + '**/node_modules', + 'built', + 'coverage', + 'jest.config.ts', + 'test', + 'test-d', + ], + }, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, +]; diff --git a/packages/misskey-bubble-game/package.json b/packages/misskey-bubble-game/package.json index a3aad147a9..528eb00b74 100644 --- a/packages/misskey-bubble-game/package.json +++ b/packages/misskey-bubble-game/package.json @@ -17,18 +17,16 @@ "scripts": { "build": "node ./build.js", "watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"", - "eslint": "eslint . --ext .js,.jsx,.ts,.tsx", + "eslint": "eslint './**/*.{js,jsx,ts,tsx}'", "typecheck": "tsc --noEmit", "lint": "pnpm typecheck && pnpm eslint" }, "devDependencies": { - "@misskey-dev/eslint-plugin": "1.0.0", "@types/matter-js": "0.19.6", "@types/seedrandom": "3.0.8", "@types/node": "20.11.5", "@typescript-eslint/eslint-plugin": "7.1.0", "@typescript-eslint/parser": "7.1.0", - "eslint": "8.57.0", "nodemon": "3.0.2", "execa": "8.0.1", "typescript": "5.3.3", diff --git a/packages/misskey-js/.eslintignore b/packages/misskey-js/.eslintignore deleted file mode 100644 index 52ea8b3362..0000000000 --- a/packages/misskey-js/.eslintignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -/built -/coverage -/.eslintrc.js -/jest.config.ts -/test -/test-d -build.js diff --git a/packages/misskey-js/.eslintrc.cjs b/packages/misskey-js/.eslintrc.cjs deleted file mode 100644 index e2e31e9e33..0000000000 --- a/packages/misskey-js/.eslintrc.cjs +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: [ - '../shared/.eslintrc.js', - ], -}; diff --git a/packages/misskey-js/build.js b/packages/misskey-js/build.js index 0b79f4b915..a13d9c1186 100644 --- a/packages/misskey-js/build.js +++ b/packages/misskey-js/build.js @@ -1,32 +1,32 @@ -import * as esbuild from "esbuild"; -import { build } from "esbuild"; -import { globSync } from "glob"; -import { execa } from "execa"; -import fs from "node:fs"; -import { fileURLToPath } from "node:url"; -import { dirname } from "node:path"; +import fs from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import { dirname } from 'node:path'; +import * as esbuild from 'esbuild'; +import { build } from 'esbuild'; +import { globSync } from 'glob'; +import { execa } from 'execa'; const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); const _package = JSON.parse(fs.readFileSync(_dirname + '/package.json', 'utf-8')); -const entryPoints = globSync("./src/**/**.{ts,tsx}"); +const entryPoints = globSync('./src/**/**.{ts,tsx}'); /** @type {import('esbuild').BuildOptions} */ const options = { entryPoints, minify: process.env.NODE_ENV === 'production', - outdir: "./built", - target: "es2022", - platform: "browser", - format: "esm", + outdir: './built', + target: 'es2022', + platform: 'browser', + format: 'esm', sourcemap: 'linked', }; // built配下をすべて削除する fs.rmSync('./built', { recursive: true, force: true }); -if (process.argv.map(arg => arg.toLowerCase()).includes("--watch")) { +if (process.argv.map(arg => arg.toLowerCase()).includes('--watch')) { await watchSrc(); } else { await buildSrc(); @@ -36,7 +36,7 @@ async function buildSrc() { console.log(`[${_package.name}] start building...`); await build(options) - .then(it => { + .then(() => { console.log(`[${_package.name}] build succeeded.`); }) .catch((err) => { @@ -65,7 +65,7 @@ function buildDts() { { stdout: process.stdout, stderr: process.stderr, - } + }, ); } @@ -86,7 +86,7 @@ async function watchSrc() { }, }]; - console.log(`[${_package.name}] start watching...`) + console.log(`[${_package.name}] start watching...`); const context = await esbuild.context({ ...options, plugins }); await context.watch(); diff --git a/packages/misskey-js/eslint.config.js b/packages/misskey-js/eslint.config.js new file mode 100644 index 0000000000..e34e7510b2 --- /dev/null +++ b/packages/misskey-js/eslint.config.js @@ -0,0 +1,28 @@ +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + ignores: [ + '**/node_modules', + 'built', + 'coverage', + 'jest.config.ts', + 'test', + 'test-d', + 'generator', + ], + }, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, +]; diff --git a/packages/misskey-js/generator/.eslintrc.cjs b/packages/misskey-js/generator/.eslintrc.cjs deleted file mode 100644 index 6a8b31da9c..0000000000 --- a/packages/misskey-js/generator/.eslintrc.cjs +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: [ - '../../shared/.eslintrc.js', - ], -}; diff --git a/packages/misskey-js/generator/eslint.config.js b/packages/misskey-js/generator/eslint.config.js new file mode 100644 index 0000000000..4bf78c3b91 --- /dev/null +++ b/packages/misskey-js/generator/eslint.config.js @@ -0,0 +1,17 @@ +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, +]; diff --git a/packages/misskey-js/generator/package.json b/packages/misskey-js/generator/package.json index a1c0f41cb2..4a02bcd8ff 100644 --- a/packages/misskey-js/generator/package.json +++ b/packages/misskey-js/generator/package.json @@ -4,15 +4,13 @@ "description": "Misskey TypeGenerator", "type": "module", "scripts": { - "generate": "tsx src/generator.ts && eslint ./built/**/* --ext .ts --fix" + "generate": "tsx src/generator.ts && eslint ./built/**/*.ts --fix" }, "devDependencies": { - "@misskey-dev/eslint-plugin": "^1.0.0", "@readme/openapi-parser": "2.5.0", "@types/node": "20.9.1", "@typescript-eslint/eslint-plugin": "6.11.0", "@typescript-eslint/parser": "6.11.0", - "eslint": "8.53.0", "openapi-types": "12.1.3", "openapi-typescript": "6.7.3", "ts-case-convert": "2.0.2", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index b99d0dd260..00342d3dbc 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -22,7 +22,7 @@ "tsd": "tsd", "api": "pnpm api-extractor run --local --verbose", "api-prod": "pnpm api-extractor run --verbose", - "eslint": "eslint . --ext .js,.jsx,.ts,.tsx", + "eslint": "eslint './**/*.{js,jsx,ts,tsx}'", "typecheck": "tsc --noEmit", "lint": "pnpm typecheck && pnpm eslint", "jest": "jest --coverage --detectOpenHandles", @@ -35,25 +35,23 @@ "directory": "packages/misskey-js" }, "devDependencies": { - "@microsoft/api-extractor": "7.43.1", - "@misskey-dev/eslint-plugin": "1.0.0", + "@microsoft/api-extractor": "7.47.0", "@swc/jest": "0.2.36", "@types/jest": "29.5.12", - "@types/node": "20.12.7", - "@typescript-eslint/eslint-plugin": "7.7.1", - "@typescript-eslint/parser": "7.7.1", - "eslint": "8.57.0", + "@types/node": "20.14.9", + "@typescript-eslint/eslint-plugin": "7.15.0", + "@typescript-eslint/parser": "7.15.0", "jest": "29.7.0", "jest-fetch-mock": "3.0.3", "jest-websocket-mock": "2.5.0", "mock-socket": "9.3.1", "ncp": "2.0.0", - "nodemon": "3.1.0", - "execa": "8.0.1", - "tsd": "0.30.7", - "typescript": "5.5.2", - "esbuild": "0.19.11", - "glob": "10.3.12" + "nodemon": "3.1.4", + "execa": "9.2.0", + "tsd": "0.31.1", + "typescript": "5.5.3", + "esbuild": "0.22.0", + "glob": "10.4.2" }, "files": [ "built" diff --git a/packages/misskey-reversi/.eslintignore b/packages/misskey-reversi/.eslintignore deleted file mode 100644 index 52ea8b3362..0000000000 --- a/packages/misskey-reversi/.eslintignore +++ /dev/null @@ -1,8 +0,0 @@ -node_modules -/built -/coverage -/.eslintrc.js -/jest.config.ts -/test -/test-d -build.js diff --git a/packages/misskey-reversi/.eslintrc.cjs b/packages/misskey-reversi/.eslintrc.cjs deleted file mode 100644 index db37a01098..0000000000 --- a/packages/misskey-reversi/.eslintrc.cjs +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - root: true, - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: [ - '../shared/.eslintrc.js', - ], -}; diff --git a/packages/misskey-reversi/eslint.config.js b/packages/misskey-reversi/eslint.config.js new file mode 100644 index 0000000000..3f81df7145 --- /dev/null +++ b/packages/misskey-reversi/eslint.config.js @@ -0,0 +1,23 @@ +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + ignores: [ + '**/node_modules', + 'built', + ], + }, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, +]; diff --git a/packages/misskey-reversi/package.json b/packages/misskey-reversi/package.json index 45a6120861..c6db6e6221 100644 --- a/packages/misskey-reversi/package.json +++ b/packages/misskey-reversi/package.json @@ -17,16 +17,14 @@ "scripts": { "build": "node ./build.js", "watch": "nodemon -w package.json -e json --exec \"node ./build.js --watch\"", - "eslint": "eslint . --ext .js,.jsx,.ts,.tsx", + "eslint": "eslint './**/*.{js,jsx,ts,tsx}'", "typecheck": "tsc --noEmit", "lint": "pnpm typecheck && pnpm eslint" }, "devDependencies": { - "@misskey-dev/eslint-plugin": "1.0.0", "@types/node": "20.11.5", "@typescript-eslint/eslint-plugin": "7.1.0", "@typescript-eslint/parser": "7.1.0", - "eslint": "8.57.0", "execa": "8.0.1", "nodemon": "3.0.2", "typescript": "5.3.3", diff --git a/packages/shared/.eslintrc.js b/packages/shared/.eslintrc.js deleted file mode 100644 index 58247877ae..0000000000 --- a/packages/shared/.eslintrc.js +++ /dev/null @@ -1,7 +0,0 @@ -module.exports = { - root: true, - ignorePatterns: ['**/.eslintrc.cjs'], - extends: [ - 'plugin:@misskey-dev/recommended', - ], -}; diff --git a/packages/shared/eslint.config.js b/packages/shared/eslint.config.js new file mode 100644 index 0000000000..e9d27c4a72 --- /dev/null +++ b/packages/shared/eslint.config.js @@ -0,0 +1,28 @@ +import globals from 'globals'; +import pluginMisskey from '@misskey-dev/eslint-plugin'; + +export default [ + ...pluginMisskey.configs['recommended'], + { + files: ['**/*.cjs'], + languageOptions: { + parserOptions: { + sourceType: 'commonjs', + }, + }, + }, + { + files: ['**/*.js', '**/*.jsx'], + languageOptions: { + parserOptions: { + sourceType: 'module', + }, + }, + }, + { + files: ['build.js'], + languageOptions: { + globals: globals.node, + }, + }, +]; diff --git a/packages/shared/package.json b/packages/shared/package.json new file mode 100644 index 0000000000..bedb411a91 --- /dev/null +++ b/packages/shared/package.json @@ -0,0 +1,3 @@ +{ + "type": "module" +} diff --git a/packages/sw/.eslintrc.cjs b/packages/sw/.eslintrc.cjs deleted file mode 100644 index b1fd6b5edc..0000000000 --- a/packages/sw/.eslintrc.cjs +++ /dev/null @@ -1,20 +0,0 @@ -module.exports = { - root: true, - env: { - node: false, - }, - parserOptions: { - parser: '@typescript-eslint/parser', - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: ['../shared/.eslintrc.js'], - globals: { - require: false, - _DEV_: false, - _LANGS_: false, - _VERSION_: false, - _ENV_: false, - _PERF_PREFIX_: false, - }, -}; diff --git a/packages/sw/eslint.config.js b/packages/sw/eslint.config.js new file mode 100644 index 0000000000..c62a2eadc6 --- /dev/null +++ b/packages/sw/eslint.config.js @@ -0,0 +1,32 @@ +import globals from 'globals'; +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + ignores: ['build.js'], + languageOptions: { + globals: { + ...Object.fromEntries(Object.entries(globals.node).map(([key]) => [key, 'off'])), + require: false, + _DEV_: false, + _LANGS_: false, + _VERSION_: false, + _ENV_: false, + _PERF_PREFIX_: false, + }, + }, + }, + { + files: ['**/*.ts', '**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, +]; diff --git a/packages/sw/package.json b/packages/sw/package.json index 2deda47369..bcd642ffc4 100644 --- a/packages/sw/package.json +++ b/packages/sw/package.json @@ -9,18 +9,16 @@ "lint": "pnpm typecheck && pnpm eslint" }, "dependencies": { - "esbuild": "0.20.2", + "esbuild": "0.22.0", "idb-keyval": "6.2.1", "misskey-js": "workspace:*" }, "devDependencies": { - "@misskey-dev/eslint-plugin": "1.0.0", - "@typescript-eslint/parser": "7.7.1", + "@typescript-eslint/parser": "7.15.0", "@typescript/lib-webworker": "npm:@types/serviceworker@0.0.67", - "eslint": "8.57.0", "eslint-plugin-import": "2.29.1", - "nodemon": "3.1.0", - "typescript": "5.5.2" + "nodemon": "3.1.4", + "typescript": "5.5.3" }, "type": "module" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 09df15853b..10968f3e82 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,8 +16,8 @@ importers: specifier: 6.1.2 version: 6.1.2(postcss@8.4.38) esbuild: - specifier: 0.20.2 - version: 0.20.2 + specifier: 0.22.0 + version: 0.22.0 execa: specifier: 8.0.1 version: 8.0.1 @@ -40,58 +40,64 @@ importers: specifier: 6.2.1 version: 6.2.1 terser: - specifier: 5.30.3 - version: 5.30.3 + specifier: 5.31.1 + version: 5.31.1 typescript: - specifier: 5.5.2 - version: 5.5.2 + specifier: 5.5.3 + version: 5.5.3 optionalDependencies: '@tensorflow/tfjs-core': specifier: 4.4.0 version: 4.4.0(encoding@0.1.13) devDependencies: + '@misskey-dev/eslint-plugin': + specifier: 2.0.2 + version: 2.0.2(@eslint/compat@1.1.0)(@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3))(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0))(eslint@9.6.0)(globals@15.7.0) '@types/node': - specifier: 20.12.7 - version: 20.12.7 + specifier: 20.14.9 + version: 20.14.9 '@typescript-eslint/eslint-plugin': - specifier: 7.7.1 - version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3) '@typescript-eslint/parser': - specifier: 7.7.1 - version: 7.7.1(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(eslint@9.6.0)(typescript@5.5.3) cross-env: specifier: 7.0.3 version: 7.0.3 cypress: - specifier: 13.7.3 - version: 13.7.3 + specifier: 13.13.0 + version: 13.13.0 eslint: - specifier: 8.57.0 - version: 8.57.0 + specifier: 9.6.0 + version: 9.6.0 + globals: + specifier: 15.7.0 + version: 15.7.0 ncp: specifier: 2.0.0 version: 2.0.0 start-server-and-test: - specifier: 2.0.3 - version: 2.0.3 + specifier: 2.0.4 + version: 2.0.4 packages/backend: dependencies: '@aws-sdk/client-s3': - specifier: 3.412.0 - version: 3.412.0 + specifier: 3.600.0 + version: 3.600.0 '@aws-sdk/lib-storage': - specifier: 3.412.0 - version: 3.412.0(@aws-sdk/client-s3@3.412.0) + specifier: 3.600.0 + version: 3.600.0(@aws-sdk/client-s3@3.600.0) '@bull-board/api': - specifier: 5.17.0 - version: 5.17.0(@bull-board/ui@5.17.0) + specifier: 5.20.5 + version: 5.20.5(@bull-board/ui@5.20.5) '@bull-board/fastify': - specifier: 5.17.0 - version: 5.17.0 + specifier: 5.20.5 + version: 5.20.5 '@bull-board/ui': - specifier: 5.17.0 - version: 5.17.0 + specifier: 5.20.5 + version: 5.20.5 '@discordapp/twemoji': specifier: 15.0.3 version: 15.0.3 @@ -111,11 +117,11 @@ importers: specifier: 9.5.0 version: 9.5.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) '@fastify/multipart': - specifier: 8.2.0 - version: 8.2.0 + specifier: 8.3.0 + version: 8.3.0 '@fastify/static': - specifier: 7.0.3 - version: 7.0.3 + specifier: 7.0.4 + version: 7.0.4 '@fastify/view': specifier: 9.1.0 version: 9.1.0 @@ -126,26 +132,26 @@ importers: specifier: 5.1.0 version: 5.1.0 '@napi-rs/canvas': - specifier: ^0.1.52 - version: 0.1.52 + specifier: ^0.1.53 + version: 0.1.53 '@nestjs/common': - specifier: 10.3.8 - version: 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + specifier: 10.3.10 + version: 10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/core': - specifier: 10.3.8 - version: 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.8)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1) + specifier: 10.3.10 + version: 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nestjs/testing': - specifier: 10.3.8 - version: 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.8)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8)) + specifier: 10.3.10 + version: 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)) '@peertube/http-signature': specifier: 1.7.0 version: 1.7.0 '@sentry/node': - specifier: ^8.5.0 - version: 8.5.0 + specifier: 8.13.0 + version: 8.13.0 '@sentry/profiling-node': - specifier: ^8.5.0 - version: 8.5.0 + specifier: 8.13.0 + version: 8.13.0 '@simplewebauthn/server': specifier: 10.0.0 version: 10.0.0(encoding@0.1.13) @@ -157,10 +163,10 @@ importers: version: 2.5.0 '@swc/cli': specifier: 0.3.12 - version: 0.3.12(@swc/core@1.4.17)(chokidar@3.5.3) + version: 0.3.12(@swc/core@1.6.6)(chokidar@3.5.3) '@swc/core': - specifier: 1.4.17 - version: 1.4.17 + specifier: 1.6.6 + version: 1.6.6 '@twemoji/parser': specifier: 15.1.1 version: 15.1.1 @@ -168,8 +174,8 @@ importers: specifier: 1.3.8 version: 1.3.8 ajv: - specifier: 8.13.0 - version: 8.13.0 + specifier: 8.16.0 + version: 8.16.0 archiver: specifier: 7.0.1 version: 7.0.1 @@ -186,8 +192,8 @@ importers: specifier: 1.20.2 version: 1.20.2 bullmq: - specifier: 5.7.8 - version: 5.7.8 + specifier: 5.8.3 + version: 5.8.3 cacheable-lookup: specifier: 7.0.0 version: 7.0.0 @@ -219,8 +225,8 @@ importers: specifier: 0.1.21 version: 0.1.21 fastify: - specifier: 4.26.2 - version: 4.26.2 + specifier: 4.28.1 + version: 4.28.1 fastify-raw-body: specifier: 4.3.0 version: 4.3.0 @@ -231,14 +237,14 @@ importers: specifier: 19.0.0 version: 19.0.0 fluent-ffmpeg: - specifier: 2.1.2 - version: 2.1.2 + specifier: 2.1.3 + version: 2.1.3 form-data: specifier: 4.0.0 version: 4.0.0 got: - specifier: 14.2.1 - version: 14.2.1 + specifier: 14.4.1 + version: 14.4.1 happy-dom: specifier: 10.0.3 version: 10.0.3 @@ -255,20 +261,20 @@ importers: specifier: 5.4.1 version: 5.4.1 ip-cidr: - specifier: 3.1.0 - version: 3.1.0 + specifier: 4.0.1 + version: 4.0.1 ipaddr.js: specifier: 2.2.0 version: 2.2.0 is-svg: - specifier: 5.0.0 - version: 5.0.0 + specifier: 5.0.1 + version: 5.0.1 js-yaml: specifier: 4.1.0 version: 4.1.0 jsdom: - specifier: 24.0.0 - version: 24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) + specifier: 24.1.0 + version: 24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) json5: specifier: 2.2.3 version: 2.2.3 @@ -279,8 +285,8 @@ importers: specifier: 11.1.0 version: 11.1.0 meilisearch: - specifier: 0.38.0 - version: 0.38.0(encoding@0.1.13) + specifier: 0.41.0 + version: 0.41.0(encoding@0.1.13) mfm-js: specifier: 0.24.0 version: 0.24.0 @@ -309,8 +315,8 @@ importers: specifier: 3.3.2 version: 3.3.2 nodemailer: - specifier: 6.9.13 - version: 6.9.13 + specifier: 6.9.14 + version: 6.9.14 nsfwjs: specifier: 2.4.2 version: 2.4.2(@tensorflow/tfjs@4.4.0(encoding@0.1.13)(seedrandom@3.0.5)) @@ -327,14 +333,14 @@ importers: specifier: 0.0.14 version: 0.0.14 otpauth: - specifier: 9.2.3 - version: 9.2.3 + specifier: 9.3.1 + version: 9.3.1 parse5: specifier: 7.1.2 version: 7.1.2 pg: - specifier: 8.11.5 - version: 8.11.5 + specifier: 8.12.0 + version: 8.12.0 pkce-challenge: specifier: 4.1.0 version: 4.1.0 @@ -345,8 +351,8 @@ importers: specifier: 2.7.0 version: 2.7.0 pug: - specifier: 3.0.2 - version: 3.0.2 + specifier: 3.0.3 + version: 3.0.3 punycode: specifier: 2.3.1 version: 2.3.1 @@ -360,8 +366,8 @@ importers: specifier: 3.4.1 version: 3.4.1 re2: - specifier: 1.21.2 - version: 1.21.2 + specifier: 1.21.3 + version: 1.21.3 redis-lock: specifier: 0.1.4 version: 0.1.4 @@ -384,8 +390,8 @@ importers: specifier: 2.7.0 version: 2.7.0 sharp: - specifier: 0.33.3 - version: 0.33.3 + specifier: 0.33.4 + version: 0.33.4 slacc: specifier: 0.0.10 version: 0.0.10 @@ -396,8 +402,8 @@ importers: specifier: 2.1.0 version: 2.1.0 systeminformation: - specifier: 5.22.7 - version: 5.22.7 + specifier: 5.22.11 + version: 5.22.11 tinycolor2: specifier: 1.6.0 version: 1.6.0 @@ -405,17 +411,17 @@ importers: specifier: 0.2.3 version: 0.2.3 tsc-alias: - specifier: 1.8.8 - version: 1.8.8 + specifier: 1.8.10 + version: 1.8.10 tsconfig-paths: specifier: 4.2.0 version: 4.2.0 typeorm: specifier: 0.3.20 - version: 0.3.20(ioredis@5.4.1)(pg@8.11.5) + version: 0.3.20(ioredis@5.4.1)(pg@8.12.0) typescript: - specifier: 5.5.2 - version: 5.5.2 + specifier: 5.5.3 + version: 5.5.3 ulid: specifier: 2.3.0 version: 2.3.0 @@ -426,8 +432,8 @@ importers: specifier: 3.6.7 version: 3.6.7 ws: - specifier: 8.17.0 - version: 8.17.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) + specifier: 8.17.1 + version: 8.17.1(bufferutil@4.0.7)(utf-8-validate@6.0.3) xev: specifier: 3.0.2 version: 3.0.2 @@ -523,18 +529,15 @@ importers: '@jest/globals': specifier: 29.7.0 version: 29.7.0 - '@misskey-dev/eslint-plugin': - specifier: 1.0.0 - version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0) '@nestjs/platform-express': - specifier: 10.3.8 - version: 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8) + specifier: 10.3.10 + version: 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10) '@simplewebauthn/types': specifier: 10.0.0 version: 10.0.0 '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17) + version: 0.2.36(@swc/core@1.6.6) '@types/accepts': specifier: 1.3.7 version: 1.3.7 @@ -557,11 +560,11 @@ importers: specifier: 2.1.24 version: 2.1.24 '@types/htmlescape': - specifier: ^1.1.3 + specifier: 1.1.3 version: 1.1.3 '@types/http-link-header': - specifier: 1.0.5 - version: 1.0.5 + specifier: 1.0.7 + version: 1.0.7 '@types/jest': specifier: 29.5.12 version: 29.5.12 @@ -569,11 +572,11 @@ importers: specifier: 4.0.9 version: 4.0.9 '@types/jsdom': - specifier: 21.1.6 - version: 21.1.6 + specifier: 21.1.7 + version: 21.1.7 '@types/jsonld': - specifier: 1.5.13 - version: 1.5.13 + specifier: 1.5.14 + version: 1.5.14 '@types/jsrsasign': specifier: 10.5.14 version: 10.5.14 @@ -584,14 +587,14 @@ importers: specifier: 0.7.34 version: 0.7.34 '@types/node': - specifier: 20.12.7 - version: 20.12.7 + specifier: 20.14.9 + version: 20.14.9 '@types/nodemailer': specifier: 6.4.15 version: 6.4.15 '@types/oauth': - specifier: 0.9.4 - version: 0.9.4 + specifier: 0.9.5 + version: 0.9.5 '@types/oauth2orize': specifier: 1.11.5 version: 1.11.5 @@ -599,8 +602,8 @@ importers: specifier: 0.1.2 version: 0.1.2 '@types/pg': - specifier: 8.11.5 - version: 8.11.5 + specifier: 8.11.6 + version: 8.11.6 '@types/pug': specifier: 2.0.10 version: 2.0.10 @@ -647,44 +650,41 @@ importers: specifier: 8.5.10 version: 8.5.10 '@typescript-eslint/eslint-plugin': - specifier: 7.7.1 - version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3) '@typescript-eslint/parser': - specifier: 7.7.1 - version: 7.7.1(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(eslint@9.6.0)(typescript@5.5.3) aws-sdk-client-mock: - specifier: 3.0.1 - version: 3.0.1 + specifier: 4.0.1 + version: 4.0.1 cross-env: specifier: 7.0.3 version: 7.0.3 - eslint: - specifier: 8.57.0 - version: 8.57.0 eslint-plugin-import: specifier: 2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0) execa: - specifier: 8.0.1 - version: 8.0.1 + specifier: 9.2.0 + version: 9.2.0 fkill: - specifier: ^9.0.0 + specifier: 9.0.0 version: 9.0.0 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7) + version: 29.7.0(@types/node@20.14.9) jest-mock: specifier: 29.7.0 version: 29.7.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 pid-port: specifier: 1.0.0 version: 1.0.0 simple-oauth2: - specifier: 5.0.0 - version: 5.0.0 + specifier: 5.0.1 + version: 5.0.1 packages/frontend: dependencies: @@ -702,13 +702,13 @@ importers: version: 2024.1.0 '@rollup/plugin-json': specifier: 6.1.0 - version: 6.1.0(rollup@4.17.2) + version: 6.1.0(rollup@4.18.0) '@rollup/plugin-replace': - specifier: 5.0.5 - version: 5.0.5(rollup@4.17.2) + specifier: 5.0.7 + version: 5.0.7(rollup@4.18.0) '@rollup/pluginutils': specifier: 5.1.0 - version: 5.1.0(rollup@4.17.2) + version: 5.1.0(rollup@4.18.0) '@syuilo/aiscript': specifier: 0.18.0 version: 0.18.0 @@ -719,11 +719,11 @@ importers: specifier: 15.1.1 version: 15.1.1 '@vitejs/plugin-vue': - specifier: 5.0.4 - version: 5.0.4(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.5.2)) + specifier: 5.0.5 + version: 5.0.5(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))(vue@3.4.31(typescript@5.5.3)) '@vue/compiler-sfc': - specifier: 3.4.26 - version: 3.4.26 + specifier: 3.4.31 + version: 3.4.31 aiscript-vscode: specifier: github:aiscript-dev/aiscript-vscode#v0.1.9 version: https://codeload.github.com/aiscript-dev/aiscript-vscode/tar.gz/34bf4e1530efcf1efa855bd04e2dab39735e1b02 @@ -740,23 +740,23 @@ importers: specifier: 1.9.3 version: 1.9.3 chart.js: - specifier: 4.4.2 - version: 4.4.2 + specifier: 4.4.3 + version: 4.4.3 chartjs-adapter-date-fns: specifier: 3.0.0 - version: 3.0.0(chart.js@4.4.2)(date-fns@2.30.0) + version: 3.0.0(chart.js@4.4.3)(date-fns@2.30.0) chartjs-chart-matrix: specifier: 2.0.1 - version: 2.0.1(chart.js@4.4.2) + version: 2.0.1(chart.js@4.4.3) chartjs-plugin-gradient: specifier: 0.6.1 - version: 0.6.1(chart.js@4.4.2) + version: 0.6.1(chart.js@4.4.3) chartjs-plugin-zoom: specifier: 2.0.1 - version: 2.0.1(chart.js@4.4.2) + version: 2.0.1(chart.js@4.4.3) chromatic: - specifier: 11.3.0 - version: 11.3.0 + specifier: 11.5.4 + version: 11.5.4 compare-versions: specifier: 6.1.0 version: 6.1.0 @@ -803,23 +803,23 @@ importers: specifier: workspace:* version: link:../misskey-reversi photoswipe: - specifier: 5.4.3 - version: 5.4.3 + specifier: 5.4.4 + version: 5.4.4 punycode: specifier: 2.3.1 version: 2.3.1 rollup: - specifier: 4.17.2 - version: 4.17.2 + specifier: 4.18.0 + version: 4.18.0 sanitize-html: specifier: 2.13.0 version: 2.13.0 sass: - specifier: 1.76.0 - version: 1.76.0 + specifier: 1.77.6 + version: 1.77.6 shiki: - specifier: 1.4.0 - version: 1.4.0 + specifier: 1.10.0 + version: 1.10.0 strict-event-emitter-types: specifier: 2.0.0 version: 2.0.0 @@ -827,102 +827,99 @@ importers: specifier: 3.1.0 version: 3.1.0 three: - specifier: 0.164.1 - version: 0.164.1 + specifier: 0.165.0 + version: 0.165.0 throttle-debounce: - specifier: 5.0.0 - version: 5.0.0 + specifier: 5.0.2 + version: 5.0.2 tinycolor2: specifier: 1.6.0 version: 1.6.0 tsc-alias: - specifier: 1.8.8 - version: 1.8.8 + specifier: 1.8.10 + version: 1.8.10 tsconfig-paths: specifier: 4.2.0 version: 4.2.0 typescript: - specifier: 5.5.2 - version: 5.5.2 + specifier: 5.5.3 + version: 5.5.3 uuid: - specifier: 9.0.1 - version: 9.0.1 + specifier: 10.0.0 + version: 10.0.0 v-code-diff: - specifier: 1.11.0 - version: 1.11.0(vue@3.4.26(typescript@5.5.2)) + specifier: 1.12.0 + version: 1.12.0(vue@3.4.31(typescript@5.5.3)) vite: - specifier: 5.2.11 - version: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) + specifier: 5.3.2 + version: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) vue: - specifier: 3.4.26 - version: 3.4.26(typescript@5.5.2) + specifier: 3.4.31 + version: 3.4.31(typescript@5.5.3) vuedraggable: specifier: next - version: 4.1.0(vue@3.4.26(typescript@5.5.2)) + version: 4.1.0(vue@3.4.31(typescript@5.5.3)) devDependencies: - '@misskey-dev/eslint-plugin': - specifier: 1.0.0 - version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0) '@misskey-dev/summaly': specifier: 5.1.0 version: 5.1.0 '@storybook/addon-actions': - specifier: 8.0.9 - version: 8.0.9 + specifier: 8.1.11 + version: 8.1.11 '@storybook/addon-essentials': - specifier: 8.0.9 - version: 8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 8.1.11 + version: 8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/addon-interactions': - specifier: 8.0.9 - version: 8.0.9(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)) + specifier: 8.1.11 + version: 8.1.11(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9))(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1)) '@storybook/addon-links': - specifier: 8.0.9 - version: 8.0.9(react@18.3.1) + specifier: 8.1.11 + version: 8.1.11(react@18.3.1) '@storybook/addon-mdx-gfm': - specifier: 8.0.9 - version: 8.0.9 + specifier: 8.1.11 + version: 8.1.11 '@storybook/addon-storysource': - specifier: 8.0.9 - version: 8.0.9 + specifier: 8.1.11 + version: 8.1.11 '@storybook/blocks': - specifier: 8.0.9 - version: 8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 8.1.11 + version: 8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/components': - specifier: 8.0.9 - version: 8.0.9(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 8.1.11 + version: 8.1.11(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/core-events': - specifier: 8.0.9 - version: 8.0.9 + specifier: 8.1.11 + version: 8.1.11 '@storybook/manager-api': - specifier: 8.0.9 - version: 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 8.1.11 + version: 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/preview-api': - specifier: 8.0.9 - version: 8.0.9 + specifier: 8.1.11 + version: 8.1.11 '@storybook/react': - specifier: 8.0.9 - version: 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.2) + specifier: 8.1.11 + version: 8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) '@storybook/react-vite': - specifier: 8.0.9 - version: 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.17.2)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)) + specifier: 8.1.11 + version: 8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) '@storybook/test': - specifier: 8.0.9 - version: 8.0.9(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)) + specifier: 8.1.11 + version: 8.1.11(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9))(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1)) '@storybook/theming': - specifier: 8.0.9 - version: 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + specifier: 8.1.11 + version: 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@storybook/types': - specifier: 8.0.9 - version: 8.0.9 + specifier: 8.1.11 + version: 8.1.11 '@storybook/vue3': - specifier: 8.0.9 - version: 8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.5.2)) + specifier: 8.1.11 + version: 8.1.11(encoding@0.1.13)(prettier@3.3.2)(vue@3.4.31(typescript@5.5.3)) '@storybook/vue3-vite': - specifier: 8.0.9 - version: 8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.5.2)) + specifier: 8.1.11 + version: 8.1.11(bufferutil@4.0.7)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))(vue@3.4.31(typescript@5.5.3)) '@testing-library/vue': - specifier: 8.0.3 - version: 8.0.3(@vue/compiler-sfc@3.4.26)(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2)))(vue@3.4.26(typescript@5.5.2)) + specifier: 8.1.0 + version: 8.1.0(@vue/compiler-sfc@3.4.31)(@vue/server-renderer@3.4.29(vue@3.4.31(typescript@5.5.3)))(vue@3.4.31(typescript@5.5.3)) '@types/escape-regexp': specifier: 0.0.3 version: 0.0.3 @@ -933,11 +930,11 @@ importers: specifier: 0.19.6 version: 0.19.6 '@types/micromatch': - specifier: 4.0.7 - version: 4.0.7 + specifier: 4.0.9 + version: 4.0.9 '@types/node': - specifier: 20.12.7 - version: 20.12.7 + specifier: 20.14.9 + version: 20.14.9 '@types/punycode': specifier: 2.1.4 version: 2.1.4 @@ -954,41 +951,38 @@ importers: specifier: 1.4.6 version: 1.4.6 '@types/uuid': - specifier: 9.0.8 - version: 9.0.8 + specifier: 10.0.0 + version: 10.0.0 '@types/ws': specifier: 8.5.10 version: 8.5.10 '@typescript-eslint/eslint-plugin': - specifier: 7.7.1 - version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3) '@typescript-eslint/parser': - specifier: 7.7.1 - version: 7.7.1(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(eslint@9.6.0)(typescript@5.5.3) '@vitest/coverage-v8': - specifier: 0.34.6 - version: 0.34.6(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)) + specifier: 1.6.0 + version: 1.6.0(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1)) '@vue/runtime-core': - specifier: 3.4.26 - version: 3.4.26 + specifier: 3.4.31 + version: 3.4.31 acorn: - specifier: 8.11.3 - version: 8.11.3 + specifier: 8.12.0 + version: 8.12.0 cross-env: specifier: 7.0.3 version: 7.0.3 cypress: - specifier: 13.8.1 - version: 13.8.1 - eslint: - specifier: 8.57.0 - version: 8.57.0 + specifier: 13.13.0 + version: 13.13.0 eslint-plugin-import: specifier: 2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0) eslint-plugin-vue: - specifier: 9.25.0 - version: 9.25.0(eslint@8.57.0) + specifier: 9.26.0 + version: 9.26.0(eslint@9.6.0) fast-glob: specifier: 3.3.2 version: 3.3.2 @@ -999,20 +993,20 @@ importers: specifier: 0.12.2 version: 0.12.2 micromatch: - specifier: 4.0.5 - version: 4.0.5 + specifier: 4.0.7 + version: 4.0.7 msw: - specifier: 2.2.14 - version: 2.2.14(typescript@5.5.2) + specifier: 2.3.1 + version: 2.3.1(typescript@5.5.3) msw-storybook-addon: - specifier: 2.0.1 - version: 2.0.1(msw@2.2.14(typescript@5.5.2)) + specifier: 2.0.2 + version: 2.0.2(msw@2.3.1(typescript@5.5.3)) nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 prettier: - specifier: 3.2.5 - version: 3.2.5 + specifier: 3.3.2 + version: 3.3.2 react: specifier: 18.3.1 version: 18.3.1 @@ -1023,32 +1017,32 @@ importers: specifier: 3.0.5 version: 3.0.5 start-server-and-test: - specifier: 2.0.3 - version: 2.0.3 + specifier: 2.0.4 + version: 2.0.4 storybook: - specifier: 8.0.9 - version: 8.0.9(@babel/preset-env@7.23.5(@babel/core@7.24.0))(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) + specifier: 8.1.11 + version: 8.1.11(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) storybook-addon-misskey-theme: specifier: github:misskey-dev/storybook-addon-misskey-theme - version: https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/components@8.0.9(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/core-events@8.0.9)(@storybook/manager-api@8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/preview-api@8.0.9)(@storybook/theming@8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/types@8.0.9)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/components@8.1.11(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/core-events@8.1.11)(@storybook/manager-api@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/preview-api@8.1.11)(@storybook/theming@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/types@8.1.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) vite-plugin-turbosnap: specifier: 1.0.3 version: 1.0.3 vitest: - specifier: 0.34.6 - version: 0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3) + specifier: 1.6.0 + version: 1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1) vitest-fetch-mock: specifier: 0.2.2 - version: 0.2.2(encoding@0.1.13)(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)) + version: 0.2.2(encoding@0.1.13)(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1)) vue-component-type-helpers: - specifier: 2.0.16 - version: 2.0.16 + specifier: 2.0.24 + version: 2.0.24 vue-eslint-parser: - specifier: 9.4.2 - version: 9.4.2(eslint@8.57.0) + specifier: 9.4.3 + version: 9.4.3(eslint@9.6.0) vue-tsc: - specifier: 2.0.16 - version: 2.0.16(typescript@5.5.2) + specifier: 2.0.24 + version: 2.0.24(typescript@5.5.3) packages/misskey-bubble-game: dependencies: @@ -1062,9 +1056,6 @@ importers: specifier: 3.0.5 version: 3.0.5 devDependencies: - '@misskey-dev/eslint-plugin': - specifier: 1.0.0 - version: 1.0.0(@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3))(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0) '@types/matter-js': specifier: 0.19.6 version: 0.19.6 @@ -1076,16 +1067,13 @@ importers: version: 3.0.8 '@typescript-eslint/eslint-plugin': specifier: 7.1.0 - version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3) + version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.6.0)(typescript@5.3.3))(eslint@9.6.0)(typescript@5.3.3) '@typescript-eslint/parser': specifier: 7.1.0 - version: 7.1.0(eslint@8.57.0)(typescript@5.3.3) + version: 7.1.0(eslint@9.6.0)(typescript@5.3.3) esbuild: specifier: 0.19.11 version: 0.19.11 - eslint: - specifier: 8.57.0 - version: 8.57.0 execa: specifier: 8.0.1 version: 8.0.1 @@ -1109,41 +1097,35 @@ importers: version: 4.4.0 devDependencies: '@microsoft/api-extractor': - specifier: 7.43.1 - version: 7.43.1(@types/node@20.12.7) - '@misskey-dev/eslint-plugin': - specifier: 1.0.0 - version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0) + specifier: 7.47.0 + version: 7.47.0(@types/node@20.14.9) '@swc/jest': specifier: 0.2.36 - version: 0.2.36(@swc/core@1.4.17) + version: 0.2.36(@swc/core@1.6.6) '@types/jest': specifier: 29.5.12 version: 29.5.12 '@types/node': - specifier: 20.12.7 - version: 20.12.7 + specifier: 20.14.9 + version: 20.14.9 '@typescript-eslint/eslint-plugin': - specifier: 7.7.1 - version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3) '@typescript-eslint/parser': - specifier: 7.7.1 - version: 7.7.1(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(eslint@9.6.0)(typescript@5.5.3) esbuild: - specifier: 0.19.11 - version: 0.19.11 - eslint: - specifier: 8.57.0 - version: 8.57.0 + specifier: 0.22.0 + version: 0.22.0 execa: - specifier: 8.0.1 - version: 8.0.1 + specifier: 9.2.0 + version: 9.2.0 glob: - specifier: 10.3.12 - version: 10.3.12 + specifier: 10.4.2 + version: 10.4.2 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.12.7) + version: 29.7.0(@types/node@20.14.9) jest-fetch-mock: specifier: 3.0.3 version: 3.0.3(encoding@0.1.13) @@ -1157,20 +1139,17 @@ importers: specifier: 2.0.0 version: 2.0.0 nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 tsd: - specifier: 0.30.7 - version: 0.30.7 + specifier: 0.31.1 + version: 0.31.1 typescript: - specifier: 5.5.2 - version: 5.5.2 + specifier: 5.5.3 + version: 5.5.3 packages/misskey-js/generator: devDependencies: - '@misskey-dev/eslint-plugin': - specifier: ^1.0.0 - version: 1.0.0(@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0)(typescript@5.3.3))(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0))(eslint@8.53.0) '@readme/openapi-parser': specifier: 2.5.0 version: 2.5.0(openapi-types@12.1.3) @@ -1179,13 +1158,10 @@ importers: version: 20.9.1 '@typescript-eslint/eslint-plugin': specifier: 6.11.0 - version: 6.11.0(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0)(typescript@5.3.3) + version: 6.11.0(@typescript-eslint/parser@6.11.0(eslint@9.6.0)(typescript@5.3.3))(eslint@9.6.0)(typescript@5.3.3) '@typescript-eslint/parser': specifier: 6.11.0 - version: 6.11.0(eslint@8.53.0)(typescript@5.3.3) - eslint: - specifier: 8.53.0 - version: 8.53.0 + version: 6.11.0(eslint@9.6.0)(typescript@5.3.3) openapi-types: specifier: 12.1.3 version: 12.1.3 @@ -1208,24 +1184,18 @@ importers: specifier: 1.2.2 version: 1.2.2 devDependencies: - '@misskey-dev/eslint-plugin': - specifier: 1.0.0 - version: 1.0.0(@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3))(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0) '@types/node': specifier: 20.11.5 version: 20.11.5 '@typescript-eslint/eslint-plugin': specifier: 7.1.0 - version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3) + version: 7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.6.0)(typescript@5.3.3))(eslint@9.6.0)(typescript@5.3.3) '@typescript-eslint/parser': specifier: 7.1.0 - version: 7.1.0(eslint@8.57.0)(typescript@5.3.3) + version: 7.1.0(eslint@9.6.0)(typescript@5.3.3) esbuild: specifier: 0.19.11 version: 0.19.11 - eslint: - specifier: 8.57.0 - version: 8.57.0 execa: specifier: 8.0.1 version: 8.0.1 @@ -1242,8 +1212,8 @@ importers: packages/sw: dependencies: esbuild: - specifier: 0.20.2 - version: 0.20.2 + specifier: 0.22.0 + version: 0.22.0 idb-keyval: specifier: 6.2.1 version: 6.2.1 @@ -1251,27 +1221,21 @@ importers: specifier: workspace:* version: link:../misskey-js devDependencies: - '@misskey-dev/eslint-plugin': - specifier: 1.0.0 - version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0) '@typescript-eslint/parser': - specifier: 7.7.1 - version: 7.7.1(eslint@8.57.0)(typescript@5.5.2) + specifier: 7.15.0 + version: 7.15.0(eslint@9.6.0)(typescript@5.5.3) '@typescript/lib-webworker': specifier: npm:@types/serviceworker@0.0.67 version: '@types/serviceworker@0.0.67' - eslint: - specifier: 8.57.0 - version: 8.57.0 eslint-plugin-import: specifier: 2.29.1 - version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0) + version: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0) nodemon: - specifier: 3.1.0 - version: 3.1.0 + specifier: 3.1.4 + version: 3.1.4 typescript: - specifier: 5.5.2 - version: 5.5.2 + specifier: 5.5.3 + version: 5.5.3 packages: @@ -1302,221 +1266,239 @@ packages: resolution: {integrity: sha512-Xk1sIhyNC/esHGGVjL/niHLowM0csl/kFO5uawBy4IrWwy0o1G8LGt3jP6nmWGz+USxeeqbihAmp/oVZju6wug==} hasBin: true - '@aws-crypto/crc32@3.0.0': - resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} - '@aws-crypto/crc32c@3.0.0': - resolution: {integrity: sha512-ENNPPManmnVJ4BTXlOjAgD7URidbAznURqD0KvfREyc4o20DPYdEldU1f5cQ7Jbj0CJJSPaMIk/9ZshdB3210w==} + '@aws-crypto/crc32c@5.2.0': + resolution: {integrity: sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==} - '@aws-crypto/ie11-detection@3.0.0': - resolution: {integrity: sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==} + '@aws-crypto/sha1-browser@5.2.0': + resolution: {integrity: sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==} - '@aws-crypto/sha1-browser@3.0.0': - resolution: {integrity: sha512-NJth5c997GLHs6nOYTzFKTbYdMNA6/1XlKVgnZoaZcQ7z7UJlOgj2JdbHE8tiYLS3fzXNCguct77SPGat2raSw==} + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} - '@aws-crypto/sha256-browser@3.0.0': - resolution: {integrity: sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==} + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} - '@aws-crypto/sha256-js@3.0.0': - resolution: {integrity: sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==} + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} - '@aws-crypto/supports-web-crypto@3.0.0': - resolution: {integrity: sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==} + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} - '@aws-crypto/util@3.0.0': - resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} + '@aws-sdk/client-s3@3.600.0': + resolution: {integrity: sha512-iYoKbJTputbf+ubkX6gSK/y/4uJEBRaXZ18jykLdBQ8UJuGrk2gqvV8h7OlGAhToCeysmmMqM0vDWyLt6lP8nw==} + engines: {node: '>=16.0.0'} - '@aws-sdk/client-s3@3.412.0': - resolution: {integrity: sha512-sNrlx9sSBmFUCqMgTznwk9Fee3PJat0nZ3RIDR5Crhsld/eexxrqb6TYKsxzFfBfXTL/oPh+/S5driRV2xsB8A==} - engines: {node: '>=14.0.0'} + '@aws-sdk/client-sso-oidc@3.600.0': + resolution: {integrity: sha512-7+I8RWURGfzvChyNQSyj5/tKrqRbzRl7H+BnTOf/4Vsw1nFOi5ROhlhD4X/Y0QCTacxnaoNcIrqnY7uGGvVRzw==} + engines: {node: '>=16.0.0'} - '@aws-sdk/client-sso@3.410.0': - resolution: {integrity: sha512-MC9GrgwtlOuSL2WS3DRM3dQ/5y+49KSMMJRH6JiEcU5vE0dX/OtEcX+VfEwpi73x5pSfIjm7xnzjzOFx+sQBIg==} - engines: {node: '>=14.0.0'} + '@aws-sdk/client-sso@3.598.0': + resolution: {integrity: sha512-nOI5lqPYa+YZlrrzwAJywJSw3MKVjvu6Ge2fCqQUNYMfxFB0NAaDFnl0EPjXi+sEbtCuz/uWE77poHbqiZ+7Iw==} + engines: {node: '>=16.0.0'} - '@aws-sdk/client-sts@3.410.0': - resolution: {integrity: sha512-e6VMrBJtnTxxUXwDmkADGIvyppmDMFf4+cGGA68tVCUm1cFNlCI6M/67bVSIPN/WVKAAfhEL5O2vVXCM7aatYg==} - engines: {node: '>=14.0.0'} + '@aws-sdk/client-sts@3.600.0': + resolution: {integrity: sha512-KQG97B7LvTtTiGmjlrG1LRAY8wUvCQzrmZVV5bjrJ/1oXAU7DITYwVbSJeX9NWg6hDuSk0VE3MFwIXS2SvfLIA==} + engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-env@3.410.0': - resolution: {integrity: sha512-c7TB9LbN0PkFOsXI0lcRJnqPNOmc4VBvrHf8jP/BkTDg4YUoKQKOFd4d0SqzODmlZiAyoMQVZTR4ISZo95Zj4Q==} - engines: {node: '>=14.0.0'} + '@aws-sdk/core@3.598.0': + resolution: {integrity: sha512-HaSjt7puO5Cc7cOlrXFCW0rtA0BM9lvzjl56x0A20Pt+0wxXGeTOZZOkXQIepbrFkV2e/HYukuT9e99vXDm59g==} + engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-ini@3.410.0': - resolution: {integrity: sha512-D8rcr5bRCFD0f42MPQ7K6TWZq5d3pfqrKINL1/bpfkK5BJbvq1BGYmR88UC6CLpTRtZ1LHY2HgYG0fp/2zjjww==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-env@3.598.0': + resolution: {integrity: sha512-vi1khgn7yXzLCcgSIzQrrtd2ilUM0dWodxj3PQ6BLfP0O+q1imO3hG1nq7DVyJtq7rFHs6+9N8G4mYvTkxby2w==} + engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-node@3.410.0': - resolution: {integrity: sha512-0wmVm33T/j1FS7MZ/j+WsPlgSc0YnCXnpbWSov1Mn6R86SHI2b2JhdIPRRE4XbGfyW2QGNUl2CwoZVaqhXeF5g==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-http@3.598.0': + resolution: {integrity: sha512-N7cIafi4HVlQvEgvZSo1G4T9qb/JMLGMdBsDCT5XkeJrF0aptQWzTFH0jIdZcLrMYvzPcuEyO3yCBe6cy/ba0g==} + engines: {node: '>=16.0.0'} - '@aws-sdk/credential-provider-process@3.410.0': - resolution: {integrity: sha512-BMju1hlDCDNkkSZpKF5SQ8G0WCLRj6/Jvw9QmudLHJuVwYJXEW1r2AsVMg98OZ3hB9G+MAvHruHZIbMiNmUMXQ==} - engines: {node: '>=14.0.0'} - - '@aws-sdk/credential-provider-sso@3.410.0': - resolution: {integrity: sha512-zEaoY/sY+KYTlQUkp9dvveAHf175b8RIt0DsQkDrRPtrg/RBHR00r5rFvz9+nrwsR8546RaBU7h/zzTaQGhmcA==} - engines: {node: '>=14.0.0'} - - '@aws-sdk/credential-provider-web-identity@3.410.0': - resolution: {integrity: sha512-cE0l8LmEHdWbDkdPNgrfdYSgp4/cIVXrjUKI1QCATA729CrHZ/OQjB/maOBOrMHO9YTiggko887NkslVvwVB7w==} - engines: {node: '>=14.0.0'} - - '@aws-sdk/lib-storage@3.412.0': - resolution: {integrity: sha512-uAdVtNuip06rJOs28zVrYXLNeHfKraxvJRTzTA+DW1dXkzh70GTKqDKHWH9IJkW/xMTE6wGSM+fDs8jsMOn/yA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-ini@3.598.0': + resolution: {integrity: sha512-/ppcIVUbRwDIwJDoYfp90X3+AuJo2mvE52Y1t2VSrvUovYn6N4v95/vXj6LS8CNDhz2jvEJYmu+0cTMHdhI6eA==} + engines: {node: '>=16.0.0'} peerDependencies: - '@aws-sdk/client-s3': ^3.0.0 + '@aws-sdk/client-sts': ^3.598.0 - '@aws-sdk/middleware-bucket-endpoint@3.410.0': - resolution: {integrity: sha512-pUGrpFgCKf9fDHu01JJhhw+MUImheS0HFlZwNG37OMubkxUAbCdmYGewGxfTCUvWyZJtx9bVjrSu6gG7w+RARg==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-node@3.600.0': + resolution: {integrity: sha512-1pC7MPMYD45J7yFjA90SxpR0yaSvy+yZiq23aXhAPZLYgJBAxHLu0s0mDCk/piWGPh8+UGur5K0bVdx4B1D5hw==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-expect-continue@3.410.0': - resolution: {integrity: sha512-e5YqGCNmW99GZjEPPujJ02RlEZql19U40oORysBhVF7mKz8BBvF3s8l37tvu37oxebDEkh1u/2cm2+ggOXxLjQ==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-process@3.598.0': + resolution: {integrity: sha512-rM707XbLW8huMk722AgjVyxu2tMZee++fNA8TJVNgs1Ma02Wx6bBrfIvlyK0rCcIRb0WdQYP6fe3Xhiu4e8IBA==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-flexible-checksums@3.410.0': - resolution: {integrity: sha512-IK7KlvEKtrQVBfmAp/MmGd0wbWLuN2GZwwfAmsU0qFb0f5vOVUbKDsu6tudtDKCBG9uXyTEsx3/QGvoK2zDy+g==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-sso@3.598.0': + resolution: {integrity: sha512-5InwUmrAuqQdOOgxTccRayMMkSmekdLk6s+az9tmikq0QFAHUCtofI+/fllMXSR9iL6JbGYi1940+EUmS4pHJA==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-host-header@3.410.0': - resolution: {integrity: sha512-ED/OVcyITln5rrxnajZP+V0PN1nug+gSDHJDqdDo/oLy7eiDr/ZWn3nlWW7WcMplQ1/Jnb+hK0UetBp/25XooA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/credential-provider-web-identity@3.598.0': + resolution: {integrity: sha512-GV5GdiMbz5Tz9JO4NJtRoFXjW0GPEujA0j+5J/B723rTN+REHthJu48HdBKouHGhdzkDWkkh1bu52V02Wprw8w==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sts': ^3.598.0 - '@aws-sdk/middleware-location-constraint@3.410.0': - resolution: {integrity: sha512-jAftSpOpw/5AdpOJ/cGiXCb+Vv22KXR5QZmxmllUDsnlm18672tpRaI2plmu/1d98CVvqhY61eSklFMrIf2c4w==} - engines: {node: '>=14.0.0'} + '@aws-sdk/lib-storage@3.600.0': + resolution: {integrity: sha512-jjgGMmFykXBAs8YO3ghgnVSjM/uf99jvVQqKJfDjwXUCLPrsZqk14v2WcDCWAXzeAroDvIOVQO1V/RR8fK18Pw==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-s3': ^3.600.0 - '@aws-sdk/middleware-logger@3.410.0': - resolution: {integrity: sha512-YtmKYCVtBfScq3/UFJk+aSZOktKJBNZL9DaSc2aPcy/goCVsYDOkGwtHk0jIkC1JRSNCkVTqL7ya60sSr8zaQQ==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-bucket-endpoint@3.598.0': + resolution: {integrity: sha512-PM7BcFfGUSkmkT6+LU9TyJiB4S8yI7dfuKQDwK5ZR3P7MKaK4Uj4yyDiv0oe5xvkF6+O2+rShj+eh8YuWkOZ/Q==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-recursion-detection@3.410.0': - resolution: {integrity: sha512-KWaes5FLzRqj28vaIEE4Bimpga2E596WdPF2HaH6zsVMJddoRDsc3ZX9ZhLOGrXzIO1RqBd0QxbLrM0S/B2aOQ==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-expect-continue@3.598.0': + resolution: {integrity: sha512-ZuHW18kaeHR8TQyhEOYMr8VwiIh0bMvF7J1OTqXHxDteQIavJWA3CbfZ9sgS4XGtrBZDyHJhjZKeCfLhN2rq3w==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-sdk-s3@3.410.0': - resolution: {integrity: sha512-K2sG2V1ZkezYMCIy3uMt0MwtflcfIwLptwm0iFLaYitiINZQ1tcslk9ggAjyTHg0rslDSI4/zjkhy8VHFOV7HA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-flexible-checksums@3.598.0': + resolution: {integrity: sha512-xukAzds0GQXvMEY9G6qt+CzwVzTx8NyKKh04O2Q+nOch6QQ8Rs+2kTRy3Z4wQmXq2pK9hlOWb5nXA7HWpmz6Ng==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-sdk-sts@3.410.0': - resolution: {integrity: sha512-YfBpctDocRR4CcROoDueJA7D+aMLBV8nTFfmVNdLLLgyuLZ/AUR11VQSu1lf9gQZKl8IpKE/BLf2fRE/qV1ZuA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-host-header@3.598.0': + resolution: {integrity: sha512-WiaG059YBQwQraNejLIi0gMNkX7dfPZ8hDIhvMr5aVPRbaHH8AYF3iNSsXYCHvA2Cfa1O9haYXsuMF9flXnCmA==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-signing@3.410.0': - resolution: {integrity: sha512-KBAZ/eoAJUSJv5us2HsKwK2OszG2s9FEyKpEhgnHLcbbKzW873zHBH5GcOGEQu4AWArTy2ndzJu3FF+9/J9hJQ==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-location-constraint@3.598.0': + resolution: {integrity: sha512-8oybQxN3F1ISOMULk7JKJz5DuAm5hCUcxMW9noWShbxTJuStNvuHf/WLUzXrf8oSITyYzIHPtf8VPlKR7I3orQ==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-ssec@3.410.0': - resolution: {integrity: sha512-DNsjVTXoxIh+PuW9o45CFaMiconbuZRm19MC3NA1yNCaCj3ZxD5OdXAutq6UjQdrx8UG4EjUlCJEEvBKmboITw==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-logger@3.598.0': + resolution: {integrity: sha512-bxBjf/VYiu3zfu8SYM2S9dQQc3tz5uBAOcPz/Bt8DyyK3GgOpjhschH/2XuUErsoUO1gDJqZSdGOmuHGZQn00Q==} + engines: {node: '>=16.0.0'} - '@aws-sdk/middleware-user-agent@3.410.0': - resolution: {integrity: sha512-ZayDtLfvCZUohSxQc/49BfoU/y6bDHLfLdyyUJbJ54Sv8zQcrmdyKvCBFUZwE6tHQgAmv9/ZT18xECMl+xiONA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-recursion-detection@3.598.0': + resolution: {integrity: sha512-vjT9BeFY9FeN0f8hm2l6F53tI0N5bUq6RcDkQXKNabXBnQxKptJRad6oP2X5y3FoVfBLOuDkQgiC2940GIPxtQ==} + engines: {node: '>=16.0.0'} - '@aws-sdk/signature-v4-multi-region@3.412.0': - resolution: {integrity: sha512-ijxOeYpNDuk2T940S9HYcZ1C+wTP9vqp1Cw37zw9whVY2mKV3Vr7i+44D4FQ5HhWULgdwhjD7IctbNxPIPzUZQ==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-sdk-s3@3.598.0': + resolution: {integrity: sha512-5AGtLAh9wyK6ANPYfaKTqJY1IFJyePIxsEbxa7zS6REheAqyVmgJFaGu3oQ5XlxfGr5Uq59tFTRkyx26G1HkHA==} + engines: {node: '>=16.0.0'} - '@aws-sdk/token-providers@3.410.0': - resolution: {integrity: sha512-d5Nc0xydkH/X0LA1HDyhGY5sEv4LuADFk+QpDtT8ogLilcre+b1jpdY8Sih/gd1KoGS1H+d1tz2hSGwUHAbUbw==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-signing@3.598.0': + resolution: {integrity: sha512-XKb05DYx/aBPqz6iCapsCbIl8aD8EihTuPCs51p75QsVfbQoVr4TlFfIl5AooMSITzojdAQqxt021YtvxjtxIQ==} + engines: {node: '>=16.0.0'} - '@aws-sdk/types@3.410.0': - resolution: {integrity: sha512-D7iaUCszv/v04NDaZUmCmekamy6VD/lKozm/3gS9+dkfU6cC2CsNoUfPV8BlV6dPdw0oWgF91am3I1stdvfVrQ==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-ssec@3.598.0': + resolution: {integrity: sha512-f0p2xP8IC1uJ5e/tND1l81QxRtRFywEdnbtKCE0H6RSn4UIt2W3Dohe1qQDbnh27okF0PkNW6BJGdSAz3p7qbA==} + engines: {node: '>=16.0.0'} - '@aws-sdk/types@3.413.0': - resolution: {integrity: sha512-j1xib0f/TazIFc5ySIKOlT1ujntRbaoG4LJFeEezz4ji03/wSJMI8Vi4KjzpBp8J1tTu0oRDnsxRIGixsUBeYQ==} - engines: {node: '>=14.0.0'} + '@aws-sdk/middleware-user-agent@3.598.0': + resolution: {integrity: sha512-4tjESlHG5B5MdjUaLK7tQs/miUtHbb6deauQx8ryqSBYOhfHVgb1ZnzvQR0bTrhpqUg0WlybSkDaZAICf9xctg==} + engines: {node: '>=16.0.0'} - '@aws-sdk/util-arn-parser@3.310.0': - resolution: {integrity: sha512-jL8509owp/xB9+Or0pvn3Fe+b94qfklc2yPowZZIFAkFcCSIdkIglz18cPDWnYAcy9JGewpMS1COXKIUhZkJsA==} - engines: {node: '>=14.0.0'} + '@aws-sdk/region-config-resolver@3.598.0': + resolution: {integrity: sha512-oYXhmTokSav4ytmWleCr3rs/1nyvZW/S0tdi6X7u+dLNL5Jee+uMxWGzgOrWK6wrQOzucLVjS4E/wA11Kv2GTw==} + engines: {node: '>=16.0.0'} - '@aws-sdk/util-endpoints@3.410.0': - resolution: {integrity: sha512-iNiqJyC7N3+8zFwnXUqcWSxrZecVZLToo1iTQQdeYL2af1IcOtRgb7n8jpAI/hmXhBSx2+3RI+Y7pxyFo1vu+w==} - engines: {node: '>=14.0.0'} + '@aws-sdk/signature-v4-multi-region@3.598.0': + resolution: {integrity: sha512-1r/EyTrO1gSa1FirnR8V7mabr7gk+l+HkyTI0fcTSr8ucB7gmYyW6WjkY8JCz13VYHFK62usCEDS7yoJoJOzTA==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/token-providers@3.598.0': + resolution: {integrity: sha512-TKY1EVdHVBnZqpyxyTHdpZpa1tUpb6nxVeRNn1zWG8QB5MvH4ALLd/jR+gtmWDNQbIG4cVuBOZFVL8hIYicKTA==} + engines: {node: '>=16.0.0'} + peerDependencies: + '@aws-sdk/client-sso-oidc': ^3.598.0 + + '@aws-sdk/types@3.598.0': + resolution: {integrity: sha512-742uRl6z7u0LFmZwDrFP6r1wlZcgVPw+/TilluDJmCAR8BgRw3IR+743kUXKBGd8QZDRW2n6v/PYsi/AWCDDMQ==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-arn-parser@3.568.0': + resolution: {integrity: sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w==} + engines: {node: '>=16.0.0'} + + '@aws-sdk/util-endpoints@3.598.0': + resolution: {integrity: sha512-Qo9UoiVVZxcOEdiOMZg3xb1mzkTxrhd4qSlg5QQrfWPJVx/QOg+Iy0NtGxPtHtVZNHZxohYwDwV/tfsnDSE2gQ==} + engines: {node: '>=16.0.0'} '@aws-sdk/util-locate-window@3.208.0': resolution: {integrity: sha512-iua1A2+P7JJEDHVgvXrRJSvsnzG7stYSGQnBVphIUlemwl6nN5D+QrgbjECtrbxRz8asYFHSzhdhECqN+tFiBg==} engines: {node: '>=14.0.0'} - '@aws-sdk/util-user-agent-browser@3.410.0': - resolution: {integrity: sha512-i1G/XGpXGMRT2zEiAhi1xucJsfCWk8nNYjk/LbC0sA+7B9Huri96YAzVib12wkHPsJQvZxZC6CpQDIHWm4lXMA==} + '@aws-sdk/util-user-agent-browser@3.598.0': + resolution: {integrity: sha512-36Sxo6F+ykElaL1mWzWjlg+1epMpSe8obwhCN1yGE7Js9ywy5U6k6l+A3q3YM9YRbm740sNxncbwLklMvuhTKw==} - '@aws-sdk/util-user-agent-node@3.410.0': - resolution: {integrity: sha512-bK70t1jHRl8HrJXd4hEIwc5PBZ7U0w+81AKFnanIVKZwZedd6nLibUXDTK14z/Jp2GFcBqd4zkt2YLGkRt/U4A==} - engines: {node: '>=14.0.0'} + '@aws-sdk/util-user-agent-node@3.598.0': + resolution: {integrity: sha512-oyWGcOlfTdzkC6SVplyr0AGh54IMrDxbhg5RxJ5P+V4BKfcDoDcZV9xenUk9NsOi9MuUjxMumb9UJGkDhM1m0A==} + engines: {node: '>=16.0.0'} peerDependencies: aws-crt: '>=1.0.0' peerDependenciesMeta: aws-crt: optional: true - '@aws-sdk/util-utf8-browser@3.259.0': - resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} - - '@aws-sdk/xml-builder@3.310.0': - resolution: {integrity: sha512-TqELu4mOuSIKQCqj63fGVs86Yh+vBx5nHRpWKNUNhB2nPTpfbziTs5c1X358be3peVWA4wPxW7Nt53KIg1tnNw==} - engines: {node: '>=14.0.0'} + '@aws-sdk/xml-builder@3.598.0': + resolution: {integrity: sha512-ZIa2RK7CHFTZ4gwK77WRtsZ6vF7xwRXxJ8KQIxK2duhoTVcn0xYxpFLdW9WZZZvdP9GIF3Loqvf8DRdeU5Jc7Q==} + engines: {node: '>=16.0.0'} '@babel/code-frame@7.23.5': resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.23.5': resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.24.7': + resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} + engines: {node: '>=6.9.0'} + '@babel/core@7.23.5': resolution: {integrity: sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==} engines: {node: '>=6.9.0'} - '@babel/core@7.24.0': - resolution: {integrity: sha512-fQfkg0Gjkza3nf0c7/w6Xf34BW4YvzNfACRLmmb7XRLa6XHdR+K9AlJlxneFfWYf6uhOzuzZVTjF/8KfndZANw==} + '@babel/core@7.24.7': + resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} engines: {node: '>=6.9.0'} '@babel/generator@7.23.5': resolution: {integrity: sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.23.6': - resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} + '@babel/generator@7.24.7': + resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.22.5': - resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + '@babel/helper-annotate-as-pure@7.24.7': + resolution: {integrity: sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==} engines: {node: '>=6.9.0'} - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.15': - resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} + '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7': + resolution: {integrity: sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==} engines: {node: '>=6.9.0'} '@babel/helper-compilation-targets@7.22.15': resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.23.6': - resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + '@babel/helper-compilation-targets@7.24.7': + resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.23.5': - resolution: {integrity: sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==} + '@babel/helper-create-class-features-plugin@7.24.7': + resolution: {integrity: sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-create-regexp-features-plugin@7.22.15': - resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} + '@babel/helper-create-regexp-features-plugin@7.24.7': + resolution: {integrity: sha512-03TCmXy2FtXJEZfbXDTSqq1fRJArk7lX9DOFC/47VthYcxyIOx+eXQmdo6DOQvrbpIix+KfXwvuXdFDZHxt+rA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-define-polyfill-provider@0.4.3': - resolution: {integrity: sha512-WBrLmuPP47n7PNwsZ57pqam6G/RGo1vw/87b0Blc53tZNGZ4x7YvZ6HgQe2vo1W/FR20OgjeZuGXzudPiXHFug==} + '@babel/helper-define-polyfill-provider@0.6.2': + resolution: {integrity: sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -1524,44 +1506,70 @@ packages: resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} engines: {node: '>=6.9.0'} + '@babel/helper-environment-visitor@7.24.7': + resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-function-name@7.23.0': resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} engines: {node: '>=6.9.0'} + '@babel/helper-function-name@7.24.7': + resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} + engines: {node: '>=6.9.0'} + '@babel/helper-hoist-variables@7.22.5': resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} - '@babel/helper-member-expression-to-functions@7.23.0': - resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} + '@babel/helper-hoist-variables@7.24.7': + resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-member-expression-to-functions@7.24.7': + resolution: {integrity: sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==} engines: {node: '>=6.9.0'} '@babel/helper-module-imports@7.22.15': resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.24.7': + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-transforms@7.23.3': resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-optimise-call-expression@7.22.5': - resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + '@babel/helper-module-transforms@7.24.7': + resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.24.7': + resolution: {integrity: sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==} engines: {node: '>=6.9.0'} '@babel/helper-plugin-utils@7.22.5': resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} engines: {node: '>=6.9.0'} - '@babel/helper-remap-async-to-generator@7.22.20': - resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} + '@babel/helper-plugin-utils@7.24.7': + resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.24.7': + resolution: {integrity: sha512-9pKLcTlZ92hNZMQfGCHImUpDOlAgkkpqalWEeftW5FBya75k8Li2ilerxkM/uBEj01iBZXcCIB/bwvDYgWyibA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-replace-supers@7.22.20': - resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} + '@babel/helper-replace-supers@7.24.7': + resolution: {integrity: sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1570,71 +1578,101 @@ packages: resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} engines: {node: '>=6.9.0'} - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': - resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + '@babel/helper-simple-access@7.24.7': + resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-skip-transparent-expression-wrappers@7.24.7': + resolution: {integrity: sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==} engines: {node: '>=6.9.0'} '@babel/helper-split-export-declaration@7.22.6': resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.23.4': resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.24.7': + resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.22.20': resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.23.5': resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} - '@babel/helper-wrap-function@7.22.20': - resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} + '@babel/helper-validator-option@7.24.7': + resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.24.7': + resolution: {integrity: sha512-N9JIYk3TD+1vq/wn77YnJOqMtfWhNewNE+DJV4puD2X7Ew9J4JvrzrFDfTfyv5EgEXVy9/Wt8QiOErzEmv5Ifw==} engines: {node: '>=6.9.0'} '@babel/helpers@7.23.5': resolution: {integrity: sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==} engines: {node: '>=6.9.0'} - '@babel/helpers@7.24.0': - resolution: {integrity: sha512-ulDZdc0Aj5uLc5nETsa7EPx2L7rM0YJM8r7ck7U73AXi7qOV44IHHRAYZHY6iU1rr3C5N4NtTmMRUJP6kwCWeA==} + '@babel/helpers@7.24.7': + resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} engines: {node: '>=6.9.0'} '@babel/highlight@7.23.4': resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} engines: {node: '>=6.9.0'} + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.23.9': resolution: {integrity: sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/parser@7.24.0': - resolution: {integrity: sha512-QuP/FxEAzMSjXygs8v4N9dvdXzEHN4W1oF3PxuWAtPo08UdM17u89RDMgjLn/mlc56iM0HlLmVkO/wgR+rDgHg==} - engines: {node: '>=6.0.0'} - hasBin: true - '@babel/parser@7.24.5': resolution: {integrity: sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==} engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3': - resolution: {integrity: sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==} + '@babel/parser@7.24.7': + resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.7': + resolution: {integrity: sha512-TiT1ss81W80eQsN+722OaeQMY/G4yTb4G9JrqeiDADs3N8lbPMGldWi9x8tyqCW5NLx1Jh2AvkE6r6QvEltMMQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3': - resolution: {integrity: sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==} + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.7': + resolution: {integrity: sha512-unaQgZ/iRu/By6tsjMZzpeBZjChYfLYry6HrEXPoz3KmfF0sVBQ1l8zKMQ4xRGLWVsjuvB8nQfjNP/DcfEOCsg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7': + resolution: {integrity: sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.13.0 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.3': - resolution: {integrity: sha512-XaJak1qcityzrX0/IU5nKHb34VaibwP3saKqG6a/tppelgllOH13LUann4ZCIBcVOeE6H18K4Vx9QKkVww3z/w==} + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.7': + resolution: {integrity: sha512-utA4HuR6F4Vvcr+o4DnjL8fCOlgRFGbeeBEGNg3ZTrLFw6VWG5XmUrvcQ0FjIYMU2ST4XcR2Wsp7t9qOAPnxMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 @@ -1682,14 +1720,14 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-assertions@7.23.3': - resolution: {integrity: sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==} + '@babel/plugin-syntax-import-assertions@7.24.7': + resolution: {integrity: sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-import-attributes@7.23.3': - resolution: {integrity: sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==} + '@babel/plugin-syntax-import-attributes@7.24.7': + resolution: {integrity: sha512-hbX+lKKeUMGihnK8nvKqmXBInriT3GVjzXKFriV3YC6APGxMbP8RZNFwy91+hocLXq90Mta+HshoB31802bb8A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1764,92 +1802,92 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-arrow-functions@7.23.3': - resolution: {integrity: sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==} + '@babel/plugin-transform-arrow-functions@7.24.7': + resolution: {integrity: sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-generator-functions@7.23.4': - resolution: {integrity: sha512-efdkfPhHYTtn0G6n2ddrESE91fgXxjlqLsnUtPWnJs4a4mZIbUaK7ffqKIIUKXSHwcDvaCVX6GXkaJJFqtX7jw==} + '@babel/plugin-transform-async-generator-functions@7.24.7': + resolution: {integrity: sha512-o+iF77e3u7ZS4AoAuJvapz9Fm001PuD2V3Lp6OSE4FYQke+cSewYtnek+THqGRWyQloRCyvWL1OkyfNEl9vr/g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-async-to-generator@7.23.3': - resolution: {integrity: sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==} + '@babel/plugin-transform-async-to-generator@7.24.7': + resolution: {integrity: sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoped-functions@7.23.3': - resolution: {integrity: sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==} + '@babel/plugin-transform-block-scoped-functions@7.24.7': + resolution: {integrity: sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-block-scoping@7.23.4': - resolution: {integrity: sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==} + '@babel/plugin-transform-block-scoping@7.24.7': + resolution: {integrity: sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-properties@7.23.3': - resolution: {integrity: sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==} + '@babel/plugin-transform-class-properties@7.24.7': + resolution: {integrity: sha512-vKbfawVYayKcSeSR5YYzzyXvsDFWU2mD8U5TFeXtbCPLFUqe7GyCgvO6XDHzje862ODrOwy6WCPmKeWHbCFJ4w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-class-static-block@7.23.4': - resolution: {integrity: sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==} + '@babel/plugin-transform-class-static-block@7.24.7': + resolution: {integrity: sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.12.0 - '@babel/plugin-transform-classes@7.23.5': - resolution: {integrity: sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==} + '@babel/plugin-transform-classes@7.24.7': + resolution: {integrity: sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-computed-properties@7.23.3': - resolution: {integrity: sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==} + '@babel/plugin-transform-computed-properties@7.24.7': + resolution: {integrity: sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-destructuring@7.23.3': - resolution: {integrity: sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==} + '@babel/plugin-transform-destructuring@7.24.7': + resolution: {integrity: sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dotall-regex@7.23.3': - resolution: {integrity: sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==} + '@babel/plugin-transform-dotall-regex@7.24.7': + resolution: {integrity: sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-duplicate-keys@7.23.3': - resolution: {integrity: sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==} + '@babel/plugin-transform-duplicate-keys@7.24.7': + resolution: {integrity: sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-dynamic-import@7.23.4': - resolution: {integrity: sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==} + '@babel/plugin-transform-dynamic-import@7.24.7': + resolution: {integrity: sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-exponentiation-operator@7.23.3': - resolution: {integrity: sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==} + '@babel/plugin-transform-exponentiation-operator@7.24.7': + resolution: {integrity: sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-export-namespace-from@7.23.4': - resolution: {integrity: sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==} + '@babel/plugin-transform-export-namespace-from@7.24.7': + resolution: {integrity: sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -1860,176 +1898,176 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-for-of@7.23.3': - resolution: {integrity: sha512-X8jSm8X1CMwxmK878qsUGJRmbysKNbdpTv/O1/v0LuY/ZkZrng5WYiekYSdg9m09OTmDDUWeEDsTE+17WYbAZw==} + '@babel/plugin-transform-for-of@7.24.7': + resolution: {integrity: sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-function-name@7.23.3': - resolution: {integrity: sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==} + '@babel/plugin-transform-function-name@7.24.7': + resolution: {integrity: sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-json-strings@7.23.4': - resolution: {integrity: sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==} + '@babel/plugin-transform-json-strings@7.24.7': + resolution: {integrity: sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-literals@7.23.3': - resolution: {integrity: sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==} + '@babel/plugin-transform-literals@7.24.7': + resolution: {integrity: sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-logical-assignment-operators@7.23.4': - resolution: {integrity: sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==} + '@babel/plugin-transform-logical-assignment-operators@7.24.7': + resolution: {integrity: sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-member-expression-literals@7.23.3': - resolution: {integrity: sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==} + '@babel/plugin-transform-member-expression-literals@7.24.7': + resolution: {integrity: sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-amd@7.23.3': - resolution: {integrity: sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==} + '@babel/plugin-transform-modules-amd@7.24.7': + resolution: {integrity: sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-commonjs@7.23.3': - resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==} + '@babel/plugin-transform-modules-commonjs@7.24.7': + resolution: {integrity: sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-systemjs@7.23.3': - resolution: {integrity: sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==} + '@babel/plugin-transform-modules-systemjs@7.24.7': + resolution: {integrity: sha512-GYQE0tW7YoaN13qFh3O1NCY4MPkUiAH3fiF7UcV/I3ajmDKEdG3l+UOcbAm4zUE3gnvUU+Eni7XrVKo9eO9auw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-modules-umd@7.23.3': - resolution: {integrity: sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==} + '@babel/plugin-transform-modules-umd@7.24.7': + resolution: {integrity: sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5': - resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + '@babel/plugin-transform-named-capturing-groups-regex@7.24.7': + resolution: {integrity: sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/plugin-transform-new-target@7.23.3': - resolution: {integrity: sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==} + '@babel/plugin-transform-new-target@7.24.7': + resolution: {integrity: sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-nullish-coalescing-operator@7.23.4': - resolution: {integrity: sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==} + '@babel/plugin-transform-nullish-coalescing-operator@7.24.7': + resolution: {integrity: sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-numeric-separator@7.23.4': - resolution: {integrity: sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==} + '@babel/plugin-transform-numeric-separator@7.24.7': + resolution: {integrity: sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-rest-spread@7.23.4': - resolution: {integrity: sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==} + '@babel/plugin-transform-object-rest-spread@7.24.7': + resolution: {integrity: sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-object-super@7.23.3': - resolution: {integrity: sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==} + '@babel/plugin-transform-object-super@7.24.7': + resolution: {integrity: sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-catch-binding@7.23.4': - resolution: {integrity: sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==} + '@babel/plugin-transform-optional-catch-binding@7.24.7': + resolution: {integrity: sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-optional-chaining@7.23.4': - resolution: {integrity: sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==} + '@babel/plugin-transform-optional-chaining@7.24.7': + resolution: {integrity: sha512-tK+0N9yd4j+x/4hxF3F0e0fu/VdcxU18y5SevtyM/PCFlQvXbR0Zmlo2eBrKtVipGNFzpq56o8WsIIKcJFUCRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-parameters@7.23.3': - resolution: {integrity: sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==} + '@babel/plugin-transform-parameters@7.24.7': + resolution: {integrity: sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-methods@7.23.3': - resolution: {integrity: sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==} + '@babel/plugin-transform-private-methods@7.24.7': + resolution: {integrity: sha512-COTCOkG2hn4JKGEKBADkA8WNb35TGkkRbI5iT845dB+NyqgO8Hn+ajPbSnIQznneJTa3d30scb6iz/DhH8GsJQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-private-property-in-object@7.23.4': - resolution: {integrity: sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==} + '@babel/plugin-transform-private-property-in-object@7.24.7': + resolution: {integrity: sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-property-literals@7.23.3': - resolution: {integrity: sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==} + '@babel/plugin-transform-property-literals@7.24.7': + resolution: {integrity: sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-regenerator@7.23.3': - resolution: {integrity: sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==} + '@babel/plugin-transform-regenerator@7.24.7': + resolution: {integrity: sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-reserved-words@7.23.3': - resolution: {integrity: sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==} + '@babel/plugin-transform-reserved-words@7.24.7': + resolution: {integrity: sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-shorthand-properties@7.23.3': - resolution: {integrity: sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==} + '@babel/plugin-transform-shorthand-properties@7.24.7': + resolution: {integrity: sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-spread@7.23.3': - resolution: {integrity: sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==} + '@babel/plugin-transform-spread@7.24.7': + resolution: {integrity: sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-sticky-regex@7.23.3': - resolution: {integrity: sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==} + '@babel/plugin-transform-sticky-regex@7.24.7': + resolution: {integrity: sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-template-literals@7.23.3': - resolution: {integrity: sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==} + '@babel/plugin-transform-template-literals@7.24.7': + resolution: {integrity: sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-typeof-symbol@7.23.3': - resolution: {integrity: sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==} + '@babel/plugin-transform-typeof-symbol@7.24.7': + resolution: {integrity: sha512-VtR8hDy7YLB7+Pet9IarXjg/zgCMSF+1mNS/EQEiEaUPoFXCVsHG64SIxcaaI2zJgRiv+YmgaQESUfWAdbjzgg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2040,32 +2078,32 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-escapes@7.23.3': - resolution: {integrity: sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==} + '@babel/plugin-transform-unicode-escapes@7.24.7': + resolution: {integrity: sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-property-regex@7.23.3': - resolution: {integrity: sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==} + '@babel/plugin-transform-unicode-property-regex@7.24.7': + resolution: {integrity: sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-regex@7.23.3': - resolution: {integrity: sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==} + '@babel/plugin-transform-unicode-regex@7.24.7': + resolution: {integrity: sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 - '@babel/plugin-transform-unicode-sets-regex@7.23.3': - resolution: {integrity: sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==} + '@babel/plugin-transform-unicode-sets-regex@7.24.7': + resolution: {integrity: sha512-2G8aAvF4wy1w/AGZkemprdGMRg5o6zPNhbHVImRz3lss55TYCBd6xStN19rt8XJHq20sqV0JbyWjOWwQRwV/wg==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 - '@babel/preset-env@7.23.5': - resolution: {integrity: sha512-0d/uxVD6tFGWXGDSfyMD1p2otoaKmu6+GD+NfAx0tMaH+dxORnp7T9TaVQ6mKyya7iBtCIVxHjWT7MuzzM9z+A==} + '@babel/preset-env@7.24.7': + resolution: {integrity: sha512-1YZNsc+y6cTvWlDHidMBsQZrZfEFjRIo/BZCT906PMdzOyXtSLTgqGdrpcuTDCXyd11Am5uQULtDIcCfnTc8fQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0-0 @@ -2108,12 +2146,16 @@ packages: resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} engines: {node: '>=6.9.0'} + '@babel/template@7.24.7': + resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.23.5': resolution: {integrity: sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==} engines: {node: '>=6.9.0'} - '@babel/traverse@7.24.0': - resolution: {integrity: sha512-HfuJlI8qq3dEDmNU5ChzzpZRWq+oxCZQyMzIMEqLho+AQnhMnKQUzH6ydo3RBl/YjPCuk68Y6s0Gx0AeyULiWw==} + '@babel/traverse@7.24.7': + resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} engines: {node: '>=6.9.0'} '@babel/types@7.23.5': @@ -2124,22 +2166,26 @@ packages: resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} engines: {node: '>=6.9.0'} + '@babel/types@7.24.7': + resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} + engines: {node: '>=6.9.0'} + '@base2/pretty-print-object@1.0.1': resolution: {integrity: sha512-4iri8i1AqYHJE2DstZYkyEprg6Pq6sKx3xn5FpySk9sNhH7qN2LLlHJCfDTZRILNwQNPD7mATWM0TBui7uC1pA==} '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@bull-board/api@5.17.0': - resolution: {integrity: sha512-qU+AiZIaYa//rkt1x7jDowtYa8u7/dLsDfEWgenZMkgvUszZ1kxJszdCtGapsDTVyPmnXgTRxpOWcR6sAYwSNQ==} + '@bull-board/api@5.20.5': + resolution: {integrity: sha512-YI95JK5A4/K4KB5VWbQn/CYNB+AO5cZ/BnZ77LxAhsaJ3ssHBN3Au0n3Z4wD7O+78+W3ON9uqGjKnHV6rXBGcQ==} peerDependencies: - '@bull-board/ui': 5.17.0 + '@bull-board/ui': 5.20.5 - '@bull-board/fastify@5.17.0': - resolution: {integrity: sha512-73YrPc7ERTWSOQRgBP6a7BPscWfcHd8U+Zq0auMdL/KkjPhG9GxapbfnovGZDDahJL/p/4YQb6ULu03zdtOrEA==} + '@bull-board/fastify@5.20.5': + resolution: {integrity: sha512-tdMR97xbzEzBbMJiJQreJHGdhfOocQn61K/WqM9I038Dk1dBHM5phQJxRJhspvwEJV4jwAayNOZbzuETI7QKwA==} - '@bull-board/ui@5.17.0': - resolution: {integrity: sha512-Vj+yWPjrjx3Iqh2N/ZBDhK2d2yJD44dfvIxm+SnXQb4ne312j117TpViInceysxGtbbAOlAW6hq6JvsDoRl7KQ==} + '@bull-board/ui@5.20.5': + resolution: {integrity: sha512-RV9VlW4qVL1A0Dewpsor4z7ZL9D56OW9LcRYjvXrIU5FSzvTvYKofmrUYoVrNQDs6jGMwJic+dMiW9K8GUU15A==} '@bundled-es-modules/cookie@2.0.0': resolution: {integrity: sha512-Or6YHg/kamKHpxULAdSqhGqnWFneIXu1NKvvfBBzKGwpVsYuFIQ5aBPHDnnoR3ghW1nvSkALd+EF9iMtY7Vjxw==} @@ -2219,12 +2265,18 @@ packages: cpu: [ppc64] os: [aix] - '@esbuild/aix-ppc64@0.20.2': - resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} + '@esbuild/aix-ppc64@0.21.5': + resolution: {integrity: sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==} engines: {node: '>=12'} cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.22.0': + resolution: {integrity: sha512-uvQR2crZ/zgzSHDvdygHyNI+ze9zwS8mqz0YtGXotSqvEE0UkYE9s+FZKQNTt1VtT719mfP3vHrUdCpxBNQZhQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.18.20': resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} engines: {node: '>=12'} @@ -2237,12 +2289,18 @@ packages: cpu: [arm64] os: [android] - '@esbuild/android-arm64@0.20.2': - resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==} + '@esbuild/android-arm64@0.21.5': + resolution: {integrity: sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==} engines: {node: '>=12'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.22.0': + resolution: {integrity: sha512-UKhPb3o2gAB/bfXcl58ZXTn1q2oVu1rEu/bKrCtmm+Nj5MKUbrOwR5WAixE2v+lk0amWuwPvhnPpBRLIGiq7ig==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.18.20': resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} engines: {node: '>=12'} @@ -2255,12 +2313,18 @@ packages: cpu: [arm] os: [android] - '@esbuild/android-arm@0.20.2': - resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==} + '@esbuild/android-arm@0.21.5': + resolution: {integrity: sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==} engines: {node: '>=12'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.22.0': + resolution: {integrity: sha512-PBnyP+r8vJE4ifxsWys9l+Mc2UY/yYZOpX82eoyGISXXb3dRr0M21v+s4fgRKWMFPMSf/iyowqPW/u7ScSUkjQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.18.20': resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} engines: {node: '>=12'} @@ -2273,12 +2337,18 @@ packages: cpu: [x64] os: [android] - '@esbuild/android-x64@0.20.2': - resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==} + '@esbuild/android-x64@0.21.5': + resolution: {integrity: sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==} engines: {node: '>=12'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.22.0': + resolution: {integrity: sha512-IjTYtvIrjhR41Ijy2dDPgYjQHWG/x/A4KXYbs1fiU3efpRdoxMChK3oEZV6GPzVEzJqxFgcuBaiX1kwEvWUxSw==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.18.20': resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} engines: {node: '>=12'} @@ -2291,12 +2361,18 @@ packages: cpu: [arm64] os: [darwin] - '@esbuild/darwin-arm64@0.20.2': - resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==} + '@esbuild/darwin-arm64@0.21.5': + resolution: {integrity: sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==} engines: {node: '>=12'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.22.0': + resolution: {integrity: sha512-mqt+Go4y9wRvEz81bhKd9RpHsQR1LwU8Xm6jZRUV/xpM7cIQFbFH6wBCLPTNsdELBvfoHeumud7X78jQQJv2TA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.18.20': resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} engines: {node: '>=12'} @@ -2309,12 +2385,18 @@ packages: cpu: [x64] os: [darwin] - '@esbuild/darwin-x64@0.20.2': - resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==} + '@esbuild/darwin-x64@0.21.5': + resolution: {integrity: sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==} engines: {node: '>=12'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.22.0': + resolution: {integrity: sha512-vTaTQ9OgYc3VTaWtOE5pSuDT6H3d/qSRFRfSBbnxFfzAvYoB3pqKXA0LEbi/oT8GUOEAutspfRMqPj2ezdFaMw==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.18.20': resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} engines: {node: '>=12'} @@ -2327,12 +2409,18 @@ packages: cpu: [arm64] os: [freebsd] - '@esbuild/freebsd-arm64@0.20.2': - resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==} + '@esbuild/freebsd-arm64@0.21.5': + resolution: {integrity: sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==} engines: {node: '>=12'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.22.0': + resolution: {integrity: sha512-0e1ZgoobJzaGnR4reD7I9rYZ7ttqdh1KPvJWnquUoDJhL0rYwdneeLailBzd2/4g/U5p4e5TIHEWa68NF2hFpQ==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.18.20': resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} engines: {node: '>=12'} @@ -2345,12 +2433,18 @@ packages: cpu: [x64] os: [freebsd] - '@esbuild/freebsd-x64@0.20.2': - resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==} + '@esbuild/freebsd-x64@0.21.5': + resolution: {integrity: sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==} engines: {node: '>=12'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.22.0': + resolution: {integrity: sha512-BFgyYwlCwRWyPQJtkzqq2p6pJbiiWgp0P9PNf7a5FQ1itKY4czPuOMAlFVItirSmEpRPCeImuwePNScZS0pL5Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.18.20': resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} engines: {node: '>=12'} @@ -2363,12 +2457,18 @@ packages: cpu: [arm64] os: [linux] - '@esbuild/linux-arm64@0.20.2': - resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==} + '@esbuild/linux-arm64@0.21.5': + resolution: {integrity: sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==} engines: {node: '>=12'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.22.0': + resolution: {integrity: sha512-V/K2rctCUgC0PCXpN7AqT4hoazXKgIYugFGu/myk2+pfe6jTW2guz/TBwq4cZ7ESqusR/IzkcQaBkcjquuBWsw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.18.20': resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} engines: {node: '>=12'} @@ -2381,12 +2481,18 @@ packages: cpu: [arm] os: [linux] - '@esbuild/linux-arm@0.20.2': - resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==} + '@esbuild/linux-arm@0.21.5': + resolution: {integrity: sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==} engines: {node: '>=12'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.22.0': + resolution: {integrity: sha512-KEMWiA9aGuPUD4BH5yjlhElLgaRXe+Eri6gKBoDazoPBTo1BXc/e6IW5FcJO9DoL19FBeCxgONyh95hLDNepIg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.18.20': resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} engines: {node: '>=12'} @@ -2399,12 +2505,18 @@ packages: cpu: [ia32] os: [linux] - '@esbuild/linux-ia32@0.20.2': - resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==} + '@esbuild/linux-ia32@0.21.5': + resolution: {integrity: sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==} engines: {node: '>=12'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.22.0': + resolution: {integrity: sha512-r2ZZqkOMOrpUhzNwxI7uLAHIDwkfeqmTnrv1cjpL/rjllPWszgqmprd/om9oviKXUBpMqHbXmppvjAYgISb26Q==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.18.20': resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} engines: {node: '>=12'} @@ -2417,12 +2529,18 @@ packages: cpu: [loong64] os: [linux] - '@esbuild/linux-loong64@0.20.2': - resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==} + '@esbuild/linux-loong64@0.21.5': + resolution: {integrity: sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==} engines: {node: '>=12'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.22.0': + resolution: {integrity: sha512-qaowLrV/YOMAL2RfKQ4C/VaDzAuLDuylM2sd/LH+4OFirMl6CuDpRlCq4u49ZBaVV8pkI/Y+hTdiibvQRhojCA==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.18.20': resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} engines: {node: '>=12'} @@ -2435,12 +2553,18 @@ packages: cpu: [mips64el] os: [linux] - '@esbuild/linux-mips64el@0.20.2': - resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==} + '@esbuild/linux-mips64el@0.21.5': + resolution: {integrity: sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==} engines: {node: '>=12'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.22.0': + resolution: {integrity: sha512-hgrezzjQTRxjkQ5k08J6rtZN5PNnkWx/Rz6Kmj9gnsdCAX1I4Dn4ZPqvFRkXo55Q3pnVQJBwbdtrTO7tMGtyVA==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.18.20': resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} engines: {node: '>=12'} @@ -2453,12 +2577,18 @@ packages: cpu: [ppc64] os: [linux] - '@esbuild/linux-ppc64@0.20.2': - resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==} + '@esbuild/linux-ppc64@0.21.5': + resolution: {integrity: sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==} engines: {node: '>=12'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.22.0': + resolution: {integrity: sha512-ewxg6FLLUio883XgSjfULEmDl3VPv/TYNnRprVAS3QeGFLdCYdx1tIudBcd7n9jIdk82v1Ajov4jx87qW7h9+g==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.18.20': resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} engines: {node: '>=12'} @@ -2471,12 +2601,18 @@ packages: cpu: [riscv64] os: [linux] - '@esbuild/linux-riscv64@0.20.2': - resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==} + '@esbuild/linux-riscv64@0.21.5': + resolution: {integrity: sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==} engines: {node: '>=12'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.22.0': + resolution: {integrity: sha512-Az5XbgSJC2lE8XK8pdcutsf9RgdafWdTpUK/+6uaDdfkviw/B4JCwAfh1qVeRWwOohwdsl4ywZrWBNWxwrPLFg==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.18.20': resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} engines: {node: '>=12'} @@ -2489,12 +2625,18 @@ packages: cpu: [s390x] os: [linux] - '@esbuild/linux-s390x@0.20.2': - resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==} + '@esbuild/linux-s390x@0.21.5': + resolution: {integrity: sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==} engines: {node: '>=12'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.22.0': + resolution: {integrity: sha512-8j4a2ChT9+V34NNNY9c/gMldutaJFmfMacTPq4KfNKwv2fitBCLYjee7c+Vxaha2nUhPK7cXcZpJtJ3+Y7ZdVQ==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.18.20': resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} engines: {node: '>=12'} @@ -2507,12 +2649,18 @@ packages: cpu: [x64] os: [linux] - '@esbuild/linux-x64@0.20.2': - resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==} + '@esbuild/linux-x64@0.21.5': + resolution: {integrity: sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==} engines: {node: '>=12'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.22.0': + resolution: {integrity: sha512-JUQyOnpbAkkRFOk/AhsEemz5TfWN4FJZxVObUlnlNCbe7QBl61ZNfM4cwBXayQA6laMJMUcqLHaYQHAB6YQ95Q==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-x64@0.18.20': resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} engines: {node: '>=12'} @@ -2525,12 +2673,24 @@ packages: cpu: [x64] os: [netbsd] - '@esbuild/netbsd-x64@0.20.2': - resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==} + '@esbuild/netbsd-x64@0.21.5': + resolution: {integrity: sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==} engines: {node: '>=12'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.22.0': + resolution: {integrity: sha512-11PoCoHXo4HFNbLsXuMB6bpMPWGDiw7xETji6COdJss4SQZLvcgNoeSqWtATRm10Jj1uEHiaIk4N0PiN6x4Fcg==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.22.0': + resolution: {integrity: sha512-Ezlhu/YyITmXwKSB+Zu/QqD7cxrjrpiw85cc0Rbd3AWr2wsgp+dWbWOE8MqHaLW9NKMZvuL0DhbJbvzR7F6Zvg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.18.20': resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} engines: {node: '>=12'} @@ -2543,12 +2703,18 @@ packages: cpu: [x64] os: [openbsd] - '@esbuild/openbsd-x64@0.20.2': - resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==} + '@esbuild/openbsd-x64@0.21.5': + resolution: {integrity: sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==} engines: {node: '>=12'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.22.0': + resolution: {integrity: sha512-ufjdW5tFJGUjlH9j/5cCE9lrwRffyZh+T4vYvoDKoYsC6IXbwaFeV/ENxeNXcxotF0P8CDzoICXVSbJaGBhkrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + '@esbuild/sunos-x64@0.18.20': resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} engines: {node: '>=12'} @@ -2561,12 +2727,18 @@ packages: cpu: [x64] os: [sunos] - '@esbuild/sunos-x64@0.20.2': - resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==} + '@esbuild/sunos-x64@0.21.5': + resolution: {integrity: sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==} engines: {node: '>=12'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.22.0': + resolution: {integrity: sha512-zY6ly/AoSmKnmNTowDJsK5ehra153/5ZhqxNLfq9NRsTTltetr+yHHcQ4RW7QDqw4JC8A1uC1YmeSfK9NRcK1w==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.18.20': resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} engines: {node: '>=12'} @@ -2579,12 +2751,18 @@ packages: cpu: [arm64] os: [win32] - '@esbuild/win32-arm64@0.20.2': - resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==} + '@esbuild/win32-arm64@0.21.5': + resolution: {integrity: sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==} engines: {node: '>=12'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.22.0': + resolution: {integrity: sha512-Kml5F7tv/1Maam0pbbCrvkk9vj046dPej30kFzlhXnhuCtYYBP6FGy/cLbc5yUT1lkZznGLf2OvuvmLjscO5rw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.18.20': resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} engines: {node: '>=12'} @@ -2597,12 +2775,18 @@ packages: cpu: [ia32] os: [win32] - '@esbuild/win32-ia32@0.20.2': - resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==} + '@esbuild/win32-ia32@0.21.5': + resolution: {integrity: sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==} engines: {node: '>=12'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.22.0': + resolution: {integrity: sha512-IOgwn+mYTM3RrcydP4Og5IpXh+ftN8oF+HELTXSmbWBlujuci4Qa3DTeO+LEErceisI7KUSfEIiX+WOUlpELkw==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.18.20': resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} engines: {node: '>=12'} @@ -2615,12 +2799,18 @@ packages: cpu: [x64] os: [win32] - '@esbuild/win32-x64@0.20.2': - resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==} + '@esbuild/win32-x64@0.21.5': + resolution: {integrity: sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==} engines: {node: '>=12'} cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.22.0': + resolution: {integrity: sha512-4bDHJrk2WHBXJPhy1y80X7/5b5iZTZP3LGcKIlAP1J+KqZ4zQAPMLEzftGyjjfcKbA4JDlPt/+2R/F1ZTeRgrw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.4.0': resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -2635,17 +2825,25 @@ packages: resolution: {integrity: sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/eslintrc@2.1.4': - resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/compat@1.1.0': + resolution: {integrity: sha512-s9Wi/p25+KbzxKlDm3VshQdImhWk+cbdblhwGNnyCU5lpSwtWa4v7VQCxSki0FAUrGA3s8nCWgYzAH41mwQVKQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.53.0': - resolution: {integrity: sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/config-array@0.17.0': + resolution: {integrity: sha512-A68TBu6/1mHHuc5YJL0U0VVeGNiklLAL6rRmhTCP2B5XjWLMnrX+HkO+IAXyHvks5cyyY1jjK5ITPQ1HGS2EVA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@8.57.0': - resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + '@eslint/eslintrc@3.1.0': + resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.6.0': + resolution: {integrity: sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.4': + resolution: {integrity: sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@fal-works/esbuild-plugin-global-externals@2.1.2': resolution: {integrity: sha512-cEee/Z+I12mZcFJshKcCqC8tuX5hG3s+d+9nZ3LabqKF1vKdF41B92pJVCBggjAGORAeOzyyDDKrZwIkLffeOQ==} @@ -2685,8 +2883,8 @@ packages: '@fastify/http-proxy@9.5.0': resolution: {integrity: sha512-1iqIdV10d5k9YtfHq9ylX5zt1NiM50fG+rIX40qt00R694sqWso3ukyTFZVk33SDoSiBW8roB7n11RUVUoN+Ag==} - '@fastify/multipart@8.2.0': - resolution: {integrity: sha512-OZ8nsyyoS2TV7Yeu3ZdrdDGsKUTAbfjrKC9jSxGgT2qdgek+BxpWX31ZubTrWMNZyU5xwk4ox6AvTjAbYWjrWg==} + '@fastify/multipart@8.3.0': + resolution: {integrity: sha512-A8h80TTyqUzaMVH0Cr9Qcm6RxSkVqmhK/MVBYHYeRRSUbUYv08WecjWKSlG2aSnD4aGI841pVxAjC+G1GafUeQ==} '@fastify/reply-from@9.0.1': resolution: {integrity: sha512-q9vFNUiXZTY1x8omDPe59os2MYq+3y7KgO/kZoXpZlnud+45Nd8Ot/svEvrUATzjkizIggfS4K8LR9zXDyZZKg==} @@ -2697,8 +2895,8 @@ packages: '@fastify/static@6.12.0': resolution: {integrity: sha512-KK1B84E6QD/FcQWxDI2aiUCwHxMJBI1KeCUzm1BwYpPY1b742+jeKruGHP2uOluuM6OkBPI8CIANrXcCRtC2oQ==} - '@fastify/static@7.0.3': - resolution: {integrity: sha512-2tmTdF+uFCykasutaO6k4/wOt7eXyi7m3dGuCPo5micXzv0qt6ttb/nWnDYL/BlXjYGfp1JI4a1gyluTIylvQA==} + '@fastify/static@7.0.4': + resolution: {integrity: sha512-p2uKtaf8BMOZWLs6wu+Ihg7bWNBdjNgCwDza4MJtTqg+5ovKmcbgbR9Xs5/smZ1YISfzKOCNYmZV8LaCj+eJ1Q==} '@fastify/view@8.2.0': resolution: {integrity: sha512-hBSiBofCnJNlPHEMZWpO1SL84eqOaqujJ1hR3jntFyZZCkweH5jMs12DKYyGesjVll7SJFRRxPUBB8kmUmneRQ==} @@ -2716,11 +2914,8 @@ packages: '@hapi/bourne@3.0.0': resolution: {integrity: sha512-Waj1cwPXJDucOib4a3bAISsKJVb15MKi9IvmTI/7ssVEm6sywXGjVJDhl6/umt1pK1ZS7PacXU3A1PmFKHEZ2w==} - '@hapi/hoek@10.0.1': - resolution: {integrity: sha512-CvlW7jmOhWzuqOqiJQ3rQVLMcREh0eel4IBnxDx2FAcK8g7qoJRQK4L1CPBASoCY6y8e6zuCy3f2g+HWdkzcMw==} - - '@hapi/hoek@11.0.2': - resolution: {integrity: sha512-aKmlCO57XFZ26wso4rJsW4oTUnrgTFw2jh3io7CAtO9w4UltBNwRXvXIVzzyfkaaLRo3nluP/19msA8vDUUuKw==} + '@hapi/hoek@11.0.4': + resolution: {integrity: sha512-PnsP5d4q7289pS2T2EgGz147BFJ2Jpb4yrEdkpz2IhgEUzos1S7HTl7ezWh1yfYzYlj89KzLdCRkqsP6SIryeQ==} '@hapi/hoek@9.3.0': resolution: {integrity: sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==} @@ -2734,14 +2929,6 @@ packages: '@hexagon/base64@1.1.27': resolution: {integrity: sha512-PdUmzpvcUM3Rh39kvz9RdbPVYhMjBjdV7Suw7ZduP7urRLsZR8l5tzgSWKm7TExwBYDFwTnYrZbnE0rQ3N5NLQ==} - '@humanwhocodes/config-array@0.11.13': - resolution: {integrity: sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==} - engines: {node: '>=10.10.0'} - - '@humanwhocodes/config-array@0.11.14': - resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} - engines: {node: '>=10.10.0'} - '@humanwhocodes/module-importer@1.0.1': resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} engines: {node: '>=12.22'} @@ -2750,20 +2937,18 @@ packages: resolution: {integrity: sha512-RE815I4arJFtt+FVeU1Tgp9/Xvecacji8w/V6XtXsWWH/wz/eNkNbhb+ny/+PlVZjV0rxQpRSQKNKE3lcktHEA==} engines: {node: '>=10.10.0'} - '@humanwhocodes/object-schema@2.0.1': - resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} + '@humanwhocodes/retry@0.3.0': + resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==} + engines: {node: '>=18.18'} - '@humanwhocodes/object-schema@2.0.2': - resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} - - '@img/sharp-darwin-arm64@0.33.3': - resolution: {integrity: sha512-FaNiGX1MrOuJ3hxuNzWgsT/mg5OHG/Izh59WW2mk1UwYHUwtfbhk5QNKYZgxf0pLOhx9ctGiGa2OykD71vOnSw==} + '@img/sharp-darwin-arm64@0.33.4': + resolution: {integrity: sha512-p0suNqXufJs9t3RqLBO6vvrgr5OhgbWp76s5gTRvdmxmuv9E1rcaqGUsl3l4mKVmXPkTkTErXediAui4x+8PSA==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [darwin] - '@img/sharp-darwin-x64@0.33.3': - resolution: {integrity: sha512-2QeSl7QDK9ru//YBT4sQkoq7L0EAJZA3rtV+v9p8xTKl4U1bUqTIaCnoC7Ctx2kCjQgwFXDasOtPTCT8eCTXvw==} + '@img/sharp-darwin-x64@0.33.4': + resolution: {integrity: sha512-0l7yRObwtTi82Z6ebVI2PnHT8EB2NxBgpK2MiKJZJ7cz32R4lxd001ecMhzzsZig3Yv9oclvqqdV93jo9hy+Dw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [darwin] @@ -2816,55 +3001,55 @@ packages: cpu: [x64] os: [linux] - '@img/sharp-linux-arm64@0.33.3': - resolution: {integrity: sha512-Zf+sF1jHZJKA6Gor9hoYG2ljr4wo9cY4twaxgFDvlG0Xz9V7sinsPp8pFd1XtlhTzYo0IhDbl3rK7P6MzHpnYA==} + '@img/sharp-linux-arm64@0.33.4': + resolution: {integrity: sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] - '@img/sharp-linux-arm@0.33.3': - resolution: {integrity: sha512-Q7Ee3fFSC9P7vUSqVEF0zccJsZ8GiiCJYGWDdhEjdlOeS9/jdkyJ6sUSPj+bL8VuOYFSbofrW0t/86ceVhx32w==} + '@img/sharp-linux-arm@0.33.4': + resolution: {integrity: sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==} engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm] os: [linux] - '@img/sharp-linux-s390x@0.33.3': - resolution: {integrity: sha512-vFk441DKRFepjhTEH20oBlFrHcLjPfI8B0pMIxGm3+yilKyYeHEVvrZhYFdqIseSclIqbQ3SnZMwEMWonY5XFA==} - engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} + '@img/sharp-linux-s390x@0.33.4': + resolution: {integrity: sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==} + engines: {glibc: '>=2.31', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] - '@img/sharp-linux-x64@0.33.3': - resolution: {integrity: sha512-Q4I++herIJxJi+qmbySd072oDPRkCg/SClLEIDh5IL9h1zjhqjv82H0Seupd+q2m0yOfD+/fJnjSoDFtKiHu2g==} + '@img/sharp-linux-x64@0.33.4': + resolution: {integrity: sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] - '@img/sharp-linuxmusl-arm64@0.33.3': - resolution: {integrity: sha512-qnDccehRDXadhM9PM5hLvcPRYqyFCBN31kq+ErBSZtZlsAc1U4Z85xf/RXv1qolkdu+ibw64fUDaRdktxTNP9A==} + '@img/sharp-linuxmusl-arm64@0.33.4': + resolution: {integrity: sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] - '@img/sharp-linuxmusl-x64@0.33.3': - resolution: {integrity: sha512-Jhchim8kHWIU/GZ+9poHMWRcefeaxFIs9EBqf9KtcC14Ojk6qua7ghKiPs0sbeLbLj/2IGBtDcxHyjCdYWkk2w==} + '@img/sharp-linuxmusl-x64@0.33.4': + resolution: {integrity: sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] - '@img/sharp-wasm32@0.33.3': - resolution: {integrity: sha512-68zivsdJ0koE96stdUfM+gmyaK/NcoSZK5dV5CAjES0FUXS9lchYt8LAB5rTbM7nlWtxaU/2GON0HVN6/ZYJAQ==} + '@img/sharp-wasm32@0.33.4': + resolution: {integrity: sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [wasm32] - '@img/sharp-win32-ia32@0.33.3': - resolution: {integrity: sha512-CyimAduT2whQD8ER4Ux7exKrtfoaUiVr7HG0zZvO0XTFn2idUWljjxv58GxNTkFb8/J9Ub9AqITGkJD6ZginxQ==} + '@img/sharp-win32-ia32@0.33.4': + resolution: {integrity: sha512-99SJ91XzUhYHbx7uhK3+9Lf7+LjwMGQZMDlO/E/YVJ7Nc3lyDFZPGhjwiYdctoH2BOzW9+TnfqcaMKt0jHLdqw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [ia32] os: [win32] - '@img/sharp-win32-x64@0.33.3': - resolution: {integrity: sha512-viT4fUIDKnli3IfOephGnolMzhz5VaTvDRkYqtZxOMIoMQ4MrAziO7pT1nVnOt2FAm7qW5aa+CCc13aEY6Le0g==} + '@img/sharp-win32-x64@0.33.4': + resolution: {integrity: sha512-3QLocdTRVIrFNye5YocZl+KKpYKP+fksi1QhmOArgx7GyhIbQp/WrJRu176jm8IxromS7RIkzMiMINVdBtC8Aw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [win32] @@ -2982,8 +3167,8 @@ packages: resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - '@joshwooding/vite-plugin-react-docgen-typescript@0.3.0': - resolution: {integrity: sha512-2D6y7fNvFmsLmRt6UCOFJPvFoPMJGT0Uh1Wg0RaigUp7kdQPs6yYn8Dmx6GZkOH/NW0yMTwRz/p0SRMMRo50vA==} + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1': + resolution: {integrity: sha512-pdoMZ9QaPnVlSM+SdU/wgg0nyD/8wQ7y90ttO2CMCyrrm7RxveYIJ5eNfjPaoMFqW41LZra7QO9j+xV4Y18Glw==} peerDependencies: typescript: '>= 4.3.x' vite: ^3.0.0 || ^4.0.0 || ^5.0.0 @@ -2995,6 +3180,10 @@ packages: resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==} engines: {node: '>=6.0.0'} + '@jridgewell/gen-mapping@0.3.5': + resolution: {integrity: sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==} + engines: {node: '>=6.0.0'} + '@jridgewell/resolve-uri@3.1.0': resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} engines: {node: '>=6.0.0'} @@ -3003,6 +3192,10 @@ packages: resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} engines: {node: '>=6.0.0'} + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + '@jridgewell/source-map@0.3.5': resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==} @@ -3015,6 +3208,9 @@ packages: '@jridgewell/trace-mapping@0.3.18': resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@jsdevtools/ono@7.1.3': resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} @@ -3048,29 +3244,31 @@ packages: '@types/react': '>=16' react: '>=16' - '@microsoft/api-extractor-model@7.28.14': - resolution: {integrity: sha512-Bery/c8A8SsKPSvA82cTTuy/+OcxZbLRmKhPkk91/AJOQzxZsShcrmHFAGeiEqSIrv1nPZ3tKq9kfMLdCHmsqg==} + '@microsoft/api-extractor-model@7.29.2': + resolution: {integrity: sha512-hAYajOjQan3uslhKJRwvvHIdLJ+ZByKqdSsJ/dgHFxPtEbdKpzMDO8zuW4K5gkSMYl5D0LbNwxkhxr51P2zsmw==} - '@microsoft/api-extractor@7.43.1': - resolution: {integrity: sha512-ohg40SsvFFgzHFAtYq5wKJc8ZDyY46bphjtnSvhSSlXpPTG7GHwyyXkn48UZiUCBwr2WC7TRC1Jfwz7nreuiyQ==} + '@microsoft/api-extractor@7.47.0': + resolution: {integrity: sha512-LT8yvcWNf76EpDC+8/ArTVSYePvuDQ+YbAUrsTcpg3ptiZ93HIcMCozP/JOxDt+rrsFfFHcpfoselKfPyRI0GQ==} hasBin: true - '@microsoft/tsdoc-config@0.16.2': - resolution: {integrity: sha512-OGiIzzoBLgWWR0UdRJX98oYO+XKGf7tiK4Zk6tQ/E4IJqGCe7dvkTvgDZV5cFJUzLGDOjeAXrnZoA6QkVySuxw==} + '@microsoft/tsdoc-config@0.17.0': + resolution: {integrity: sha512-v/EYRXnCAIHxOHW+Plb6OWuUoMotxTN0GLatnpOb1xq0KuTNw/WI3pamJx/UbsoJP5k9MCw1QxvvhPcF9pH3Zg==} - '@microsoft/tsdoc@0.14.2': - resolution: {integrity: sha512-9b8mPpKrfeGRuhFH5iO1iwCLeIIsV6+H1sRfxbkoGXIyQE2BTsPd9zqSqQJ+pv5sJ/hT5M1zvOFL02MnEezFug==} + '@microsoft/tsdoc@0.15.0': + resolution: {integrity: sha512-HZpPoABogPvjeJOdzCOSJsXeL/SMCBgBZMVC3X3d7YYp2gf31MfxhUoYUNwf1ERPJOnQc0wkFn9trqI6ZEdZuA==} '@misskey-dev/browser-image-resizer@2024.1.0': resolution: {integrity: sha512-4EnO0zLW5NDtng3Gaz5MuT761uiuoOuplwX18wBqgj8w56LTU5BjLn/vbHwDIIe0j2gwqDYhMb7bDjmr1/Fomg==} - '@misskey-dev/eslint-plugin@1.0.0': - resolution: {integrity: sha512-dh6UbcrNDVg5DD8k8Qh4ab30OPpuEYIlJCqaBV/lkIV8wNN/AfCJ2V7iTP8V8KjryM4t+sf5IqzQLQnT0mWI4A==} + '@misskey-dev/eslint-plugin@2.0.2': + resolution: {integrity: sha512-bnTqxCSP0CIN0xSpIGib13bz+K8/3e4h8OlQjuCPlhZF7oFwtn339EZM8yJkHg6gdfciV8KOr3gzlLyG3jiVEQ==} peerDependencies: - '@typescript-eslint/eslint-plugin': '>= 6' - '@typescript-eslint/parser': '>= 6' - eslint: '>= 3' + '@eslint/compat': '>= 1' + '@typescript-eslint/eslint-plugin': '>= 7' + '@typescript-eslint/parser': '>= 7' + eslint: '>= 8' eslint-plugin-import: '>= 2' + globals: '>= 15' '@misskey-dev/sharp-read-bmp@1.2.0': resolution: {integrity: sha512-er4pRakXzHYfEgOFAFfQagqDouG+wLm+kwNq1I30oSdIHDa0wM3KjFpfIGQ25Fks4GcmOl1s7Zh6xoQu5dNjTw==} @@ -3116,73 +3314,73 @@ packages: resolution: {integrity: sha512-0ZcCVQxifZmhwNBoQIrystCb+2sWBY2Zw8lpfJBPCHGCA/HWqehITeCRVIv4VMy8MPlaHo2w2pTHFV2pFfqKPw==} engines: {node: '>=18'} - '@mswjs/interceptors@0.26.15': - resolution: {integrity: sha512-HM47Lu1YFmnYHKMBynFfjCp0U/yRskHj/8QEJW0CBEPOlw8Gkmjfll+S9b8M7V5CNDw2/ciRxjjnWeaCiblSIQ==} + '@mswjs/interceptors@0.29.1': + resolution: {integrity: sha512-3rDakgJZ77+RiQUuSK69t1F0m8BQKA8Vh5DCS5V0DWvNY67zob2JhhQrhCO0AKLGINTRSFd1tBaHcJTkhefoSw==} engines: {node: '>=18'} - '@napi-rs/canvas-android-arm64@0.1.52': - resolution: {integrity: sha512-x/K471KbASPVh5mfBUxokza66J0FNIlOgMNANWAf5C8HiATb487KecEhSkUQvvTS3WLYC9uSqIPHFgwF+tir3w==} + '@napi-rs/canvas-android-arm64@0.1.53': + resolution: {integrity: sha512-2YhxfVsZguATlRWE0fZdTx35SE9+r5D7HV5GPNDataZOKmHf+zZ5//dspuuBSbOriQdoicaFrgXKCUqI0pK3WQ==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@napi-rs/canvas-darwin-arm64@0.1.52': - resolution: {integrity: sha512-4OgVRD7TW02q5Q7lWLLjT+pYJ9ZHkQUTBOuXbPQ5wB0Wnh3RIq/aMY6thoXDZDzdR5vV3a5TUtbZUJ0aqLq3NA==} + '@napi-rs/canvas-darwin-arm64@0.1.53': + resolution: {integrity: sha512-ls+CWLMusf4RAGo5BvIIzA6dNcc0elwVp6LKjHfQECHA8KKmvdB58YuE5BQcTlb2rzk0SEKtBC/Th3NI2oNdfg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@napi-rs/canvas-darwin-x64@0.1.52': - resolution: {integrity: sha512-3fgeGJ3j2X6Mtmn0QYf3iA+A6y1ePnsayakc2emEokzf03ErrPczONw3vjnTQo53JLPMzEnfPGAffdktU/ssPA==} + '@napi-rs/canvas-darwin-x64@0.1.53': + resolution: {integrity: sha512-ZAgcoCH5+5OKS2P8Lxx+jbkAPKkyLD2x6OvSrHg1U6ppdxmLA+CkJlRl8w45HCXwuyIiP7OeymECRtiNYTwznQ==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.52': - resolution: {integrity: sha512-aaDEEK5XwHUrPt0q4SR8l7Va0vtn50KmSs+itxP+o7RNk3Nuch8fINHOXyhMyhwNYgv1tfiJVyHsJhD0E6lXGA==} + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.53': + resolution: {integrity: sha512-p9km/3C/loDxu3AvA8/vtpIS1BGMd/Ehkl2Iu/v/Gw8N/KUIt3HUvTS7AKApyVE28bxTfq96wJQjtcT8jzDncw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@napi-rs/canvas-linux-arm64-gnu@0.1.52': - resolution: {integrity: sha512-tzuwM7Amt5mkrp4csQjYWkFzwFdiCm7RNdJ5usX8syzKSXmozqWzLHjzo/2ozdSQNUy6wyzRrxkG4Rh6g0OpOA==} + '@napi-rs/canvas-linux-arm64-gnu@0.1.53': + resolution: {integrity: sha512-QKK+sykEiYwjwd+ogyLcpcnH38DNZ8KViBlnfEpoGA2Wa+21/cWQKfMxnbgb/rbvm5tazJinZcihFvH577WQ5g==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/canvas-linux-arm64-musl@0.1.52': - resolution: {integrity: sha512-HQCtJlDT0dFp3uUZVzZOZ1VLMO7lbLRc548MjMxPpojit2ZdGopFzJ8jDSr4iszHrTO1SM1AxPaCM3pRvCAtjw==} + '@napi-rs/canvas-linux-arm64-musl@0.1.53': + resolution: {integrity: sha512-2N41U0X8RnrTKzpTtPv1ozlYkJtPsUdbfF3uP/KEd/BsULGd8Y8ghkGMS6CM+821au4ex0dPrWOOdT9wC1rSqQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/canvas-linux-x64-gnu@0.1.52': - resolution: {integrity: sha512-z5sBEw0PVWPH/MIQL8hOR8C3YYVlu8lqtRUcYajigMfXAhbMiNqDWTjuIWGMz3nIydDjZmn8KTxw/D4a0HFPqQ==} + '@napi-rs/canvas-linux-x64-gnu@0.1.53': + resolution: {integrity: sha512-7XjuTvDKCODtf/vMwF43VGDrjfgwYKgS91ggdcX3UrJaBYWyWu/+eqNvNj+zdXSe/0x+YOjf5jG4m8xIXdBMQA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/canvas-linux-x64-musl@0.1.52': - resolution: {integrity: sha512-G1+JdWFhHLyHhULJS51xTEhB7EL0ZiAUQwQaRi4/w75OOYDQ91O+o4miaxDHiV0hZuxBhHtZU6ftV2Zl3RMguw==} + '@napi-rs/canvas-linux-x64-musl@0.1.53': + resolution: {integrity: sha512-970WEvB8vmj+uxvgdBZ+AGFV7uq9GJhXrqG5PGQ5lWciHX0P0d/OhS2F7TITgFR0LsKDQZ7XQgzMxsYOfwZ0FQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/canvas-win32-x64-msvc@0.1.52': - resolution: {integrity: sha512-hMI626VsCC/wv29qHF78N7TSG+auatOp08DHln0Zdif5y1NJ14NU/rNUhzlTW8Zc6ssw+AMDJ3KKYYWYYg1aoA==} + '@napi-rs/canvas-win32-x64-msvc@0.1.53': + resolution: {integrity: sha512-rLFQCSJaWg/sv54Aap9nAhaodi4Vyb4un50EgW+PNkk8icMziU6KLRKirGBdQr9ZdxnshAPeQXD1g2ArStujKA==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@napi-rs/canvas@0.1.52': - resolution: {integrity: sha512-xeW9EghZLDPZuqWJ4l1+eG3ld0i9J7SpV2zlgi34MPt/FE9K2XWGCfnLr0gHGOBkcI3YOVhI13I0HqRAkMPdVw==} + '@napi-rs/canvas@0.1.53': + resolution: {integrity: sha512-XsEZi97+kKykmAiPpY+IpZoHxJY1srqFZp8jDt1/RySzC0kB0iZYt/VMIFqQKpLCARZjD7SOAz2AULtwYlesCA==} engines: {node: '>= 10'} '@ndelangen/get-tarball@3.0.7': resolution: {integrity: sha512-NqGfTZIZpRFef1GoVaShSSRwDC3vde3ThtTeqFdcYd6ipKqnfEVhjK2hUeHjCQUcptyZr2TONqcloFXM+5QBrQ==} - '@nestjs/common@10.3.8': - resolution: {integrity: sha512-P+vPEIvqx2e+fonsYVlFXKvoChyJ8Tq+lfpqdVFqblovHbFr3kZ/nYX0cPs+XuW6bnRT8tz0SSR9XBGU43kJhw==} + '@nestjs/common@10.3.10': + resolution: {integrity: sha512-H8k0jZtxk1IdtErGDmxFRy0PfcOAUg41Prrqpx76DQusGGJjsaovs1zjXVD1rZWaVYchfT1uczJ6L4Kio10VNg==} peerDependencies: class-transformer: '*' class-validator: '*' @@ -3194,8 +3392,8 @@ packages: class-validator: optional: true - '@nestjs/core@10.3.8': - resolution: {integrity: sha512-AxF4tpYLDNn5Wfb3C4bNaaHJ4pREH5FJrSisR2A5zkYpQFORFs0Tc36lOFPMwBTy8Iv2wUwWLUVc5ftBnxEv4w==} + '@nestjs/core@10.3.10': + resolution: {integrity: sha512-ZbQ4jovQyzHtCGCrzK5NdtW1SYO2fHSsgSY1+/9WdruYCUra+JDkWEXgZ4M3Hv480Dl3OXehAmY1wCOojeMyMQ==} peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/microservices': ^10.0.0 @@ -3211,14 +3409,14 @@ packages: '@nestjs/websockets': optional: true - '@nestjs/platform-express@10.3.8': - resolution: {integrity: sha512-sifLoxgEJvAgbim1UuW6wyScMfkS9SVQRH+lN33N/9ZvZSjO6NSDLOe+wxqsnZkia+QrjFC0qy0ITRAsggfqbg==} + '@nestjs/platform-express@10.3.10': + resolution: {integrity: sha512-wK2ow3CZI2KFqWeEpPmoR300OB6BcBLxARV1EiClJLCj4S1mZsoCmS0YWgpk3j1j6mo0SI8vNLi/cC2iZPEPQA==} peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/core': ^10.0.0 - '@nestjs/testing@10.3.8': - resolution: {integrity: sha512-hpX9das2TdFTKQ4/2ojhjI6YgXtCfXRKui3A4Qaj54VVzc5+mtK502Jj18Vzji98o9MVS6skmYu+S/UvW3U6Fw==} + '@nestjs/testing@10.3.10': + resolution: {integrity: sha512-i3HAtVQJijxNxJq1k39aelyJlyEIBRONys7IipH/4r8W0J+M1V+y5EKDOyi4j1SdNSb/vmNyWpZ2/ewZjl3kRA==} peerDependencies: '@nestjs/common': ^10.0.0 '@nestjs/core': ^10.0.0 @@ -3230,6 +3428,10 @@ packages: '@nestjs/platform-express': optional: true + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -3273,19 +3475,19 @@ packages: '@open-draft/until@2.1.0': resolution: {integrity: sha512-U69T3ItWHvLwGg5eJ0n3I62nWuE6ilHlmz7zM0npLBRvPRd7e6NYmg54vvRtP5mZG7kZqZCFVdsTWo7BPtBujg==} - '@opentelemetry/api-logs@0.51.1': - resolution: {integrity: sha512-E3skn949Pk1z2XtXu/lxf6QAZpawuTM/IUEXcAzpiUkTd73Hmvw26FiN3cJuTmkpM5hZzHwkomVdtrh/n/zzwA==} + '@opentelemetry/api-logs@0.52.1': + resolution: {integrity: sha512-qnSqB2DQ9TPP96dl8cDubDvrUyWc0/sK81xHTK8eSUspzDM3bsewX903qclQFvVhgStjRWdC5bLb3kQqMkfV5A==} engines: {node: '>=14'} - '@opentelemetry/api@1.8.0': - resolution: {integrity: sha512-I/s6F7yKUDdtMsoBWXJe8Qz40Tui5vsuKCWJEWVL+5q9sSWRzzx6v2KeNsOBEwd94j0eWkpWCH4yB6rZg9Mf0w==} + '@opentelemetry/api@1.9.0': + resolution: {integrity: sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==} engines: {node: '>=8.0.0'} - '@opentelemetry/context-async-hooks@1.24.1': - resolution: {integrity: sha512-R5r6DO4kgEOVBxFXhXjwospLQkv+sYxwCfjvoZBe7Zm6KKXAV9kDSJhi/D1BweowdZmO+sdbENLs374gER8hpQ==} + '@opentelemetry/context-async-hooks@1.25.1': + resolution: {integrity: sha512-UW/ge9zjvAEmRWVapOP0qyCvPulWU6cQxGxDbWEFfGOj1VBBZAuOqTo3X6yWmDTD3Xe15ysCZChHncr2xFMIfQ==} engines: {node: '>=14'} peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' + '@opentelemetry/api': '>=1.0.0 <1.10.0' '@opentelemetry/core@1.24.1': resolution: {integrity: sha512-wMSGfsdmibI88K9wB498zXY04yThPexo8jvwNNlm542HZB7XrrMRBbAyKJqG8qDRJwIBdBrPMi4V9ZPW/sqrcg==} @@ -3293,86 +3495,98 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.9.0' - '@opentelemetry/instrumentation-connect@0.36.0': - resolution: {integrity: sha512-k9++bmJZ9zDEs3u3DnKTn2l7QTiNFg3gPx7G9rW0TPnP+xZoBSBTrEcGYBaqflQlrFG23Q58+X1sM2ayWPv5Fg==} + '@opentelemetry/core@1.25.1': + resolution: {integrity: sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + + '@opentelemetry/instrumentation-connect@0.37.0': + resolution: {integrity: sha512-SeQktDIH5rNzjiEiazWiJAIXkmnLOnNV7wwHpahrqE0Ph+Z3heqMfxRtoMtbdJSIYLfcNZYO51AjxZ00IXufdw==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-express@0.39.0': - resolution: {integrity: sha512-AG8U7z7D0JcBu/7dDcwb47UMEzj9/FMiJV2iQZqrsZnxR3FjB9J9oIH2iszJYci2eUdp2WbdvtpD9RV/zmME5A==} + '@opentelemetry/instrumentation-express@0.40.1': + resolution: {integrity: sha512-+RKMvVe2zw3kIXRup9c1jFu3T4d0fs5aKy015TpiMyoCKX1UMu3Z0lfgYtuyiSTANvg5hZnDbWmQmqSPj9VTvg==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-fastify@0.36.1': - resolution: {integrity: sha512-3Nfm43PI0I+3EX+1YbSy6xbDu276R1Dh1tqAk68yd4yirnIh52Kd5B+nJ8CgHA7o3UKakpBjj6vSzi5vNCzJIA==} + '@opentelemetry/instrumentation-fastify@0.37.0': + resolution: {integrity: sha512-WRjwzNZgupSzbEYvo9s+QuHJRqZJjVdNxSEpGBwWK8RKLlHGwGVAu0gcc2gPamJWUJsGqPGvahAPWM18ZkWj6A==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-graphql@0.40.0': - resolution: {integrity: sha512-LVRdEHWACWOczv2imD+mhUrLMxsEjPPi32vIZJT57zygR5aUiA4em8X3aiGOCycgbMWkIu8xOSGSxdx3JmzN+w==} + '@opentelemetry/instrumentation-graphql@0.41.0': + resolution: {integrity: sha512-R/gXeljgIhaRDKquVkKYT5QHPnFouM8ooyePZEP0kqyaVAedtR1V7NfAUJbxfTG5fBQa5wdmLjvu63+tzRXZCA==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-hapi@0.38.0': - resolution: {integrity: sha512-ZcOqEuwuutTDYIjhDIStix22ECblG/i9pHje23QGs4Q4YS4RMaZ5hKCoQJxW88Z4K7T53rQkdISmoXFKDV8xMg==} + '@opentelemetry/instrumentation-hapi@0.39.0': + resolution: {integrity: sha512-ik2nA9Yj2s2ay+aNY+tJsKCsEx6Tsc2g/MK0iWBW5tibwrWKTy1pdVt5sB3kd5Gkimqj23UV5+FH2JFcQLeKug==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-http@0.51.1': - resolution: {integrity: sha512-6b3nZnFFEz/3xZ6w8bVxctPUWIPWiXuPQ725530JgxnN1cvYFd8CJ75PrHZNjynmzSSnqBkN3ef4R9N+RpMh8Q==} + '@opentelemetry/instrumentation-http@0.52.1': + resolution: {integrity: sha512-dG/aevWhaP+7OLv4BQQSEKMJv8GyeOp3Wxl31NHqE8xo9/fYMfEljiZphUHIfyg4gnZ9swMyWjfOQs5GUQe54Q==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-ioredis@0.40.0': - resolution: {integrity: sha512-Jv/fH7KhpWe4KBirsiqeUJIYrsdR2iu2l4nWhfOlRvaZ+zYIiLEzTQR6QhBbyRoAbU4OuYJzjWusOmmpGBnwng==} + '@opentelemetry/instrumentation-ioredis@0.41.0': + resolution: {integrity: sha512-rxiLloU8VyeJGm5j2fZS8ShVdB82n7VNP8wTwfUQqDwRfHCnkzGr+buKoxuhGD91gtwJ91RHkjHA1Eg6RqsUTg==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-koa@0.40.0': - resolution: {integrity: sha512-dJc3H/bKMcgUYcQpLF+1IbmUKus0e5Fnn/+ru/3voIRHwMADT3rFSUcGLWSczkg68BCgz0vFWGDTvPtcWIFr7A==} + '@opentelemetry/instrumentation-koa@0.41.0': + resolution: {integrity: sha512-mbPnDt7ELvpM2S0vixYUsde7122lgegLOJQxx8iJQbB8YHal/xnTh9v7IfArSVzIDo+E+080hxZyUZD4boOWkw==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mongodb@0.43.0': - resolution: {integrity: sha512-bMKej7Y76QVUD3l55Q9YqizXybHUzF3pujsBFjqbZrRn2WYqtsDtTUlbCK7fvXNPwFInqZ2KhnTqd0gwo8MzaQ==} + '@opentelemetry/instrumentation-mongodb@0.45.0': + resolution: {integrity: sha512-xnZP9+ayeB1JJyNE9cIiwhOJTzNEsRhXVdLgfzmrs48Chhhk026mQdM5CITfyXSCfN73FGAIB8d91+pflJEfWQ==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mongoose@0.38.1': - resolution: {integrity: sha512-zaeiasdnRjXe6VhYCBMdkmAVh1S5MmXC/0spet+yqoaViGnYst/DOxPvhwg3yT4Yag5crZNWsVXnA538UjP6Ow==} + '@opentelemetry/instrumentation-mongoose@0.39.0': + resolution: {integrity: sha512-J1r66A7zJklPPhMtrFOO7/Ud2p0Pv5u8+r23Cd1JUH6fYPmftNJVsLp2urAt6PHK4jVqpP/YegN8wzjJ2mZNPQ==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mysql2@0.38.1': - resolution: {integrity: sha512-qkpHMgWSDTYVB1vlZ9sspf7l2wdS5DDq/rbIepDwX5BA0N0068JTQqh0CgAh34tdFqSCnWXIhcyOXC2TtRb0sg==} + '@opentelemetry/instrumentation-mysql2@0.39.0': + resolution: {integrity: sha512-Iypuq2z6TCfriAXCIZjRq8GTFCKhQv5SpXbmI+e60rYdXw8NHtMH4NXcGF0eKTuoCsC59IYSTUvDQYDKReaszA==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-mysql@0.38.1': - resolution: {integrity: sha512-+iBAawUaTfX/HAlvySwozx0C2B6LBfNPXX1W8Z2On1Uva33AGkw2UjL9XgIg1Pj4eLZ9R4EoJ/aFz+Xj4E/7Fw==} + '@opentelemetry/instrumentation-mysql@0.39.0': + resolution: {integrity: sha512-8snHPh83rhrDf31v9Kq0Nf+ts8hdr7NguuszRqZomZBHgE0+UyXZSkXHAAFZoBPPRMGyM68uaFE5hVtFl+wOcA==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-nestjs-core@0.37.1': - resolution: {integrity: sha512-ebYQjHZEmGHWEALwwDGhSQVLBaurFnuLIkZD5igPXrt7ohfF4lc5/4al1LO+vKc0NHk8SJWStuRueT86ISA8Vg==} + '@opentelemetry/instrumentation-nestjs-core@0.38.0': + resolution: {integrity: sha512-M381Df1dM8aqihZz2yK+ugvMFK5vlHG/835dc67Sx2hH4pQEQYDA2PpFPTgc9AYYOydQaj7ClFQunESimjXDgg==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation-pg@0.41.0': - resolution: {integrity: sha512-BSlhpivzBD77meQNZY9fS4aKgydA8AJBzv2dqvxXFy/Hq64b7HURgw/ztbmwFeYwdF5raZZUifiiNSMLpOJoSA==} + '@opentelemetry/instrumentation-pg@0.42.0': + resolution: {integrity: sha512-sjgcM8CswYy8zxHgXv4RAZ09DlYhQ+9TdlourUs63Df/ek5RrB1ZbjznqW7PB6c3TyJJmX6AVtPTjAsROovEjA==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': ^1.3.0 + + '@opentelemetry/instrumentation-redis-4@0.40.0': + resolution: {integrity: sha512-0ieQYJb6yl35kXA75LQUPhHtGjtQU9L85KlWa7d4ohBbk/iQKZ3X3CFl5jC5vNMq/GGPB3+w3IxNvALlHtrp7A==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 @@ -3383,8 +3597,8 @@ packages: peerDependencies: '@opentelemetry/api': ^1.3.0 - '@opentelemetry/instrumentation@0.51.1': - resolution: {integrity: sha512-JIrvhpgqY6437QIqToyozrUG1h5UhwHkaGK/WAX+fkrpyPtc+RO5FkRtUd9BH0MibabHHvqsnBGKfKVijbmp8w==} + '@opentelemetry/instrumentation@0.52.1': + resolution: {integrity: sha512-uXJbYU/5/MBHjMp1FqrILLRuiJCs3Ofk0MeRDk8g1S1gD47U8X3JnSwcMO1rtRo1x1a7zKaQHaoYu49p/4eSKw==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': ^1.3.0 @@ -3399,22 +3613,32 @@ packages: peerDependencies: '@opentelemetry/api': '>=1.0.0 <1.9.0' + '@opentelemetry/resources@1.25.1': + resolution: {integrity: sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ==} + engines: {node: '>=14'} + peerDependencies: + '@opentelemetry/api': '>=1.0.0 <1.10.0' + '@opentelemetry/sdk-metrics@1.24.1': resolution: {integrity: sha512-FrAqCbbGao9iKI+Mgh+OsC9+U2YMoXnlDHe06yH7dvavCKzE3S892dGtX54+WhSFVxHR/TMRVJiK/CV93GR0TQ==} engines: {node: '>=14'} peerDependencies: '@opentelemetry/api': '>=1.3.0 <1.9.0' - '@opentelemetry/sdk-trace-base@1.24.1': - resolution: {integrity: sha512-zz+N423IcySgjihl2NfjBf0qw1RWe11XIAWVrTNOSSI6dtSPJiVom2zipFB2AEEtJWpv0Iz6DY6+TjnyTV5pWg==} + '@opentelemetry/sdk-trace-base@1.25.1': + resolution: {integrity: sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw==} engines: {node: '>=14'} peerDependencies: - '@opentelemetry/api': '>=1.0.0 <1.9.0' + '@opentelemetry/api': '>=1.0.0 <1.10.0' '@opentelemetry/semantic-conventions@1.24.1': resolution: {integrity: sha512-VkliWlS4/+GHLLW7J/rVBA00uXus1SWvwFvcUDxDwmFxYfg/2VI6ekwdXS28cjI8Qz2ky2BzG8OUHo+WeYIWqw==} engines: {node: '>=14'} + '@opentelemetry/semantic-conventions@1.25.1': + resolution: {integrity: sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ==} + engines: {node: '>=14'} + '@opentelemetry/sql-common@0.40.1': resolution: {integrity: sha512-nSDlnHSqzC3pXn/wZEZVLuAuJ1MYMXPBwtv2qAbCa3847SaHItdE7SzUq/Jtb0KZmh1zfAbNi3AAMjztTT4Ugg==} engines: {node: '>=14'} @@ -3444,23 +3668,167 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@prisma/instrumentation@5.14.0': - resolution: {integrity: sha512-DeybWvIZzu/mUsOYP9MVd6AyBj+MP7xIMrcuIn25MX8FiQX39QBnET5KhszTAip/ToctUuDwSJ46QkIoyo3RFA==} + '@prisma/instrumentation@5.16.0': + resolution: {integrity: sha512-MVzNRW2ikWvVNnMIEgQMcwWxpFD+XF2U2h0Qz7MjutRqJxrhWexWV2aSi2OXRaU8UL5wzWw7pnjdKUzYhWauLg==} - '@radix-ui/react-compose-refs@1.0.1': - resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} + '@radix-ui/primitive@1.1.0': + resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} + + '@radix-ui/react-compose-refs@1.1.0': + resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==} peerDependencies: '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true - '@radix-ui/react-slot@1.0.2': - resolution: {integrity: sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg==} + '@radix-ui/react-context@1.1.0': + resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==} peerDependencies: '@types/react': '*' - react: ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-dialog@1.1.1': + resolution: {integrity: sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-dismissable-layer@1.1.0': + resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-focus-guards@1.1.0': + resolution: {integrity: sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-focus-scope@1.1.0': + resolution: {integrity: sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-id@1.1.0': + resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-portal@1.1.1': + resolution: {integrity: sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-presence@1.1.0': + resolution: {integrity: sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-primitive@2.0.0': + resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@radix-ui/react-slot@1.1.0': + resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-callback-ref@1.1.0': + resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-controllable-state@1.1.0': + resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-escape-keydown@1.1.0': + resolution: {integrity: sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + '@radix-ui/react-use-layout-effect@1.1.0': + resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc peerDependenciesMeta: '@types/react': optional: true @@ -3489,8 +3857,8 @@ packages: rollup: optional: true - '@rollup/plugin-replace@5.0.5': - resolution: {integrity: sha512-rYO4fOi8lMaTg/z5Jb+hKnrHHVn8j2lwkqwyS4kTRhKyWOLf2wST2sWXr4WzWiTcoHTp2sTjqUbqIj2E39slKQ==} + '@rollup/plugin-replace@5.0.7': + resolution: {integrity: sha512-PqxSfuorkHz/SPpyngLyg5GCEkOcee9M1bkxiVDr41Pd61mqP1PLOoDPbpl44SB2mQGKwV/In74gqQmGITOhEQ==} engines: {node: '>=14.0.0'} peerDependencies: rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 @@ -3507,88 +3875,88 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} + '@rollup/rollup-android-arm-eabi@4.18.0': + resolution: {integrity: sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} + '@rollup/rollup-android-arm64@4.18.0': + resolution: {integrity: sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} + '@rollup/rollup-darwin-arm64@4.18.0': + resolution: {integrity: sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} + '@rollup/rollup-darwin-x64@4.18.0': + resolution: {integrity: sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': + resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} + '@rollup/rollup-linux-arm-musleabihf@4.18.0': + resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} + '@rollup/rollup-linux-arm64-gnu@4.18.0': + resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} + '@rollup/rollup-linux-arm64-musl@4.18.0': + resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': + resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} + '@rollup/rollup-linux-riscv64-gnu@4.18.0': + resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} + '@rollup/rollup-linux-s390x-gnu@4.18.0': + resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.17.2': - resolution: {integrity: sha512-Hy7pLwByUOuyaFC6mAr7m+oMC+V7qyifzs/nW2OJfC8H4hbCzOX07Ov0VFk/zP3kBsELWNFi7rJtgbKYsav9QQ==} + '@rollup/rollup-linux-x64-gnu@4.18.0': + resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} + '@rollup/rollup-linux-x64-musl@4.18.0': + resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} + '@rollup/rollup-win32-arm64-msvc@4.18.0': + resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} + '@rollup/rollup-win32-ia32-msvc@4.18.0': + resolution: {integrity: sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} + '@rollup/rollup-win32-x64-msvc@4.18.0': + resolution: {integrity: sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==} cpu: [x64] os: [win32] - '@rushstack/node-core-library@4.1.0': - resolution: {integrity: sha512-qz4JFBZJCf1YN5cAXa1dP6Mki/HrsQxc/oYGAGx29dF2cwF2YMxHoly0FBhMw3IEnxo5fMj0boVfoHVBkpkx/w==} + '@rushstack/node-core-library@5.4.1': + resolution: {integrity: sha512-WNnwdS8r9NZ/2K3u29tNoSRldscFa7SxU0RT+82B6Dy2I4Hl2MeCSKm4EXLXPKeNzLGvJ1cqbUhTLviSF8E6iA==} peerDependencies: '@types/node': '*' peerDependenciesMeta: @@ -3598,50 +3966,53 @@ packages: '@rushstack/rig-package@0.5.2': resolution: {integrity: sha512-mUDecIJeH3yYGZs2a48k+pbhM6JYwWlgjs2Ca5f2n1G2/kgdgP9D/07oglEGf6mRyXEnazhEENeYTSNDRCwdqA==} - '@rushstack/terminal@0.10.1': - resolution: {integrity: sha512-C6Vi/m/84IYJTkfzmXr1+W8Wi3MmBjVF/q3za91Gb3VYjKbpALHVxY6FgH625AnDe5Z0Kh4MHKWA3Z7bqgAezA==} + '@rushstack/terminal@0.13.0': + resolution: {integrity: sha512-Ou44Q2s81BqJu3dpYedAX54am9vn245F0HzqVrfJCMQk5pGgoKKOBOjkbfZC9QKcGNaECh6pwH2s5noJt7X6ew==} peerDependencies: '@types/node': '*' peerDependenciesMeta: '@types/node': optional: true - '@rushstack/ts-command-line@4.19.2': - resolution: {integrity: sha512-cqmXXmBEBlzo9WtyUrHtF9e6kl0LvBY7aTSVX4jfnBfXWZQWnPq9JTFPlQZ+L/ZwjZ4HrNwQsOVvhe9oOucZkw==} + '@rushstack/ts-command-line@4.22.0': + resolution: {integrity: sha512-Qj28t6MO3HRgAZ72FDeFsrpdE6wBWxF3VENgvrXh7JF2qIT+CrXiOJIesW80VFZB9QwObSpkB1ilx794fGQg6g==} - '@sentry/core@8.5.0': - resolution: {integrity: sha512-SO3ddBzGdha+Oflp+IKwBxj+7ds1q69OAT3VsypTd+WUFQdI9DIhR92Bjf+QQZCIzUNOi79VWOh3aOi3f6hMnw==} + '@sec-ant/readable-stream@0.4.1': + resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} + + '@sentry/core@8.13.0': + resolution: {integrity: sha512-N9Qg4ZGxZWp8eb2eUUHVVKgjBLtFIjS805nG92s6yJmkvOpKm6mLtcUaT/iDf3Hta6nG+xRkhbE3r+Z4cbXG8w==} engines: {node: '>=14.18'} - '@sentry/node@8.5.0': - resolution: {integrity: sha512-t9cHAx/wLJYtdVf2XlzKlRJGvwdAp1wjzG0tC4E1Znx74OuUS1cFNo5WrGuOi0/YcWSxiJaxBvtUcsWK86fIgw==} + '@sentry/node@8.13.0': + resolution: {integrity: sha512-OeZ7K90RhyxfwfreerIi4cszzHrPRRH36STJno2+p3sIGbG5VScOccqXzYEOAqHpByxnti4KQN34BLAT2BFOEA==} engines: {node: '>=14.18'} - '@sentry/opentelemetry@8.5.0': - resolution: {integrity: sha512-AbxFUNjuTKQ9ugZrssmGtPxWkBr4USNoP7GjaaGCNwNzvIVYCa+i8dv7BROJiW2lsxNAremULEbh+nbVmhGxDA==} + '@sentry/opentelemetry@8.13.0': + resolution: {integrity: sha512-NYn/HNE/SxFXe8pfnxJknhrrRzYRMHNssCoi5M1CeR5G7F2BGxxVmaGsd8j0WyTCpUS4i97G4vhYtDGxHvWN6w==} engines: {node: '>=14.18'} peerDependencies: - '@opentelemetry/api': ^1.8.0 - '@opentelemetry/core': ^1.24.1 - '@opentelemetry/instrumentation': ^0.51.1 - '@opentelemetry/sdk-trace-base': ^1.23.0 - '@opentelemetry/semantic-conventions': ^1.23.0 + '@opentelemetry/api': ^1.9.0 + '@opentelemetry/core': ^1.25.1 + '@opentelemetry/instrumentation': ^0.52.1 + '@opentelemetry/sdk-trace-base': ^1.25.1 + '@opentelemetry/semantic-conventions': ^1.25.1 - '@sentry/profiling-node@8.5.0': - resolution: {integrity: sha512-nEXJqVNfZWYi4PakQXBZCJeH59UlnBv+zaYftDNUUXttCmzRXpL1ujNm5mJrJHlWjV7tgIFw02HW3nh2yyKOkw==} + '@sentry/profiling-node@8.13.0': + resolution: {integrity: sha512-6qirN71xlMahcm4m25XZLnjQdvs0EaFym/9MdLqcsAa3gAHZtw6h+IDapUzBWRXVOrU1OR5oQdh2tlFthsDtew==} engines: {node: '>=14.18'} hasBin: true - '@sentry/types@8.5.0': - resolution: {integrity: sha512-eDgkSmKI4+XL0QZm4H3j/n1RgnrbnjXZmjj+LsfccRZQwbPu9bWlc8q7Y7Ty1gOsoUpX+TecNLp2a8CRID4KHA==} + '@sentry/types@8.13.0': + resolution: {integrity: sha512-r63s/H5gvQnQM9tTGBXz2xErUbxZALh4e2Lg/1aHj4zIvGLBjA2z5qWsh6TEZYbpmgAyGShLDr6+rWeUVf9yBQ==} engines: {node: '>=14.18'} - '@sentry/utils@8.5.0': - resolution: {integrity: sha512-fdrCzo8SAYiw9JBhkJPqYqJkDXZ/wICzN7+zcXIuzKNhE1hdoFjeKcPnpUI3bKZCG6e3hT1PTYQXhVw7GIZV9w==} + '@sentry/utils@8.13.0': + resolution: {integrity: sha512-PxV0v9VbGWH9zP37P5w2msLUFDr287nYjoY2XVF+RSolyiTs1CQNI5ZMUO3o4MsSac/dpXxjyrZXQd72t/jRYA==} engines: {node: '>=14.18'} - '@shikijs/core@1.4.0': - resolution: {integrity: sha512-CxpKLntAi64h3j+TwWqVIQObPTED0FyXLHTTh3MKXtqiQNn2JGcMQQ362LftDbc9kYbDtrksNMNoVmVXzKFYUQ==} + '@shikijs/core@1.10.0': + resolution: {integrity: sha512-BZcr6FCmPfP6TXaekvujZcnkFmJHZ/Yglu97r/9VjzVndQA56/F4WjUKtJRQUnK59Wi7p/UTAOekMfCJv7jnYg==} '@sideway/address@4.1.4': resolution: {integrity: sha512-7vwq+rOHVWjyXxVlR76Agnvhy8I9rpzjosTESvmhNeXOXdZZB15Fl+TI9x1SiHZH5Jv2wTGduSxFDIaq0m3DUw==} @@ -3670,10 +4041,18 @@ packages: resolution: {integrity: sha512-CX6t4SYQ37lzxicAqsBtxA3OseeoVrh9cSJ5PFYam0GksYlupRfy1A+Q4aYD3zvcfECLc0zO2u+ZnR2UYKvCrw==} engines: {node: '>=14.16'} - '@sindresorhus/is@6.1.0': - resolution: {integrity: sha512-BuvU07zq3tQ/2SIgBsEuxKYDyDjC0n7Zir52bpHy2xnBbW81+po43aLFPLbeV3HRAheFbGud1qgcqSYfhtHMAg==} + '@sindresorhus/is@6.3.1': + resolution: {integrity: sha512-FX4MfcifwJyFOI2lPoX7PQxCqx8BG1HCho7WdiXwpEQx1Ycij0JxkfYtGK7yqNScrZGSlt6RE6sw8QYoH7eKnQ==} engines: {node: '>=16'} + '@sindresorhus/merge-streams@2.3.0': + resolution: {integrity: sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==} + engines: {node: '>=18'} + + '@sindresorhus/merge-streams@4.0.0': + resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} + engines: {node: '>=18'} + '@sinonjs/commons@2.0.0': resolution: {integrity: sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==} @@ -3692,275 +4071,299 @@ packages: '@sinonjs/text-encoding@0.7.2': resolution: {integrity: sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==} - '@smithy/abort-controller@2.0.14': - resolution: {integrity: sha512-zXtteuYLWbSXnzI3O6xq3FYvigYZFW8mdytGibfarLL2lxHto9L3ILtGVnVGmFZa7SDh62l39EnU5hesLN87Fw==} - engines: {node: '>=14.0.0'} - '@smithy/abort-controller@2.2.0': resolution: {integrity: sha512-wRlta7GuLWpTqtFfGo+nZyOO1vEvewdNR1R4rTxpC8XU6vG/NDyrFBhwLZsqg1NUoR1noVaXJPC/7ZK47QCySw==} engines: {node: '>=14.0.0'} - '@smithy/chunked-blob-reader-native@2.0.0': - resolution: {integrity: sha512-HM8V2Rp1y8+1343tkZUKZllFhEQPNmpNdgFAncbTsxkZ18/gqjk23XXv3qGyXWp412f3o43ZZ1UZHVcHrpRnCQ==} + '@smithy/abort-controller@3.1.1': + resolution: {integrity: sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ==} + engines: {node: '>=16.0.0'} - '@smithy/chunked-blob-reader@2.0.0': - resolution: {integrity: sha512-k+J4GHJsMSAIQPChGBrjEmGS+WbPonCXesoqP9fynIqjn7rdOThdH8FAeCmokP9mxTYKQAKoHCLPzNlm6gh7Wg==} + '@smithy/chunked-blob-reader-native@3.0.0': + resolution: {integrity: sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg==} - '@smithy/config-resolver@2.0.9': - resolution: {integrity: sha512-QBkGPLUqyPmis9Erz8v4q5lo/ErnF7+GD5WZHa6JZiXopUPfaaM+B21n8gzS5xCkIXZmnwzNQhObP9xQPu8oqQ==} - engines: {node: '>=14.0.0'} + '@smithy/chunked-blob-reader@3.0.0': + resolution: {integrity: sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA==} - '@smithy/credential-provider-imds@2.0.11': - resolution: {integrity: sha512-uJJs8dnM5iXkn8a2GaKvlKMhcOJ+oJPYqY9gY3CM/EieCVObIDjxUtR/g8lU/k/A+OauA78GzScAfulmFjPOYA==} - engines: {node: '>=14.0.0'} + '@smithy/config-resolver@3.0.4': + resolution: {integrity: sha512-VwiOk7TwXoE7NlNguV/aPq1hFH72tqkHCw8eWXbr2xHspRyyv9DLpLXhq+Ieje+NwoqXrY0xyQjPXdOE6cGcHA==} + engines: {node: '>=16.0.0'} - '@smithy/eventstream-codec@2.0.8': - resolution: {integrity: sha512-onO4to8ujCKn4m5XagReT9Nc6FlNG5vveuvjp1H7AtaG7njdet1LOl6/jmUOkskF2C/w+9jNw3r9Ak+ghOvN0A==} + '@smithy/core@2.2.4': + resolution: {integrity: sha512-qdY3LpMOUyLM/gfjjMQZui+UTNS7kBRDWlvyIhVOql5dn2J3isk9qUTBtQ1CbDH8MTugHis1zu3h4rH+Qmmh4g==} + engines: {node: '>=16.0.0'} - '@smithy/eventstream-serde-browser@2.0.8': - resolution: {integrity: sha512-/RGlkKUnC0sd+xKBKH/2APSBRmVMZTeLOKZMhrZmrO+ONoU+DwyMr/RLJ6WnmBKN+2ebjffM4pcIJTKLNNDD8g==} - engines: {node: '>=14.0.0'} + '@smithy/credential-provider-imds@3.1.3': + resolution: {integrity: sha512-U1Yrv6hx/mRK6k8AncuI6jLUx9rn0VVSd9NPEX6pyYFBfkSkChOc/n4zUb8alHUVg83TbI4OdZVo1X0Zfj3ijA==} + engines: {node: '>=16.0.0'} - '@smithy/eventstream-serde-config-resolver@2.0.8': - resolution: {integrity: sha512-EyAEj258eMUv9zcMvBbqrInh2eHRYuiwQAjXDMxZFCyP+JePzQB6O++3wFwjQeRKMFFgZipNgnEXfReII4+NAw==} - engines: {node: '>=14.0.0'} + '@smithy/eventstream-codec@3.1.2': + resolution: {integrity: sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw==} - '@smithy/eventstream-serde-node@2.0.8': - resolution: {integrity: sha512-FMBatSUSKwh6aguKVJokXfJaV8nqsuCkCZHb9MP9zah0ZF+ohbTLeeed7DQGeTVBueVIVWEzIsShPxtxBv7MMQ==} - engines: {node: '>=14.0.0'} + '@smithy/eventstream-serde-browser@3.0.4': + resolution: {integrity: sha512-Eo4anLZX6ltGJTZ5yJMc80gZPYYwBn44g0h7oFq6et+TYr5dUsTpIcDbz2evsOKIZhZ7zBoFWHtBXQ4QQeb5xA==} + engines: {node: '>=16.0.0'} - '@smithy/eventstream-serde-universal@2.0.8': - resolution: {integrity: sha512-6InMXH8BUKoEDa6CAuxR4Gn8Gf2vBfVtjA9A6zDKZClYHT+ANUJS+2EtOBc5wECJJGk4KLn5ajQyrt9MBv5lcw==} - engines: {node: '>=14.0.0'} + '@smithy/eventstream-serde-config-resolver@3.0.3': + resolution: {integrity: sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ==} + engines: {node: '>=16.0.0'} - '@smithy/fetch-http-handler@2.1.4': - resolution: {integrity: sha512-SL24M9W5ERByoXaVicRx+bj9GJVujDnPn+QO7GY7adhY0mPGa6DSF58pVKsgIh4r5Tx/k3SWCPlH4BxxSxA/fQ==} + '@smithy/eventstream-serde-node@3.0.4': + resolution: {integrity: sha512-mjlG0OzGAYuUpdUpflfb9zyLrBGgmQmrobNT8b42ZTsGv/J03+t24uhhtVEKG/b2jFtPIHF74Bq+VUtbzEKOKg==} + engines: {node: '>=16.0.0'} - '@smithy/hash-blob-browser@2.0.8': - resolution: {integrity: sha512-IgvRlBMfg/qLg321a59T1yTdEEbaizLrEVsU3DHj65DAO4lFRMF5f+l7vuV+je6m1G9wSD5GQXLturX8qlGb4g==} + '@smithy/eventstream-serde-universal@3.0.4': + resolution: {integrity: sha512-Od9dv8zh3PgOD7Vj4T3HSuox16n0VG8jJIM2gvKASL6aCtcS8CfHZDWe1Ik3ZXW6xBouU+45Q5wgoliWDZiJ0A==} + engines: {node: '>=16.0.0'} - '@smithy/hash-node@2.0.8': - resolution: {integrity: sha512-yZL/nmxZzjZV5/QX5JWSgXlt0HxuMTwFO89CS++jOMMPiCMZngf6VYmtNdccs8IIIAMmfQeTzwu07XgUE/Zd3Q==} - engines: {node: '>=14.0.0'} + '@smithy/fetch-http-handler@3.2.0': + resolution: {integrity: sha512-vFvDxMrc6sO5Atec8PaISckMcAwsCrRhYxwUylg97bRT2KZoumOF7qk5+6EVUtuM1IG9AJV5aqXnHln9ZdXHpg==} - '@smithy/hash-stream-node@2.0.8': - resolution: {integrity: sha512-82zC6I9ZJycbEZH8TVyXyBx9c2ZIPQDgBvM0x5AFPUl/i1AxwKKX+lwYRnzgkF//cYhIIoJaCfJ9mjSMPRGvCQ==} - engines: {node: '>=14.0.0'} + '@smithy/hash-blob-browser@3.1.2': + resolution: {integrity: sha512-hAbfqN2UbISltakCC2TP0kx4LqXBttEv2MqSPE98gVuDFMf05lU+TpC41QtqGP3Ff5A3GwZMPfKnEy0VmEUpmg==} - '@smithy/invalid-dependency@2.0.8': - resolution: {integrity: sha512-88VOS7W3KzUz/bNRc+Sl/F/CDIasFspEE4G39YZRHIh9YmsXF7GUyVaAKURfMNulTie62ayk6BHC9O0nOBAVgQ==} + '@smithy/hash-node@3.0.3': + resolution: {integrity: sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw==} + engines: {node: '>=16.0.0'} + + '@smithy/hash-stream-node@3.1.2': + resolution: {integrity: sha512-PBgDMeEdDzi6JxKwbfBtwQG9eT9cVwsf0dZzLXoJF4sHKHs5HEo/3lJWpn6jibfJwT34I1EBXpBnZE8AxAft6g==} + engines: {node: '>=16.0.0'} + + '@smithy/invalid-dependency@3.0.3': + resolution: {integrity: sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw==} '@smithy/is-array-buffer@2.0.0': resolution: {integrity: sha512-z3PjFjMyZNI98JFRJi/U0nGoLWMSJlDjAW4QUX2WNZLas5C0CmVV6LJ01JI0k90l7FvpmixjWxPFmENSClQ7ug==} engines: {node: '>=14.0.0'} - '@smithy/md5-js@2.0.8': - resolution: {integrity: sha512-1VVECXEiuJvjXv+mudiaUFKYwgDLOWz5MTTy8RzbrPiU3GiOb3/o5/urdkYpqmgoMfxdvxxOw/Adjv2dV2q2Yg==} + '@smithy/is-array-buffer@3.0.0': + resolution: {integrity: sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==} + engines: {node: '>=16.0.0'} - '@smithy/middleware-content-length@2.0.10': - resolution: {integrity: sha512-EGSbysyA4jH0p3xI6G0jdXoj9Iz9GUnAta6aEaHtXm3wVWtenRf80y2TeVvNkVSr5jwKOdSCjKIRI2l1A/oZLA==} - engines: {node: '>=14.0.0'} + '@smithy/md5-js@3.0.3': + resolution: {integrity: sha512-O/SAkGVwpWmelpj/8yDtsaVe6sINHLB1q8YE/+ZQbDxIw3SRLbTZuRaI10K12sVoENdnHqzPp5i3/H+BcZ3m3Q==} - '@smithy/middleware-endpoint@2.0.8': - resolution: {integrity: sha512-yOpogfG2d2V0cbJdAJ6GLAWkNOc9pVsL5hZUfXcxJu408N3CUCsXzIAFF6+70ZKSE+lCfG3GFErcSXv/UfUbjw==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-content-length@3.0.3': + resolution: {integrity: sha512-Dbz2bzexReYIQDWMr+gZhpwBetNXzbhnEMhYKA6urqmojO14CsXjnsoPYO8UL/xxcawn8ZsuVU61ElkLSltIUQ==} + engines: {node: '>=16.0.0'} - '@smithy/middleware-retry@2.0.11': - resolution: {integrity: sha512-pknfokumZ+wvBERSuKAI2vVr+aK3ZgPiWRg6+0ZG4kKJogBRpPmDGWw+Jht0izS9ZaEbIobNzueIb4wD33JJVg==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-endpoint@3.0.4': + resolution: {integrity: sha512-whUJMEPwl3ANIbXjBXZVdJNgfV2ZU8ayln7xUM47rXL2txuenI7jQ/VFFwCzy5lCmXScjp6zYtptW5Evud8e9g==} + engines: {node: '>=16.0.0'} - '@smithy/middleware-serde@2.0.8': - resolution: {integrity: sha512-Is0sm+LiNlgsc0QpstDzifugzL9ehno1wXp109GgBgpnKTK3j+KphiparBDI4hWTtH9/7OUsxuspNqai2yyhcg==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-retry@3.0.7': + resolution: {integrity: sha512-f5q7Y09G+2h5ivkSx5CHvlAT4qRR3jBFEsfXyQ9nFNiWQlr8c48blnu5cmbTQ+p1xmIO14UXzKoF8d7Tm0Gsjw==} + engines: {node: '>=16.0.0'} - '@smithy/middleware-stack@2.0.1': - resolution: {integrity: sha512-UexsfY6/oQZRjTQL56s9AKtMcR60tBNibSgNYX1I2WXaUaXg97W9JCkFyth85TzBWKDBTyhLfenrukS/kyu54A==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-serde@3.0.3': + resolution: {integrity: sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA==} + engines: {node: '>=16.0.0'} - '@smithy/node-config-provider@2.0.11': - resolution: {integrity: sha512-CaR1dciSSGKttjhcefpytYjsfI/Yd5mqL8am4wfmyFCDxSiPsvnEWHl8UjM/RbcAjX0klt+CeIKPSHEc0wGvJA==} - engines: {node: '>=14.0.0'} + '@smithy/middleware-stack@3.0.3': + resolution: {integrity: sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA==} + engines: {node: '>=16.0.0'} + + '@smithy/node-config-provider@3.1.3': + resolution: {integrity: sha512-rxdpAZczzholz6CYZxtqDu/aKTxATD5DAUDVj7HoEulq+pDSQVWzbg0btZDlxeFfa6bb2b5tUvgdX5+k8jUqcg==} + engines: {node: '>=16.0.0'} '@smithy/node-http-handler@2.5.0': resolution: {integrity: sha512-mVGyPBzkkGQsPoxQUbxlEfRjrj6FPyA3u3u2VXGr9hT8wilsoQdZdvKpMBFMB8Crfhv5dNkKHIW0Yyuc7eABqA==} engines: {node: '>=14.0.0'} - '@smithy/property-provider@2.0.9': - resolution: {integrity: sha512-25pPZ8f8DeRwYI5wbPRZaoMoR+3vrw8DwbA0TjP+GsdiB2KxScndr4HQehiJ5+WJ0giOTWhLz0bd+7Djv1qpUQ==} - engines: {node: '>=14.0.0'} + '@smithy/node-http-handler@3.1.1': + resolution: {integrity: sha512-L71NLyPeP450r2J/mfu1jMc//Z1YnqJt2eSNw7uhiItaONnBLDA68J5jgxq8+MBDsYnFwNAIc7dBG1ImiWBiwg==} + engines: {node: '>=16.0.0'} - '@smithy/protocol-http@3.0.10': - resolution: {integrity: sha512-6+tjNk7rXW7YTeGo9qwxXj/2BFpJTe37kTj3EnZCoX/nH+NP/WLA7O83fz8XhkGqsaAhLUPo/bB12vvd47nsmg==} - engines: {node: '>=14.0.0'} + '@smithy/property-provider@3.1.3': + resolution: {integrity: sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g==} + engines: {node: '>=16.0.0'} '@smithy/protocol-http@3.3.0': resolution: {integrity: sha512-Xy5XK1AFWW2nlY/biWZXu6/krgbaf2dg0q492D8M5qthsnU2H+UgFeZLbM76FnH7s6RO/xhQRkj+T6KBO3JzgQ==} engines: {node: '>=14.0.0'} - '@smithy/querystring-builder@2.0.14': - resolution: {integrity: sha512-lQ4pm9vTv9nIhl5jt6uVMPludr6syE2FyJmHsIJJuOD7QPIJnrf9HhUGf1iHh9KJ4CUv21tpOU3X6s0rB6uJ0g==} - engines: {node: '>=14.0.0'} + '@smithy/protocol-http@4.0.3': + resolution: {integrity: sha512-x5jmrCWwQlx+Zv4jAtc33ijJ+vqqYN+c/ZkrnpvEe/uDas7AT7A/4Rc2CdfxgWv4WFGmEqODIrrUToPN6DDkGw==} + engines: {node: '>=16.0.0'} '@smithy/querystring-builder@2.2.0': resolution: {integrity: sha512-L1kSeviUWL+emq3CUVSgdogoM/D9QMFaqxL/dd0X7PCNWmPXqt+ExtrBjqT0V7HLN03Vs9SuiLrG3zy3JGnE5A==} engines: {node: '>=14.0.0'} - '@smithy/querystring-parser@2.0.8': - resolution: {integrity: sha512-ArbanNuR7O/MmTd90ZqhDqGOPPDYmxx3huHxD+R3cuCnazcK/1tGQA+SnnR5307T7ZRb5WTpB6qBggERuibVSA==} - engines: {node: '>=14.0.0'} + '@smithy/querystring-builder@3.0.3': + resolution: {integrity: sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw==} + engines: {node: '>=16.0.0'} - '@smithy/service-error-classification@2.0.1': - resolution: {integrity: sha512-QHa9+t+v4s0cMuDCcbjIJN67mNZ42/+fc3jKe8P6ZMPXZl5ksKk6a8vhZ/m494GZng5eFTc3OePv+NF9cG83yg==} - engines: {node: '>=14.0.0'} + '@smithy/querystring-parser@3.0.3': + resolution: {integrity: sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ==} + engines: {node: '>=16.0.0'} - '@smithy/shared-ini-file-loader@2.0.10': - resolution: {integrity: sha512-jWASteSezRKohJ7GdA7pHDvmr7Q7tw3b5mu3xLHIkZy/ICftJ+O7aqNaF8wklhI7UNFoQ7flFRM3Rd0KA+1BbQ==} - engines: {node: '>=14.0.0'} + '@smithy/service-error-classification@3.0.3': + resolution: {integrity: sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ==} + engines: {node: '>=16.0.0'} - '@smithy/signature-v4@2.0.5': - resolution: {integrity: sha512-ABIzXmUDXK4n2c9cXjQLELgH2RdtABpYKT+U131e2I6RbCypFZmxIHmIBufJzU2kdMCQ3+thBGDWorAITFW04A==} - engines: {node: '>=14.0.0'} + '@smithy/shared-ini-file-loader@3.1.3': + resolution: {integrity: sha512-Z8Y3+08vgoDgl4HENqNnnzSISAaGrF2RoKupoC47u2wiMp+Z8P/8mDh1CL8+8ujfi2U5naNvopSBmP/BUj8b5w==} + engines: {node: '>=16.0.0'} - '@smithy/smithy-client@2.1.5': - resolution: {integrity: sha512-7S865uKzsxApM8W8Q6zkij7tcUFgaG8PuADMFdMt1yL/ku3d0+s6Zwrg3N7iXCPM08Gu/mf0BIfTXIu/9i450Q==} - engines: {node: '>=14.0.0'} + '@smithy/signature-v4@3.1.2': + resolution: {integrity: sha512-3BcPylEsYtD0esM4Hoyml/+s7WP2LFhcM3J2AGdcL2vx9O60TtfpDOL72gjb4lU8NeRPeKAwR77YNyyGvMbuEA==} + engines: {node: '>=16.0.0'} + + '@smithy/smithy-client@3.1.5': + resolution: {integrity: sha512-x9bL9Mx2CT2P1OiUlHM+ZNpbVU6TgT32f9CmTRzqIHA7M4vYrROCWEoC3o4xHNJASoGd4Opos3cXYPgh+/m4Ww==} + engines: {node: '>=16.0.0'} '@smithy/types@2.12.0': resolution: {integrity: sha512-QwYgloJ0sVNBeBuBs65cIkTbfzV/Q6ZNPCJ99EICFEdJYG50nGIY/uYXp+TbsdJReIuPr0a0kXmCvren3MbRRw==} engines: {node: '>=14.0.0'} - '@smithy/types@2.6.0': - resolution: {integrity: sha512-PgqxJq2IcdMF9iAasxcqZqqoOXBHufEfmbEUdN1pmJrJltT42b0Sc8UiYSWWzKkciIp9/mZDpzYi4qYG1qqg6g==} - engines: {node: '>=14.0.0'} + '@smithy/types@3.3.0': + resolution: {integrity: sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA==} + engines: {node: '>=16.0.0'} - '@smithy/url-parser@2.0.8': - resolution: {integrity: sha512-wQw7j004ScCrBRJ+oNPXlLE9mtofxyadSZ9D8ov/rHkyurS7z1HTNuyaGRj6OvKsEk0SVQsuY0C9+EfM75XTkw==} + '@smithy/url-parser@3.0.3': + resolution: {integrity: sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A==} - '@smithy/util-base64@2.0.0': - resolution: {integrity: sha512-Zb1E4xx+m5Lud8bbeYi5FkcMJMnn+1WUnJF3qD7rAdXpaL7UjkFQLdmW5fHadoKbdHpwH9vSR8EyTJFHJs++tA==} - engines: {node: '>=14.0.0'} + '@smithy/util-base64@3.0.0': + resolution: {integrity: sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==} + engines: {node: '>=16.0.0'} - '@smithy/util-body-length-browser@2.0.0': - resolution: {integrity: sha512-JdDuS4ircJt+FDnaQj88TzZY3+njZ6O+D3uakS32f2VNnDo3vyEuNdBOh/oFd8Df1zSZOuH1HEChk2AOYDezZg==} + '@smithy/util-body-length-browser@3.0.0': + resolution: {integrity: sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==} - '@smithy/util-body-length-node@2.1.0': - resolution: {integrity: sha512-/li0/kj/y3fQ3vyzn36NTLGmUwAICb7Jbe/CsWCktW363gh1MOcpEcSO3mJ344Gv2dqz8YJCLQpb6hju/0qOWw==} - engines: {node: '>=14.0.0'} + '@smithy/util-body-length-node@3.0.0': + resolution: {integrity: sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==} + engines: {node: '>=16.0.0'} '@smithy/util-buffer-from@2.0.0': resolution: {integrity: sha512-/YNnLoHsR+4W4Vf2wL5lGv0ksg8Bmk3GEGxn2vEQt52AQaPSCuaO5PM5VM7lP1K9qHRKHwrPGktqVoAHKWHxzw==} engines: {node: '>=14.0.0'} - '@smithy/util-config-provider@2.0.0': - resolution: {integrity: sha512-xCQ6UapcIWKxXHEU4Mcs2s7LcFQRiU3XEluM2WcCjjBtQkUN71Tb+ydGmJFPxMUrW/GWMgQEEGipLym4XG0jZg==} - engines: {node: '>=14.0.0'} + '@smithy/util-buffer-from@3.0.0': + resolution: {integrity: sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==} + engines: {node: '>=16.0.0'} - '@smithy/util-defaults-mode-browser@2.0.9': - resolution: {integrity: sha512-JONLJVQWT8165XoSV36ERn3SVlZLJJ4D6IeGsCSePv65Uxa93pzSLE0UMSR9Jwm4zix7rst9AS8W5QIypZWP8Q==} + '@smithy/util-config-provider@3.0.0': + resolution: {integrity: sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==} + engines: {node: '>=16.0.0'} + + '@smithy/util-defaults-mode-browser@3.0.7': + resolution: {integrity: sha512-Q2txLyvQyGfmjsaDbVV7Sg8psefpFcrnlGapDzXGFRPFKRBeEg6OvFK8FljqjeHSaCZ6/UuzQExUPqBR/2qlDA==} engines: {node: '>= 10.0.0'} - '@smithy/util-defaults-mode-node@2.0.11': - resolution: {integrity: sha512-tmqjNsfj+bgZN6jXBe6efZnukzILA7BUytHkzqikuRLNtR+0VVchQHvawD0w6vManh76rO81ydhioe7i4oBzuA==} + '@smithy/util-defaults-mode-node@3.0.7': + resolution: {integrity: sha512-F4Qcj1fG6MGi2BSWCslfsMSwllws/WzYONBGtLybyY+halAcXdWhcew+mej8M5SKd5hqPYp4f7b+ABQEaeytgg==} engines: {node: '>= 10.0.0'} - '@smithy/util-hex-encoding@2.0.0': - resolution: {integrity: sha512-c5xY+NUnFqG6d7HFh1IFfrm3mGl29lC+vF+geHv4ToiuJCBmIfzx6IeHLg+OgRdPFKDXIw6pvi+p3CsscaMcMA==} - engines: {node: '>=14.0.0'} + '@smithy/util-endpoints@2.0.4': + resolution: {integrity: sha512-ZAtNf+vXAsgzgRutDDiklU09ZzZiiV/nATyqde4Um4priTmasDH+eLpp3tspL0hS2dEootyFMhu1Y6Y+tzpWBQ==} + engines: {node: '>=16.0.0'} - '@smithy/util-middleware@2.0.1': - resolution: {integrity: sha512-LnsBMi0Mg3gfz/TpNGLv2Jjcz2ra1OX5HR/4IaCepIYmtPQzqMWDdhX/XTW1LS8OZ0xbQuyQPcHkQ+2XkhWOVQ==} - engines: {node: '>=14.0.0'} + '@smithy/util-hex-encoding@3.0.0': + resolution: {integrity: sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==} + engines: {node: '>=16.0.0'} - '@smithy/util-retry@2.0.1': - resolution: {integrity: sha512-naj4X0IafJ9yJnVJ58QgSMkCNLjyQOnyrnKh/T0f+0UOUxJiT8vuFn/hS7B/pNqbo2STY7PyJ4J4f+5YqxwNtA==} - engines: {node: '>= 14.0.0'} + '@smithy/util-middleware@3.0.3': + resolution: {integrity: sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw==} + engines: {node: '>=16.0.0'} - '@smithy/util-stream@2.0.11': - resolution: {integrity: sha512-2MeWfqSpZKdmEJ+tH8CJQSgzLWhH5cmdE24X7JB0hiamXrOmswWGGuPvyj/9sQCTclo57pNxLR2p7KrP8Ahiyg==} - engines: {node: '>=14.0.0'} + '@smithy/util-retry@3.0.3': + resolution: {integrity: sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w==} + engines: {node: '>=16.0.0'} - '@smithy/util-uri-escape@2.0.0': - resolution: {integrity: sha512-ebkxsqinSdEooQduuk9CbKcI+wheijxEb3utGXkCoYQkJnwTnLbH1JXGimJtUkQwNQbsbuYwG2+aFVyZf5TLaw==} - engines: {node: '>=14.0.0'} + '@smithy/util-stream@3.0.5': + resolution: {integrity: sha512-xC3L5PKMAT/Bh8fmHNXP9sdQ4+4aKVUU3EEJ2CF/lLk7R+wtMJM+v/1B4en7jO++Wa5spGzFDBCl0QxgbUc5Ug==} + engines: {node: '>=16.0.0'} '@smithy/util-uri-escape@2.2.0': resolution: {integrity: sha512-jtmJMyt1xMD/d8OtbVJ2gFZOSKc+ueYJZPW20ULW1GOp/q/YIM0wNh+u8ZFao9UaIGz4WoPW8hC64qlWLIfoDA==} engines: {node: '>=14.0.0'} + '@smithy/util-uri-escape@3.0.0': + resolution: {integrity: sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==} + engines: {node: '>=16.0.0'} + '@smithy/util-utf8@2.0.0': resolution: {integrity: sha512-rctU1VkziY84n5OXe3bPNpKR001ZCME2JCaBBFgtiM2hfKbHFudc/BkMuPab8hRbLd0j3vbnBTTZ1igBf0wgiQ==} engines: {node: '>=14.0.0'} - '@smithy/util-waiter@2.0.8': - resolution: {integrity: sha512-t9yaoofNhdEhNlyDeV5al/JJEFJ62HIQBGktgCUE63MvKn6imnbkh1qISsYMyMYVLwhWCpZ3Xa3R1LA+SnWcng==} - engines: {node: '>=14.0.0'} + '@smithy/util-utf8@3.0.0': + resolution: {integrity: sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==} + engines: {node: '>=16.0.0'} + + '@smithy/util-waiter@3.1.2': + resolution: {integrity: sha512-4pP0EV3iTsexDx+8PPGAKCQpd/6hsQBaQhqWzU4hqKPHN5epPsxKbvUTIiYIHTxaKt6/kEaqPBpu/ufvfbrRzw==} + engines: {node: '>=16.0.0'} '@sqltools/formatter@1.2.5': resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} - '@storybook/addon-actions@8.0.9': - resolution: {integrity: sha512-+I3VTvlKdj8puHeS2tyaOVv9syDiNLneVZbTfqN+UDOK2i42NwvZr8PVwjTzMlEj9eePJdCZgiipz55xwts5bw==} + '@storybook/addon-actions@8.1.11': + resolution: {integrity: sha512-jqYXgBgOVInStOCk//AA+dGkrfN8R7rDXA4lyu82zM59kvICtG9iqgmkSRDn0Z3zUkM+lIHZGoz0aLVQ8pxsgw==} - '@storybook/addon-backgrounds@8.0.9': - resolution: {integrity: sha512-pCDecACrVyxPaJKEWS0sHsRb8xw+IPCSxDM1TkjaAQ6zZ468A/dcUnqW+LVK8bSXgQwWzn23wqnqPFSy5yptuQ==} + '@storybook/addon-backgrounds@8.1.11': + resolution: {integrity: sha512-naGf1ovmsU2pSWb270yRO1IidnO+0YCZ5Tcb8I4rPhZ0vsdXNURYKS1LPSk1OZkvaUXdeB4Im9HhHfUBJOW9oQ==} - '@storybook/addon-controls@8.0.9': - resolution: {integrity: sha512-wWdmd62UP/sfPm8M7aJjEA+kEXTUIR/QsYi9PoYBhBZcXiikZ4kNan7oD7GfsnzGGKHrBVfwQhO+TqaENGYytA==} + '@storybook/addon-controls@8.1.11': + resolution: {integrity: sha512-q/Vt4meNVlFlBWIMCJhx6r+bqiiYocCta2RoUK5nyIZUiLzHncKHX6JnCU36EmJzRyah9zkwjfCb2G1r9cjnoQ==} - '@storybook/addon-docs@8.0.9': - resolution: {integrity: sha512-x7hX7UuzJtClu6XwU3SfpyFhuckVcgqgD6BU6Ihxl0zs+i4xp6iKVXYSnHFMRM1sgoeT8TjPxab35Ke8w8BVRw==} + '@storybook/addon-docs@8.1.11': + resolution: {integrity: sha512-69dv+CE4R5wFU7xnJmhuyEbLN2PEVDV3N/BbgJqeucIYPmm6zDV83Q66teCHKYtRln3BFUqPH5mxsjiHobxfJQ==} - '@storybook/addon-essentials@8.0.9': - resolution: {integrity: sha512-mwAgdfrOsTuTDcagvM7veBh+iayZIWmKOazzkhrIWbhYcrXOsweigD2UOVeHgAiAzJK49znr4FXTCKcE1hOWcw==} + '@storybook/addon-essentials@8.1.11': + resolution: {integrity: sha512-uRTpcIZQnflML8H+2onicUNIIssKfuviW8Lyrs/KFwSZ1rMcYzhwzCNbGlIbAv04tgHe5NqEyNhb+DVQcZQBzg==} - '@storybook/addon-highlight@8.0.9': - resolution: {integrity: sha512-vaRHGDbx7dpNpQECAHk5wczlZO3ntstprGlqnZt0o7ylz6xB5+pTQwTuIFty0hwKv+3TPcskzzifATUyEOEmyg==} + '@storybook/addon-highlight@8.1.11': + resolution: {integrity: sha512-Iu8FCAd4ETsB6QF4xDE/OLLZY3HOFopuLM5KE0f58jnccF5zAVGr1Rj/54p6TeK0PEou0tLRPFuZs+LPlEzrSw==} - '@storybook/addon-interactions@8.0.9': - resolution: {integrity: sha512-AMIdNcyM6DDAWvMitBJMqp1iPZND8AXB4QT4VZHGMKG2ngHNKktriEKpTfcRkfKPGTJs9T+71dWfm6/R4tticw==} + '@storybook/addon-interactions@8.1.11': + resolution: {integrity: sha512-nkc01z61mYM1kxf0ncBQLlFnnwW4RAVPfRSxK9BdbFN3AAvFiHCwVZdn71mi+C3L8oTqYR6o32e0RlXk+AjhHA==} - '@storybook/addon-links@8.0.9': - resolution: {integrity: sha512-FVt+AdW3JFSqbJzkKiqKsMRWqHXqEvCBqFs7lNfk3OW0w0jfv1iREtrxE0dVdJoUFQC9V/2Im/EpJ7UB3C2bNQ==} + '@storybook/addon-links@8.1.11': + resolution: {integrity: sha512-HlV2RQSrZyi+55W1B1a9eWNuJdNpWx0g3j7s2arNlNmbd6/kfWAp84axBstI1tL0nW4svut7bWlCsMSOIden+A==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta peerDependenciesMeta: react: optional: true - '@storybook/addon-mdx-gfm@8.0.9': - resolution: {integrity: sha512-AoEx+OGKANtVZgKyWKrQhGpMpDuc2S7PnOlNLUiDYzmj8ABAGPmEJmqeb/VHVgqLQSjhOW1fMsQ4fYsecvMxTQ==} + '@storybook/addon-mdx-gfm@8.1.11': + resolution: {integrity: sha512-0/4Xaisvmoi26iK1ezTOB9dN2b0JbgWKzO2PO6att2Jh7lplLCf1QeoE8Y4SgCh0brage+mA8mKI8NrT7d18pg==} - '@storybook/addon-measure@8.0.9': - resolution: {integrity: sha512-91svOOGEXmGG4USglwXLE3wtlUVgtbKJVxTKX7xRI+AC5JEEaKByVzP17/X8Qn/8HilUL7AfSQ0kCoqtPSJ5cA==} + '@storybook/addon-measure@8.1.11': + resolution: {integrity: sha512-LkQD3SiLWaWt53aLB3EnmhD9Im8EOO+HKSUE+XGnIJRUcHHRqHfvDkN9KX7T1DCWbfRE5WzMHF5o23b3UiAANw==} - '@storybook/addon-outline@8.0.9': - resolution: {integrity: sha512-fQ+jm356TgUnz81IxsC99/aOesbLw3N5OQRJpo/A6kqbLMzlq3ybVzuXYCKC3f0ArgQRNh4NoMeJBMRFMtaWRw==} + '@storybook/addon-outline@8.1.11': + resolution: {integrity: sha512-vco3RLVjkcS25dNtj1lxmjq4fC0Nq08KNLMS5cbNPVJWNTuSUi/2EthSTQQCdpfMV/p6u+D5uF20A9Pl0xJFXw==} - '@storybook/addon-storysource@8.0.9': - resolution: {integrity: sha512-5m3K2Rs4fQtKtqwrq4CDS1jK2wzWOlnxhE2ArX5XTWytb1am65CEPxfYTEQkvZH9oPGwX3cXytPCziynqysFMQ==} + '@storybook/addon-storysource@8.1.11': + resolution: {integrity: sha512-b2K3+ZzfANDTTeN1jnqNgAQ5ZIhnhIAv89gC/36cOhSK5NLyKmyVKLGQmR3fVqX3URpnz9xccst2JNXopvtccw==} - '@storybook/addon-toolbars@8.0.9': - resolution: {integrity: sha512-nNSBnnBOhQ+EJwkrIkK4ZBYPcozNmEH770CZ/6NK85SUJ6WEBZapE6ru33jIUokFGEvlOlNCeai0GUc++cQP8w==} + '@storybook/addon-toolbars@8.1.11': + resolution: {integrity: sha512-reIKB0+JTiP+GNzynlDcRf4xmv9+j/DQ94qiXl2ZG5+ufKilH8DiRZpVA/i0x+4+TxdGdOJr1/pOf8tAmhNEoQ==} - '@storybook/addon-viewport@8.0.9': - resolution: {integrity: sha512-Ao4+D56cO7biaw+iTlMU1FBec1idX0cmdosDeCFZin06MSawcPkeBlRBeruaSQYdLes8TBMdZPFgfuqI5yIk6g==} + '@storybook/addon-viewport@8.1.11': + resolution: {integrity: sha512-qk4IcGnAgiAUQxt8l5PIQ293Za+w6wxlJQIpxr7+QM8OVkADPzXY0MmQfYWU9EQplrxAC2MSx3/C1gZeq+MDOQ==} - '@storybook/blocks@8.0.9': - resolution: {integrity: sha512-F2zSrfSwzTFN7qW3zB80tG+EXtmfmCDC6Ird0F7tolszb6tOqJcAcBOwQbE2O0wI63sLu21qxzXgaKBMkiWvJg==} + '@storybook/blocks@8.1.11': + resolution: {integrity: sha512-eMed7PpL/hAVM6tBS7h70bEAyzbiSU9I/kye4jZ7DkCbAsrX6OKmC7pcHSDn712WTcf3vVqxy5jOKUmOXpc0eg==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta peerDependenciesMeta: react: optional: true react-dom: optional: true - '@storybook/builder-manager@8.0.9': - resolution: {integrity: sha512-/PxDwZIfMc/PSRZcasb6SIdGr3azIlenzx7dBF7Imt8i4jLHiAf1t00GvghlfJsvsrn4DNp95rbRbXTDyTj7tQ==} + '@storybook/builder-manager@8.1.11': + resolution: {integrity: sha512-U7bmed4Ayg+OlJ8HPmLeGxLTHzDY7rxmxM4aAs4YL01fufYfBcjkIP9kFhJm+GJOvGm+YJEUAPe5mbM1P/bn0Q==} - '@storybook/builder-vite@8.0.9': - resolution: {integrity: sha512-7hEQFZIIz7VvxdySDpPE96iMvZxQvRZcRdhaNGeE+8Y2pyc3DgYE4WY3sjr+LUoB0a6TYLpAIKqbXwtLz0R+PQ==} + '@storybook/builder-vite@8.1.11': + resolution: {integrity: sha512-hG4eoNMCPgjZ2Ai+zSmk69zjsyEihe75XbJXtYfGRqjMWtz2+SAUFO54fLc2BD5svcUiTeN+ukWcTrwApyPsKg==} peerDependencies: '@preact/preset-vite': '*' typescript: '>= 4.3.x' @@ -3974,48 +4377,53 @@ packages: vite-plugin-glimmerx: optional: true - '@storybook/channels@8.0.9': - resolution: {integrity: sha512-7Lcfyy5CsLWWGhMPO9WG4jZ/Alzp0AjepFhEreYHRPtQrfttp6qMAjE/g1aHgun0qHCYWxwqIG4NLR/hqDNrXQ==} + '@storybook/channels@8.1.11': + resolution: {integrity: sha512-fu5FTqo6duOqtJFa6gFzKbiSLJoia+8Tibn3xFfB6BeifWrH81hc+AZq0lTmHo5qax2G5t8ZN8JooHjMw6k2RA==} - '@storybook/cli@8.0.9': - resolution: {integrity: sha512-lilYTKn8F5YOePijqfRYFa5v2mHVIJxPCIgTn+OXAmAFbcizZ6P8P6niU4J/NXulgx68Ln1M7hYhFtTP25hVTw==} + '@storybook/cli@8.1.11': + resolution: {integrity: sha512-4U48w9C7mVEKrykcPcfHwJkRyCqJ28XipbElACbjIIkQEqaHaOVtP3GeKIrgkoOXe/HK3O4zKWRP2SqlVS0r4A==} hasBin: true - '@storybook/client-logger@8.0.9': - resolution: {integrity: sha512-LzV/RHkbf07sRc1Jc0ff36RlapKf9Ul7/+9VMvVbI3hshH1CpmrZK4t/tsIdpX/EVOdJ1Gg5cES06PnleOAIPA==} + '@storybook/client-logger@8.1.11': + resolution: {integrity: sha512-DVMh2usz3yYmlqCLCiCKy5fT8/UR9aTh+gSqwyNFkGZrIM4otC5A8eMXajXifzotQLT5SaOEnM3WzHwmpvMIEA==} - '@storybook/codemod@8.0.9': - resolution: {integrity: sha512-VBeGpSZSQpL6iyLLqceJSNGhdCqcNwv+xC/aWdDFOkmuE1YfbmNNwpa9QYv4ZFJ2QjUsm4iTWG60qK+9NXeSKA==} + '@storybook/codemod@8.1.11': + resolution: {integrity: sha512-/LCozjH1IQ1TOs9UQV59BE0X6UZ9q+C0NEUz7qmJZPrwAii3FkW4l7D/fwxblpMExaoxv0oE8NQfUz49U/5Ymg==} - '@storybook/components@8.0.9': - resolution: {integrity: sha512-JcwBGADzIJs0PSzqykrrD2KHzNG9wtexUOKuidt+FSv9szpUhe3qBAXIHpdfBRl7mOJ9TRZ5rt+mukEnfncdzA==} + '@storybook/components@8.1.11': + resolution: {integrity: sha512-iXKsNu7VmrLBtjMfPj7S4yJ6T13GU6joKcVcrcw8wfrQJGlPFp4YaURPBUEDxvCt1XWi5JkaqJBvb48kIrROEQ==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - '@storybook/core-common@8.0.9': - resolution: {integrity: sha512-Jmue+sfHFb4GTYBzyWYw1MygoJiQSfISIrKmNIzAmZ+oR9EOr+jpu/i/bH+uetZ2Hqg1AGhj1VB7OtJp9HQyWw==} + '@storybook/core-common@8.1.11': + resolution: {integrity: sha512-Ix0nplD4I4DrV2t9B+62jaw1baKES9UbR/Jz9LVKFF9nsua3ON0aVe73dOjMxFWBngpzBYWe+zYBTZ7aQtDH4Q==} + peerDependencies: + prettier: ^2 || ^3 + peerDependenciesMeta: + prettier: + optional: true - '@storybook/core-events@8.0.9': - resolution: {integrity: sha512-DxSUx7wG9Qe3OFUBnv3OrYq48J8UWNo2DUR5/JecJCtp3n++L4fAEW3J0IF5FfxpQDMQSp1yTNjZ2PaWCMd2ag==} + '@storybook/core-events@8.1.11': + resolution: {integrity: sha512-vXaNe2KEW9BGlLrg0lzmf5cJ0xt+suPjWmEODH5JqBbrdZ67X6ApA2nb6WcxDQhykesWCuFN5gp1l+JuDOBi7A==} - '@storybook/core-server@8.0.9': - resolution: {integrity: sha512-BIe1T5YUBl0GYxEjRoTQsvXD2pyuzL8rPTUD41zlzSQM0R8U6Iant9SzRms4u0+rKUm2mGxxKuODlUo5ewqaGA==} + '@storybook/core-server@8.1.11': + resolution: {integrity: sha512-L6dzQTmR0np/kagNONvvlm6lSvF1FNc9js3vxsEEPnEypLbhx8bDZaHmuhmBpYUzKyUMpRVQTE/WgjHLuBBuxA==} - '@storybook/csf-plugin@8.0.9': - resolution: {integrity: sha512-pXaNCNi++kxKsqSWwvx215fPx8cNqvepLVxQ7B69qXLHj80DHn0Q3DFBO3sLXNiQMJ2JK4OYcTxMfuOiyzszKw==} + '@storybook/csf-plugin@8.1.11': + resolution: {integrity: sha512-hkA8gjFtSN/tabG0cuvmEqanMXtxPr3qTkp4UNSt1R6jBEgFHRG2y/KYLl367kDwOSFTT987ZgRfJJruU66Fvw==} - '@storybook/csf-tools@8.0.9': - resolution: {integrity: sha512-PiNMhL97giLytTdQwuhsZ92buVk4gy9H/8DtrDhUc45/1OmF95gogm6T2Yap729SIFwgpOcuq/U3aVo6d6swVQ==} + '@storybook/csf-tools@8.1.11': + resolution: {integrity: sha512-6qMWAg/dBwCVIHzANM9lSHoirwqSS+wWmv+NwAs0t9S94M75IttHYxD3IyzwaSYCC5llp0EQFvtXXAuSfFbibg==} - '@storybook/csf@0.1.6': - resolution: {integrity: sha512-JjWnBptVhBYJ14yq+cHs66BXjykRUWQ5TlD1RhPxMOtavynYyV/Q+QR98/N+XB+mcPtFMm5I2DvNkpj0/Dk8Mw==} + '@storybook/csf@0.1.9': + resolution: {integrity: sha512-JlZ6v/iFn+iKohKGpYXnMeNeTiiAMeFoDhYnPLIC8GnyyIWqEI9wJYrOK9i9rxlJ8NZAH/ojGC/u/xVC41qSgQ==} - '@storybook/docs-mdx@3.0.0': - resolution: {integrity: sha512-NmiGXl2HU33zpwTv1XORe9XG9H+dRUC1Jl11u92L4xr062pZtrShLmD4VKIsOQujxhhOrbxpwhNOt+6TdhyIdQ==} + '@storybook/docs-mdx@3.1.0-next.0': + resolution: {integrity: sha512-t4syFIeSyufieNovZbLruPt2DmRKpbwL4fERCZ1MifWDRIORCKLc4NCEHy+IqvIqd71/SJV2k4B51nF7vlJfmQ==} - '@storybook/docs-tools@8.0.9': - resolution: {integrity: sha512-OzogAeOmeHea/MxSPKRBWtOQVNSpoq+OOpimO9YRA5h5GBRJ2TUOGT44Gny6QT4ll5AvQA8fIiq9KezKcLekAg==} + '@storybook/docs-tools@8.1.11': + resolution: {integrity: sha512-mEXtR9rS7Y+OdKtT/QG6JBGYR1L41mcDhIqhnk7RmYl9qJstVAegrCKWR53sPKFdTVOHU7dmu6k+BD+TqHpyyw==} '@storybook/global@5.0.0': resolution: {integrity: sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==} @@ -4027,83 +4435,83 @@ packages: react: ^16.8.0 || ^17.0.0 || ^18.0.0 react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 - '@storybook/instrumenter@8.0.9': - resolution: {integrity: sha512-Gw74dgpTU/2p7FG0s7DuVdqCbJ2MEcSuRJjDo7HcXRYcvWp7I6Ly+C0v7N5VaoS+kbBVerAhLKIHZgG/LZf1og==} + '@storybook/instrumenter@8.1.11': + resolution: {integrity: sha512-r/U9hcqnodNMHuzRt1g56mWrVsDazR85Djz64M3KOwBhrTj5d46DF4/EE80w/5zR5JOrT7p8WmjJRowiVteOCQ==} - '@storybook/manager-api@8.0.9': - resolution: {integrity: sha512-99b3yKArDSvfabXL7QE3nA95e4DdW/5H/ZCcr6/E2qCQJayZ6G1v/WWamKXbiaTpkndulFmcb/+ZmnDXcweIIQ==} + '@storybook/manager-api@8.1.11': + resolution: {integrity: sha512-QSgwKfAw01K9YvvZj30iGBMgQ4YaCT3vojmttuqdH5ukyXkiO7pENLJj4Y+alwUeSi0g+SJeadCI3PXySBHOGg==} - '@storybook/manager@8.0.9': - resolution: {integrity: sha512-+NnRo+5JQFGNqveKrLtC0b+Z08Tae4m44iq292bPeZMpr9OkFsIkU0PBPsHTHPkrqC/zZXRNsCsTEgvu3p2OIA==} + '@storybook/manager@8.1.11': + resolution: {integrity: sha512-e02y9dmxowo7cTKYm9am7UO6NOHoHy6Xi7xZf/UA932qLwFZUtk5pnwIEFaZWI3OQsRUCGhP+FL5zizU7uVZeg==} - '@storybook/node-logger@8.0.9': - resolution: {integrity: sha512-5ajMdZFrYrjGLJOVDq7dlEQNFsgeLHymt4dCK9MulL/ciXykmXUZXE3Bye0wFy+I2qqDVvrvR8uzCvSFvm5MAQ==} + '@storybook/node-logger@8.1.11': + resolution: {integrity: sha512-wdzFo7B2naGhS52L3n1qBkt5BfvQjs8uax6B741yKRpiGgeAN8nz8+qelkD25MbSukxvbPgDot7WJvsMU/iCzg==} - '@storybook/preview-api@8.0.9': - resolution: {integrity: sha512-zHfX34bkAMzzmE7vbDzaqFwSW6ExiBD0HiO1L/IsHF55f0f7xV7IH8uJyFRrDTvAoW3ReSxZDMvvPpeydFPKGA==} + '@storybook/preview-api@8.1.11': + resolution: {integrity: sha512-8ZChmFV56GKppCJ0hnBd/kNTfGn2gWVq1242kuet13pbJtBpvOhyq4W01e/Yo14tAPXvgz8dSnMvWLbJx4QfhQ==} - '@storybook/preview@8.0.9': - resolution: {integrity: sha512-tFsR8xc8AYBZZrZw8enklFbSQt7ZAV+rv20BoxwDhd3q7fjXyK7O4moGPqUwBZ7rukTG13nPoISxr+VXAk/HYA==} + '@storybook/preview@8.1.11': + resolution: {integrity: sha512-K/9NZmjnL0D1BROkTNWNoPqgL2UaocALRSqCARmkBLgU2Rn/FuZgEclHkWlYo6pUrmLNK+bZ+XzpNMu12iTbpg==} - '@storybook/react-dom-shim@8.0.9': - resolution: {integrity: sha512-8011KlRuG3obr5pZZ7bcEyYYNWF3tR596YadoMd267NPoHKvwAbKL1L/DNgb6kiYjZDUf9QfaKSCWW31k0kcRQ==} + '@storybook/react-dom-shim@8.1.11': + resolution: {integrity: sha512-KVDSuipqkFjpGfldoRM5xR/N1/RNmbr+sVXqMmelr0zV2jGnexEZnoa7wRHk7IuXuivLWe8BxMxzvQWqjIa4GA==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - '@storybook/react-vite@8.0.9': - resolution: {integrity: sha512-FT5KeulUH6grfzOJOxJCxpv9+81UVDrT9UPcgiFhQT9rKtsgmltezThwbHknByZNw3WWnf+ieidMLEis9hd73A==} + '@storybook/react-vite@8.1.11': + resolution: {integrity: sha512-QqkE6QKsIDthXtps9+YSBQ39O4VvU7Uu3y6WSA3IPgKTtGnmIvhwXtapjf7WQ2cNb5KY1JksFxHXbDe0i5IL4g==} engines: {node: '>=18.0.0'} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta vite: ^4.0.0 || ^5.0.0 - '@storybook/react@8.0.9': - resolution: {integrity: sha512-NeQ6suZG3HKikwe3Tx9cAIaRx7uP8FKCmlVvIiBg4LTTI5orCt94PPakvuZukZcbkqvcCnEBkebAzwUpn8PiJw==} + '@storybook/react@8.1.11': + resolution: {integrity: sha512-t+EYXOkgwg3ropLGS9y8gGvX5/Okffu/6JYL3YWksrBGAZSqVV4NkxCnVJZepS717SyhR0tN741gv/SxxFPJMg==} engines: {node: '>=18.0.0'} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta typescript: '>= 4.2.x' peerDependenciesMeta: typescript: optional: true - '@storybook/router@8.0.9': - resolution: {integrity: sha512-aAOWxbM9J4mt+cp4o88T2PB29mgBBTOzU37/pUsTHYnKnR9XI4npXEXdN8Gv+ryqM0kj0AbBpz/llFlnR2MNNA==} + '@storybook/router@8.1.11': + resolution: {integrity: sha512-nU5lsBvy0L8wBYOkjagh29ztZicDATpZNYrHuavlhQ2jznmmHdJvXKYk+VrMAbthjQ6ZBqfeeMNPR1UlnqR5Rw==} - '@storybook/source-loader@8.0.9': - resolution: {integrity: sha512-FDnpxIGE5nIYT15pvYe6rz95TSBrdLcDll7lOHNyZisWt19MI3wZU3YkVsFNRBuFrebo+FjVU3wHyoV81ur1Qw==} + '@storybook/source-loader@8.1.11': + resolution: {integrity: sha512-4cfJ7aPjtniIdDGiFjdFpO47byHOl4RKYCJEHf9t+j0xHmlXe4B9aAinxuFfv3GKAXfLvSbbwGO0cDZQRj+brw==} - '@storybook/telemetry@8.0.9': - resolution: {integrity: sha512-AGGfcup06t+wxhBIkHd0iybieOh9PDVZQJ9oPct5JGB39+ni9wvs0WOD+MYlHbsjp8id7+aGkh6mYuYOvfck+Q==} + '@storybook/telemetry@8.1.11': + resolution: {integrity: sha512-Jqvm7HcZismKzPuebhyLECO6KjGiSk4ycbca1WUM/TUvifxCXqgoUPlHHQEEfaRdHS63/MSqtMNjLsQRLC/vNQ==} - '@storybook/test@8.0.9': - resolution: {integrity: sha512-bRd5tBJnPzR6UKbDXONWnFWtdkNOY99HMLDUWe5fTRo50GwkrpFBVqPflhdkruEeof0kAbBUbnoN2CIYgtnAFw==} + '@storybook/test@8.1.11': + resolution: {integrity: sha512-k+V3HemF2/I8fkRxRqM8uH8ULrpBSAAdBOtWSHWLvHguVcb2YA4g4kKo6tXBB9256QfyDW4ZiaAj0/9TMxmJPQ==} - '@storybook/theming@8.0.9': - resolution: {integrity: sha512-jgfDuYoiNMMirQiASN3Eg0hGDXsEtpdAcMxyShqYGwu9elxgD9yUnYC2nSckYsM74a3ZQ3JaViZ9ZFSe2FHmeQ==} + '@storybook/theming@8.1.11': + resolution: {integrity: sha512-Chn/opjO6Rl1isNobutYqAH2PjKNkj09YBw/8noomk6gElSa3JbUTyaG/+JCHA6OG/9kUsqoKDb5cZmAKNq/jA==} peerDependencies: - react: ^16.8.0 || ^17.0.0 || ^18.0.0 - react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta peerDependenciesMeta: react: optional: true react-dom: optional: true - '@storybook/types@8.0.9': - resolution: {integrity: sha512-ew0EXzk9k4B557P1qIWYrnvUcgaE0WWA5qQS0AU8l+fRTp5nvl9O3SP/zNIB0SN1qDFO7dXr3idTNTyIikTcEQ==} + '@storybook/types@8.1.11': + resolution: {integrity: sha512-k9N5iRuY2+t7lVRL6xeu6diNsxO3YI3lS4Juv3RZ2K4QsE/b3yG5ElfJB8DjHDSHwRH4ORyrU71KkOCUVfvtnw==} - '@storybook/vue3-vite@8.0.9': - resolution: {integrity: sha512-IkzYsEyCo5HIvLWbJeGrBu/VIN4u+LvdIAz7vcFqVVXBtTUhy+9/8caLx8fdnM0FWgKcBRQs8HnjBB2V0lOFcg==} + '@storybook/vue3-vite@8.1.11': + resolution: {integrity: sha512-q0bqh8XEEunaTmp4YiDqM2+YZLwEIevTb5PnNe7G7f2qOiSCE1ncBDnBK717UlCd+iYr34NTztgV2/jIhz1i5w==} engines: {node: '>=18.0.0'} peerDependencies: vite: ^4.0.0 || ^5.0.0 - '@storybook/vue3@8.0.9': - resolution: {integrity: sha512-EqVdS62YbOCAE0wJrQKW0sHpM90be8N8Mvmj+HzB0QYhJNtFqP9ehwbcTfwEKtaVGudisHgGBOzNoSKDlxFaag==} + '@storybook/vue3@8.1.11': + resolution: {integrity: sha512-xJtvfLiCOY3UqwDMd0hZdsadPm1q8dwjfM1UN2Q2ssRWNfXzww1oi+Msj902wz9zFZMYVZypfTfgrdRgWmfEjA==} engines: {node: '>=18.0.0'} peerDependencies: vue: ^3.0.0 @@ -4131,8 +4539,8 @@ packages: cpu: [arm64] os: [darwin] - '@swc/core-darwin-arm64@1.4.17': - resolution: {integrity: sha512-HVl+W4LezoqHBAYg2JCqR+s9ife9yPfgWSj37iIawLWzOmuuJ7jVdIB7Ee2B75bEisSEKyxRlTl6Y1Oq3owBgw==} + '@swc/core-darwin-arm64@1.6.6': + resolution: {integrity: sha512-5DA8NUGECcbcK1YLKJwNDKqdtTYDVnkfDU1WvQSXq/rU+bjYCLtn5gCe8/yzL7ISXA6rwqPU1RDejhbNt4ARLQ==} engines: {node: '>=10'} cpu: [arm64] os: [darwin] @@ -4143,8 +4551,8 @@ packages: cpu: [x64] os: [darwin] - '@swc/core-darwin-x64@1.4.17': - resolution: {integrity: sha512-WYRO9Fdzq4S/he8zjW5I95G1zcvyd9yyD3Tgi4/ic84P5XDlSMpBDpBLbr/dCPjmSg7aUXxNQqKqGkl6dQxYlA==} + '@swc/core-darwin-x64@1.6.6': + resolution: {integrity: sha512-2nbh/RHpweNRsJiYDFk1KcX7UtaKgzzTNUjwtvK5cp0wWrpbXmPvdlWOx3yzwoiSASDFx78242JHHXCIOlEdsw==} engines: {node: '>=10'} cpu: [x64] os: [darwin] @@ -4161,8 +4569,8 @@ packages: cpu: [arm] os: [linux] - '@swc/core-linux-arm-gnueabihf@1.4.17': - resolution: {integrity: sha512-cgbvpWOvtMH0XFjvwppUCR+Y+nf6QPaGu6AQ5hqCP+5Lv2zO5PG0RfasC4zBIjF53xgwEaaWmGP5/361P30X8Q==} + '@swc/core-linux-arm-gnueabihf@1.6.6': + resolution: {integrity: sha512-YgytuyUfR7b0z0SRHKV+ylr83HmgnROgeT7xryEkth6JGpAEHooCspQ4RrWTU8+WKJ7aXiZlGXPgybQ4TiS+TA==} engines: {node: '>=10'} cpu: [arm] os: [linux] @@ -4173,8 +4581,8 @@ packages: cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-gnu@1.4.17': - resolution: {integrity: sha512-l7zHgaIY24cF9dyQ/FOWbmZDsEj2a9gRFbmgx2u19e3FzOPuOnaopFj0fRYXXKCmtdx+anD750iBIYnTR+pq/Q==} + '@swc/core-linux-arm64-gnu@1.6.6': + resolution: {integrity: sha512-yGwx9fddzEE0iURqRVwKBQ4IwRHE6hNhl15WliHpi/PcYhzmYkUIpcbRXjr0dssubXAVPVnx6+jZVDSbutvnfg==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -4185,8 +4593,8 @@ packages: cpu: [arm64] os: [linux] - '@swc/core-linux-arm64-musl@1.4.17': - resolution: {integrity: sha512-qhH4gr9gAlVk8MBtzXbzTP3BJyqbAfUOATGkyUtohh85fPXQYuzVlbExix3FZXTwFHNidGHY8C+ocscI7uDaYw==} + '@swc/core-linux-arm64-musl@1.6.6': + resolution: {integrity: sha512-a6fMbqzSAsS5KCxFJyg1mD5kwN3ZFO8qQLyJ75R/htZP/eCt05jrhmOI7h2n+1HjiG332jLnZ9S8lkVE5O8Nqw==} engines: {node: '>=10'} cpu: [arm64] os: [linux] @@ -4197,8 +4605,8 @@ packages: cpu: [x64] os: [linux] - '@swc/core-linux-x64-gnu@1.4.17': - resolution: {integrity: sha512-vRDFATL1oN5oZMImkwbgSHEkp8xG1ofEASBypze01W1Tqto8t+yo6gsp69wzCZBlxldsvPpvFZW55Jq0Rn+UnA==} + '@swc/core-linux-x64-gnu@1.6.6': + resolution: {integrity: sha512-hRGsUKNzzZle28YF0dYIpN0bt9PceR9LaVBq7x8+l9TAaDLFbgksSxcnU/ubTtsy+WsYSYGn+A83w3xWC0O8CQ==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -4209,8 +4617,8 @@ packages: cpu: [x64] os: [linux] - '@swc/core-linux-x64-musl@1.4.17': - resolution: {integrity: sha512-zQNPXAXn3nmPqv54JVEN8k2JMEcMTQ6veVuU0p5O+A7KscJq+AGle/7ZQXzpXSfUCXlLMX4wvd+rwfGhh3J4cw==} + '@swc/core-linux-x64-musl@1.6.6': + resolution: {integrity: sha512-NokIUtFxJDVv3LzGeEtYMTV3j2dnGKLac59luTeq36DQLZdJQawQIdTbzzWl2jE7lxxTZme+dhsVOH9LxE3ceg==} engines: {node: '>=10'} cpu: [x64] os: [linux] @@ -4221,8 +4629,8 @@ packages: cpu: [arm64] os: [win32] - '@swc/core-win32-arm64-msvc@1.4.17': - resolution: {integrity: sha512-z86n7EhOwyzxwm+DLE5NoLkxCTme2lq7QZlDjbQyfCxOt6isWz8rkW5QowTX8w9Rdmk34ncrjSLvnHOeLY17+w==} + '@swc/core-win32-arm64-msvc@1.6.6': + resolution: {integrity: sha512-lzYdI4qb4k1dFG26yv+9Jaq/bUMAhgs/2JsrLncGjLof86+uj74wKYCQnbzKAsq2hDtS5DqnHnl+//J+miZfGA==} engines: {node: '>=10'} cpu: [arm64] os: [win32] @@ -4233,8 +4641,8 @@ packages: cpu: [ia32] os: [win32] - '@swc/core-win32-ia32-msvc@1.4.17': - resolution: {integrity: sha512-JBwuSTJIgiJJX6wtr4wmXbfvOswHFj223AumUrK544QV69k60FJ9q2adPW9Csk+a8wm1hLxq4HKa2K334UHJ/g==} + '@swc/core-win32-ia32-msvc@1.6.6': + resolution: {integrity: sha512-bvl7FMaXIJQ76WZU0ER4+RyfKIMGb6S2MgRkBhJOOp0i7VFx4WLOnrmMzaeoPJaJSkityVKAftfNh7NBzTIydQ==} engines: {node: '>=10'} cpu: [ia32] os: [win32] @@ -4245,17 +4653,17 @@ packages: cpu: [x64] os: [win32] - '@swc/core-win32-x64-msvc@1.4.17': - resolution: {integrity: sha512-jFkOnGQamtVDBm3MF5Kq1lgW8vx4Rm1UvJWRUfg+0gx7Uc3Jp3QMFeMNw/rDNQYRDYPG3yunCC+2463ycd5+dg==} + '@swc/core-win32-x64-msvc@1.6.6': + resolution: {integrity: sha512-WAP0JoCTfgeYKgOeYJoJV4ZS0sQUmU3OwvXa2dYYtMLF7zsNqOiW4niU7QlThBHgUv/qNZm2p6ITEgh3w1cltw==} engines: {node: '>=10'} cpu: [x64] os: [win32] - '@swc/core@1.4.17': - resolution: {integrity: sha512-tq+mdWvodMBNBBZbwFIMTVGYHe9N7zvEaycVVjfvAx20k1XozHbHhRv+9pEVFJjwRxLdXmtvFZd3QZHRAOpoNQ==} + '@swc/core@1.6.6': + resolution: {integrity: sha512-sHfmIUPUXNrQTwFMVCY5V5Ena2GTOeaWjS2GFUpjLhAgVfP90OP67DWow7+cYrfFtqBdILHuWnjkTcd0+uPKlg==} engines: {node: '>=10'} peerDependencies: - '@swc/helpers': ^0.5.0 + '@swc/helpers': '*' peerDependenciesMeta: '@swc/helpers': optional: true @@ -4269,8 +4677,8 @@ packages: peerDependencies: '@swc/core': '*' - '@swc/types@0.1.5': - resolution: {integrity: sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==} + '@swc/types@0.1.9': + resolution: {integrity: sha512-qKnCno++jzcJ4lM4NTfYifm1EFSCeIfKiAHAfkENZAV5Kl9PjJIyd2yeeVv6c/2CckuLyv2NmRC5pv6pm2WQBg==} '@swc/wasm@1.2.130': resolution: {integrity: sha512-rNcJsBxS70+pv8YUWwf5fRlWX6JoY/HJc25HD/F8m6Kv7XhJdqPPMhyX6TKkUBPAG7TWlZYoxa+rHAjPy4Cj3Q==} @@ -4332,16 +4740,16 @@ packages: resolution: {integrity: sha512-EmCsnzdvawyk4b+4JKaLLuicHcJQRZtL1zSy9AWJLiiHTbDDseYgLxfaCEfLk8v2bUe7SBXwl3n3B7OjgvH11Q==} hasBin: true - '@testing-library/dom@9.3.3': - resolution: {integrity: sha512-fB0R+fa3AUqbLHWyxXa2kGVtf1Fe1ZZFr0Zp6AIbIAzXb2mKbEXl+PCQNUOaq5lbTab5tfctfXRNsWXxa2f7Aw==} - engines: {node: '>=14'} + '@testing-library/dom@10.1.0': + resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==} + engines: {node: '>=18'} '@testing-library/dom@9.3.4': resolution: {integrity: sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==} engines: {node: '>=14'} - '@testing-library/jest-dom@6.4.2': - resolution: {integrity: sha512-CzqH0AFymEMG48CpzXFriYYkOjk6ZGPCLMhW9e9jg3KMCn5OfJecF8GtGW7yGfR/IgCe3SX8BSwjdzI6BBbZLw==} + '@testing-library/jest-dom@6.4.5': + resolution: {integrity: sha512-AguB9yvTXmCnySBP1lWjfNNUwpbElsaQ567lt2VdGqAdHtpieLgjmcVyv1q7PMIvLbgpDdkWV5Ydv3FEejyp2A==} engines: {node: '>=14', npm: '>=6', yarn: '>=1'} peerDependencies: '@jest/globals': '>= 28' @@ -4367,8 +4775,8 @@ packages: peerDependencies: '@testing-library/dom': '>=7.21.4' - '@testing-library/vue@8.0.3': - resolution: {integrity: sha512-wSsbNlZ69ZFQgVlHMtc/ZC/g9BHO7MhyDrd4nHyfEubtMr3kToN/w4/BsSBknGIF8w9UmPbsgbIuq/CbdBHzCA==} + '@testing-library/vue@8.1.0': + resolution: {integrity: sha512-ls4RiHO1ta4mxqqajWRh8158uFObVrrtAPoxk7cIp4HrnQUj/ScKzqz53HxYpG3X6Zb7H2v+0eTGLSoy8HQ2nA==} engines: {node: '>=14'} peerDependencies: '@vue/compiler-sfc': '>= 3' @@ -4384,8 +4792,8 @@ packages: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} - '@tsd/typescript@5.3.3': - resolution: {integrity: sha512-CQlfzol0ldaU+ftWuG52vH29uRoKboLinLy84wS8TQOu+m+tWoaUfk4svL4ij2V8M5284KymJBlHUusKj6k34w==} + '@tsd/typescript@5.4.5': + resolution: {integrity: sha512-saiCxzHRhUrRxQV2JhH580aQUZiKQUXI38FcAcikcfOomAil4G4lxT0RfrrKywoAYP/rqAdYXYmNRLppcd+hQQ==} engines: {node: '>=14.17'} '@twemoji/parser@15.0.0': @@ -4430,12 +4838,6 @@ packages: '@types/cacheable-request@6.0.3': resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} - '@types/chai-subset@1.3.5': - resolution: {integrity: sha512-c2mPnw+xHtXDoHmdtcCXGwyLMiauiAyxWMzhGpqHC4nqI/Y5G2XhTampslK2rb59kpcuHon03UH8W6iYUzw88A==} - - '@types/chai@4.3.11': - resolution: {integrity: sha512-qQR1dr2rGIHYlJulmr8Ioq3De0Le9E4MJ5AiaeAETJJpndT1uUNHsGFK3L/UIu+rbkQSdj8J/w2bCsBZc/Y5fQ==} - '@types/color-convert@2.0.3': resolution: {integrity: sha512-2Q6wzrNiuEvYxVQqhh7sXM2mhIhvZR/Paq4FdsQkOMgWsCIkKvSGj8Le1/XalulrmgOzPMqNa0ix+ePY4hTrfg==} @@ -4466,6 +4868,9 @@ packages: '@types/detect-port@1.3.2': resolution: {integrity: sha512-xxgAGA2SAU4111QefXPSp5eGbDm/hW6zhvYl9IeEPZEry9F4d66QAHm5qpUXjb6IsevZV/7emAEx5MhP6O192g==} + '@types/diff@5.2.1': + resolution: {integrity: sha512-uxpcuwWJGhe2AR1g8hD9F5OYGCqjqWnBUQFD8gMZsDbv8oPHzxJF6iMO6n8Tk0AdzlxoaaoQhOYlIg/PukVU8g==} + '@types/disposable-email-domains@1.0.2': resolution: {integrity: sha512-SDKwyYTjk3y5aZBxxc38yRecpJPjsqn57STz1bNxYYlv4k11bBe7QB8w4llXDTmQXKT1mFvgGmJv+8Zdu3YmJw==} @@ -4529,8 +4934,8 @@ packages: '@types/http-errors@2.0.4': resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} - '@types/http-link-header@1.0.5': - resolution: {integrity: sha512-AxhIKR8UbyoqCTNp9rRepkktHuUOw3DjfOfDCaO9kwI8AYzjhxyrvZq4+mRw/2daD3hYDknrtSeV6SsPwmc71w==} + '@types/http-link-header@1.0.7': + resolution: {integrity: sha512-snm5oLckop0K3cTDAiBnZDy6ncx9DJ3mCRDvs42C884MbVYPP74Tiq2hFsSDRTyjK6RyDYDIulPiW23ge+g5Lw==} '@types/istanbul-lib-coverage@2.0.4': resolution: {integrity: sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g==} @@ -4547,8 +4952,8 @@ packages: '@types/js-yaml@4.0.9': resolution: {integrity: sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==} - '@types/jsdom@21.1.6': - resolution: {integrity: sha512-/7kkMsC+/kMs7gAYmmBR9P0vGTnOoLhQhyhQJSlXGI5bzTHp6xdo0TtKWQAsz6pmSAeVqKSbqeyP6hytqr9FDw==} + '@types/jsdom@21.1.7': + resolution: {integrity: sha512-yOriVnggzrnQ3a9OKOCxaVuSug3w3/SbOj5i7VwXWZEyUNl3bLF9V3MfxGbZKuwqJOQyRfqXyROBB1CoZLFWzA==} '@types/json-schema@7.0.12': resolution: {integrity: sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==} @@ -4559,8 +4964,8 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/jsonld@1.5.13': - resolution: {integrity: sha512-n7fUU6W4kSYK8VQlf/LsE9kddBHPKhODoVOjsZswmve+2qLwBy6naWxs/EiuSZN9NU0N06Ra01FR+j87C62T0A==} + '@types/jsonld@1.5.14': + resolution: {integrity: sha512-z4IRf5oRgjPTkazDDv94sjzI5iK3DrDEW7Y5Gk4VO4+ANymgtHtNaXWi93+BmiAoG3PB9QTv5DgSpKWGYVvysA==} '@types/jsrsasign@10.5.14': resolution: {integrity: sha512-lppSlfK6etu+cuKs40K4rg8As79PH6hzIB+v55zSqImbSH3SE6Fm8MBHCiI91cWlAP3Z4igtJK1VL3fSN09blQ==} @@ -4595,8 +5000,8 @@ packages: '@types/mdx@2.0.3': resolution: {integrity: sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==} - '@types/micromatch@4.0.7': - resolution: {integrity: sha512-C/FMQ8HJAZhTsDpl4wDKZdMeeW5USjgzOczUwTGbRc1ZopPgOhIEnxY2ZgUrsuyy4DwK1JVOJZKFakv3TbCKiA==} + '@types/micromatch@4.0.9': + resolution: {integrity: sha512-7V+8ncr22h4UoYRLnLXSpTxjQrNUXtWHGeMPRJt1nULXI57G9bIcpyrHlmrQ7QK24EyyuXvYcSSWAM8GA9nqCg==} '@types/mime-types@2.1.4': resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==} @@ -4628,8 +5033,8 @@ packages: '@types/node@20.11.5': resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} - '@types/node@20.12.7': - resolution: {integrity: sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==} + '@types/node@20.14.9': + resolution: {integrity: sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==} '@types/node@20.9.1': resolution: {integrity: sha512-HhmzZh5LSJNS5O8jQKpJ/3ZcrrlG6L70hpGqMIAoM9YVD0YBRNWYsfwcXq8VnSjlNpCpgLzMXdiPo+dxcvSmiA==} @@ -4646,8 +5051,8 @@ packages: '@types/oauth2orize@1.11.5': resolution: {integrity: sha512-C6hrRoh9hCnqis39OpeUZSwgw+TIzcV0CsxwJMGfQjTx4I1r+CLmuEPzoDJr5NRTfc7OMwHNLkQwrGFLKrJjMQ==} - '@types/oauth@0.9.4': - resolution: {integrity: sha512-qk9orhti499fq5XxKCCEbd0OzdPZuancneyse3KtR+vgMiHRbh+mn8M4G6t64ob/Fg+GZGpa565MF/2dKWY32A==} + '@types/oauth@0.9.5': + resolution: {integrity: sha512-+oQ3C2Zx6ambINOcdIARF5Z3Tu3x//HipE889/fqo3sgpQZbe9c6ExdQFtN6qlhpR7p83lTZfPJt0tCAW29dog==} '@types/offscreencanvas@2019.3.0': resolution: {integrity: sha512-esIJx9bQg+QYF0ra8GnvfianIY8qWB0GBx54PK5Eps6m+xTj86KLavHv6qDhzKcu5UUOgNfJ2pWaIIV7TRUd9Q==} @@ -4658,8 +5063,8 @@ packages: '@types/pg-pool@2.0.4': resolution: {integrity: sha512-qZAvkv1K3QbmHHFYSNRYPkRjOWRLBYrL4B9c+wG0GSVGBw0NtJwPcgx/DSddeDJvRGMHCEQ4VMEVfuJ/0gZ3XQ==} - '@types/pg@8.11.5': - resolution: {integrity: sha512-2xMjVviMxneZHDHX5p5S6tsRRs7TpDHeeK7kTTMe/kAC/mRRNjWHjZg0rkiY+e17jXSZV3zJYDxXV8Cy72/Vuw==} + '@types/pg@8.11.6': + resolution: {integrity: sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==} '@types/pg@8.6.1': resolution: {integrity: sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w==} @@ -4766,6 +5171,9 @@ packages: '@types/unist@3.0.2': resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + '@types/uuid@10.0.0': + resolution: {integrity: sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==} + '@types/uuid@9.0.8': resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==} @@ -4815,8 +5223,8 @@ packages: typescript: optional: true - '@typescript-eslint/eslint-plugin@7.7.1': - resolution: {integrity: sha512-KwfdWXJBOviaBVhxO3p5TJiLpNuh2iyXyjmWN0f1nU87pwyvfS0EmjC6ukQVYVFJd/K1+0NWGPDXiyEyQorn0Q==} + '@typescript-eslint/eslint-plugin@7.15.0': + resolution: {integrity: sha512-uiNHpyjZtFrLwLDpHnzaDlP3Tt6sGMqTCiqmxaN4n4RP0EfYZDODJyddiFDF44Hjwxr5xAcaYxVKm9QKQFJFLA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -4846,8 +5254,8 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.7.1': - resolution: {integrity: sha512-vmPzBOOtz48F6JAGVS/kZYk4EkXao6iGrD838sp1w3NQQC0W8ry/q641KU4PrG7AKNAf56NOcR8GOpH8l9FPCw==} + '@typescript-eslint/parser@7.15.0': + resolution: {integrity: sha512-k9fYuQNnypLFcqORNClRykkGOMOj+pV6V91R4GO/l1FDGwpqmSwoOQrOHo3cGaH63e+D3ZiCAOsuS/D2c99j/A==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -4864,8 +5272,8 @@ packages: resolution: {integrity: sha512-6TmN4OJiohHfoOdGZ3huuLhpiUgOGTpgXNUPJgeZOZR3DnIpdSgtt83RS35OYNNXxM4TScVlpVKC9jyQSETR1A==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/scope-manager@7.7.1': - resolution: {integrity: sha512-PytBif2SF+9SpEUKynYn5g1RHFddJUcyynGpztX3l/ik7KmZEv19WCMhUBkHXPU9es/VWGD3/zg3wg90+Dh2rA==} + '@typescript-eslint/scope-manager@7.15.0': + resolution: {integrity: sha512-Q/1yrF/XbxOTvttNVPihxh1b9fxamjEoz2Os/Pe38OHwxC24CyCqXxGTOdpb4lt6HYtqw9HetA/Rf6gDGaMPlw==} engines: {node: ^18.18.0 || >=20.0.0} '@typescript-eslint/type-utils@6.11.0': @@ -4888,8 +5296,8 @@ packages: typescript: optional: true - '@typescript-eslint/type-utils@7.7.1': - resolution: {integrity: sha512-ZksJLW3WF7o75zaBPScdW1Gbkwhd/lyeXGf1kQCxJaOeITscoSl0MjynVvCzuV5boUz/3fOI06Lz8La55mu29Q==} + '@typescript-eslint/type-utils@7.15.0': + resolution: {integrity: sha512-SkgriaeV6PDvpA6253PDVep0qCqgbO1IOBiycjnXsszNTVQe5flN5wR5jiczoEoDEnAqYFSFFc9al9BSGVltkg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -4906,8 +5314,8 @@ packages: resolution: {integrity: sha512-qTWjWieJ1tRJkxgZYXx6WUYtWlBc48YRxgY2JN1aGeVpkhmnopq+SUC8UEVGNXIvWH7XyuTjwALfG6bFEgCkQA==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/types@7.7.1': - resolution: {integrity: sha512-AmPmnGW1ZLTpWa+/2omPrPfR7BcbUU4oha5VIbSbS1a1Tv966bklvLNXxp3mrbc+P2j4MNOTfDffNsk4o0c6/w==} + '@typescript-eslint/types@7.15.0': + resolution: {integrity: sha512-aV1+B1+ySXbQH0pLK0rx66I3IkiZNidYobyfn0WFsdGhSXw+P3YOqeTq5GED458SfB24tg+ux3S+9g118hjlTw==} engines: {node: ^18.18.0 || >=20.0.0} '@typescript-eslint/typescript-estree@6.11.0': @@ -4928,8 +5336,8 @@ packages: typescript: optional: true - '@typescript-eslint/typescript-estree@7.7.1': - resolution: {integrity: sha512-CXe0JHCXru8Fa36dteXqmH2YxngKJjkQLjxzoj6LYwzZ7qZvgsLSc+eqItCrqIop8Vl2UKoAi0StVWu97FQZIQ==} + '@typescript-eslint/typescript-estree@7.15.0': + resolution: {integrity: sha512-gjyB/rHAopL/XxfmYThQbXbzRMGhZzGw6KpcMbfe8Q3nNQKStpxnUKeXb0KiN/fFDR42Z43szs6rY7eHk0zdGQ==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -4949,8 +5357,8 @@ packages: peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/utils@7.7.1': - resolution: {integrity: sha512-QUvBxPEaBXf41ZBbaidKICgVL8Hin0p6prQDu6bbetWo39BKbWJxRsErOzMNT1rXvTll+J7ChrbmMCXM9rsvOQ==} + '@typescript-eslint/utils@7.15.0': + resolution: {integrity: sha512-hfDMDqaqOqsUVGiEPSMLR/AjTSCsmJwjpKkYQRo1FNbmW4tBwBspYDwO9eh7sKSTwMQgBw9/T4DHudPaqshRWA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -4963,87 +5371,78 @@ packages: resolution: {integrity: sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==} engines: {node: ^16.0.0 || >=18.0.0} - '@typescript-eslint/visitor-keys@7.7.1': - resolution: {integrity: sha512-gBL3Eq25uADw1LQ9kVpf3hRM+DWzs0uZknHYK3hq4jcTPqVCClHGDnB6UUUV2SFeBeA4KWHWbbLqmbGcZ4FYbw==} + '@typescript-eslint/visitor-keys@7.15.0': + resolution: {integrity: sha512-Hqgy/ETgpt2L5xueA/zHHIl4fJI2O4XUE9l4+OIfbJIRSnTJb/QscncdqqZzofQegIJugRIF57OJea1khw2SDw==} engines: {node: ^18.18.0 || >=20.0.0} '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} - '@vitejs/plugin-vue@5.0.4': - resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==} + '@vitejs/plugin-vue@5.0.5': + resolution: {integrity: sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==} engines: {node: ^18.0.0 || >=20.0.0} peerDependencies: vite: ^5.0.0 vue: ^3.2.25 - '@vitest/coverage-v8@0.34.6': - resolution: {integrity: sha512-fivy/OK2d/EsJFoEoxHFEnNGTg+MmdZBAVK9Ka4qhXR2K3J0DS08vcGVwzDtXSuUMabLv4KtPcpSKkcMXFDViw==} + '@vitest/coverage-v8@1.6.0': + resolution: {integrity: sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==} peerDependencies: - vitest: '>=0.32.0 <1' + vitest: 1.6.0 - '@vitest/expect@0.34.6': - resolution: {integrity: sha512-QUzKpUQRc1qC7qdGo7rMK3AkETI7w18gTCUrsNnyjjJKYiuUB9+TQK3QnR1unhCnWRC0AbKv2omLGQDF/mIjOw==} + '@vitest/expect@1.6.0': + resolution: {integrity: sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==} - '@vitest/expect@1.3.1': - resolution: {integrity: sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==} + '@vitest/runner@1.6.0': + resolution: {integrity: sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==} - '@vitest/runner@0.34.6': - resolution: {integrity: sha512-1CUQgtJSLF47NnhN+F9X2ycxUP0kLHQ/JWvNHbeBfwW8CzEGgeskzNnHDyv1ieKTltuR6sdIHV+nmR6kPxQqzQ==} - - '@vitest/snapshot@0.34.6': - resolution: {integrity: sha512-B3OZqYn6k4VaN011D+ve+AA4whM4QkcwcrwaKwAbyyvS/NB1hCWjFIBQxAQQSQir9/RtyAAGuq+4RJmbn2dH4w==} - - '@vitest/spy@0.34.6': - resolution: {integrity: sha512-xaCvneSaeBw/cz8ySmF7ZwGvL0lBjfvqc1LpQ/vcdHEvpLn3Ff1vAvjw+CoGn0802l++5L/pxb7whwcWAw+DUQ==} - - '@vitest/spy@1.3.1': - resolution: {integrity: sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==} + '@vitest/snapshot@1.6.0': + resolution: {integrity: sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==} '@vitest/spy@1.6.0': resolution: {integrity: sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==} - '@vitest/utils@0.34.6': - resolution: {integrity: sha512-IG5aDD8S6zlvloDsnzHw0Ut5xczlF+kv2BOTo+iXfPr54Yhi5qbVOgGB1hZaVq4iJ4C/MZ2J0y15IlsV/ZcI0A==} - - '@vitest/utils@1.3.1': - resolution: {integrity: sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==} - '@vitest/utils@1.6.0': resolution: {integrity: sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==} '@volar/language-core@2.2.0': resolution: {integrity: sha512-a8WG9+4OdeNDW4ywABZIM6S6UN7em8uIlM/BZ2pWQUYrVmX+m8sj/X+QadvO+Li/t/LjAqbWJQtVgxdpEWLALQ==} + '@volar/language-core@2.4.0-alpha.11': + resolution: {integrity: sha512-DtftH0DtpksK1y+de/kLnu8CHcFQ7huKXi7cyxH9R0PbOOTSGXd31kijBeKNzyoXRp8dqGpu/7WhOlCWXQR62w==} + '@volar/source-map@2.2.0': resolution: {integrity: sha512-HQlPRlHOVqCCHK8wI76ZldHkEwKsjp7E6idUc36Ekni+KJDNrqgSqPvyHQixybXPHNU7CI9Uxd9/IkxO7LuNBw==} + '@volar/source-map@2.4.0-alpha.11': + resolution: {integrity: sha512-yyjmv8KUkTcxXzwme9qUMl6Szdji9JUQa8eadE4ib/spFXXZGq6QOX8cgSu5UQ0ooyBJFO1zdVH5otBJyZE3Ew==} + '@volar/typescript@2.2.0': resolution: {integrity: sha512-wC6l4zLiiCLxF+FGaHCbWlQYf4vMsnRxYhcI6WgvaNppOD6r1g+Ef1RKRJUApALWU46Yy/JDU/TbdV6w/X6Liw==} - '@vue/compiler-core@3.4.21': - resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==} + '@volar/typescript@2.4.0-alpha.11': + resolution: {integrity: sha512-N/v+wSddhtsNtfv2w0Bxj2QQWURN5budGzpyBTrlcXxz2dnvB0eAMqrEQbBi6rCOVHlRaXbh+wyTRdAcB/FHrg==} - '@vue/compiler-core@3.4.25': - resolution: {integrity: sha512-Y2pLLopaElgWnMNolgG8w3C5nNUVev80L7hdQ5iIKPtMJvhVpG0zhnBG/g3UajJmZdvW0fktyZTotEHD1Srhbg==} + '@vue/compiler-core@3.4.29': + resolution: {integrity: sha512-TFKiRkKKsRCKvg/jTSSKK7mYLJEQdUiUfykbG49rubC9SfDyvT2JrzTReopWlz2MxqeLyxh9UZhvxEIBgAhtrg==} - '@vue/compiler-core@3.4.26': - resolution: {integrity: sha512-N9Vil6Hvw7NaiyFUFBPXrAyETIGlQ8KcFMkyk6hW1Cl6NvoqvP+Y8p1Eqvx+UdqsnrnI9+HMUEJegzia3mhXmQ==} + '@vue/compiler-core@3.4.31': + resolution: {integrity: sha512-skOiodXWTV3DxfDhB4rOf3OGalpITLlgCeOwb+Y9GJpfQ8ErigdBUHomBzvG78JoVE8MJoQsb+qhZiHfKeNeEg==} - '@vue/compiler-dom@3.4.21': - resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==} + '@vue/compiler-dom@3.4.29': + resolution: {integrity: sha512-A6+iZ2fKIEGnfPJejdB7b1FlJzgiD+Y/sxxKwJWg1EbJu6ZPgzaPQQ51ESGNv0CP6jm6Z7/pO6Ia8Ze6IKrX7w==} - '@vue/compiler-dom@3.4.25': - resolution: {integrity: sha512-Ugz5DusW57+HjllAugLci19NsDK+VyjGvmbB2TXaTcSlQxwL++2PETHx/+Qv6qFwNLzSt7HKepPe4DcTE3pBWg==} + '@vue/compiler-dom@3.4.31': + resolution: {integrity: sha512-wK424WMXsG1IGMyDGyLqB+TbmEBFM78hIsOJ9QwUVLGrcSk0ak6zYty7Pj8ftm7nEtdU/DGQxAXp0/lM/2cEpQ==} - '@vue/compiler-dom@3.4.26': - resolution: {integrity: sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA==} + '@vue/compiler-sfc@3.4.31': + resolution: {integrity: sha512-einJxqEw8IIJxzmnxmJBuK2usI+lJonl53foq+9etB2HAzlPjAS/wa7r0uUpXw5ByX3/0uswVSrjNb17vJm1kQ==} - '@vue/compiler-sfc@3.4.26': - resolution: {integrity: sha512-It1dp+FAOCgluYSVYlDn5DtZBxk1NCiJJfu2mlQqa/b+k8GL6NG/3/zRbJnHdhV2VhxFghaDq5L4K+1dakW6cw==} + '@vue/compiler-ssr@3.4.29': + resolution: {integrity: sha512-rFbwCmxJ16tDp3N8XCx5xSQzjhidYjXllvEcqX/lopkoznlNPz3jyy0WGJCyhAaVQK677WWFt3YO/WUEkMMUFQ==} - '@vue/compiler-ssr@3.4.26': - resolution: {integrity: sha512-FNwLfk7LlEPRY/g+nw2VqiDKcnDTVdCfBREekF8X74cPLiWHUX6oldktf/Vx28yh4STNy7t+/yuLoMBBF7YDiQ==} + '@vue/compiler-ssr@3.4.31': + resolution: {integrity: sha512-RtefmITAje3fJ8FSg1gwgDhdKhZVntIVbwupdyZDSifZTRMiWxWehAOTCc8/KZDnBOcYQ4/9VWxsTbd3wT0hAA==} '@vue/devtools-api@6.6.1': resolution: {integrity: sha512-LgPscpE3Vs0x96PzSSB4IGVSZXZBZHpfxs+ZA1d+VEPwHdOXowy/Y2CsvCAIFrf+ssVU1pD1jidj505EpUnfbA==} @@ -5056,28 +5455,38 @@ packages: typescript: optional: true - '@vue/reactivity@3.4.26': - resolution: {integrity: sha512-E/ynEAu/pw0yotJeLdvZEsp5Olmxt+9/WqzvKff0gE67tw73gmbx6tRkiagE/eH0UCubzSlGRebCbidB1CpqZQ==} - - '@vue/runtime-core@3.4.26': - resolution: {integrity: sha512-AFJDLpZvhT4ujUgZSIL9pdNcO23qVFh7zWCsNdGQBw8ecLNxOOnPcK9wTTIYCmBJnuPHpukOwo62a2PPivihqw==} - - '@vue/runtime-dom@3.4.26': - resolution: {integrity: sha512-UftYA2hUXR2UOZD/Fc3IndZuCOOJgFxJsWOxDkhfVcwLbsfh2CdXE2tG4jWxBZuDAs9J9PzRTUFt1PgydEtItw==} - - '@vue/server-renderer@3.4.26': - resolution: {integrity: sha512-xoGAqSjYDPGAeRWxeoYwqJFD/gw7mpgzOvSxEmjWaFO2rE6qpbD1PC172YRpvKhrihkyHJkNDADFXTfCyVGhKw==} + '@vue/language-core@2.0.24': + resolution: {integrity: sha512-997YD6Lq/66LXr3ZOLNxDCmyn13z9NP8LU1UZn9hGCDWhzlbXAIP0hOgL3w3x4RKEaWTaaRtsHP9DzHvmduruQ==} peerDependencies: - vue: 3.4.26 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true - '@vue/shared@3.4.21': - resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==} + '@vue/reactivity@3.4.31': + resolution: {integrity: sha512-VGkTani8SOoVkZNds1PfJ/T1SlAIOf8E58PGAhIOUDYPC4GAmFA2u/E14TDAFcf3vVDKunc4QqCe/SHr8xC65Q==} - '@vue/shared@3.4.25': - resolution: {integrity: sha512-k0yappJ77g2+KNrIaF0FFnzwLvUBLUYr8VOwz+/6vLsmItFp51AcxLL7Ey3iPd7BIRyWPOcqUjMnm7OkahXllA==} + '@vue/runtime-core@3.4.31': + resolution: {integrity: sha512-LDkztxeUPazxG/p8c5JDDKPfkCDBkkiNLVNf7XZIUnJ+66GVGkP+TIh34+8LtPisZ+HMWl2zqhIw0xN5MwU1cw==} - '@vue/shared@3.4.26': - resolution: {integrity: sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==} + '@vue/runtime-dom@3.4.31': + resolution: {integrity: sha512-2Auws3mB7+lHhTFCg8E9ZWopA6Q6L455EcU7bzcQ4x6Dn4cCPuqj6S2oBZgN2a8vJRS/LSYYxwFFq2Hlx3Fsaw==} + + '@vue/server-renderer@3.4.29': + resolution: {integrity: sha512-HMLCmPI2j/k8PVkSBysrA2RxcxC5DgBiCdj7n7H2QtR8bQQPqKAe8qoaxLcInzouBmzwJ+J0x20ygN/B5mYBng==} + peerDependencies: + vue: 3.4.29 + + '@vue/server-renderer@3.4.31': + resolution: {integrity: sha512-D5BLbdvrlR9PE3by9GaUp1gQXlCNadIZytMIb8H2h3FMWJd4oUfkUTEH2wAr3qxoRz25uxbTcbqd3WKlm9EHQA==} + peerDependencies: + vue: 3.4.31 + + '@vue/shared@3.4.29': + resolution: {integrity: sha512-hQ2gAQcBO/CDpC82DCrinJNgOHI2v+FA7BDW4lMSPeBpQ7sRe2OLHWe5cph1s7D8DUQAwRt18dBDfJJ220APEA==} + + '@vue/shared@3.4.31': + resolution: {integrity: sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==} '@vue/test-utils@2.4.1': resolution: {integrity: sha512-VO8nragneNzUZUah6kOjiFmD/gwRjUauG9DROh6oaOeFwX1cZRUNHhdeogE8635cISigXFTtGLUQWx5KCb0xeg==} @@ -5151,8 +5560,8 @@ packages: engines: {node: '>=0.4.0'} hasBin: true - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.12.0: + resolution: {integrity: sha512-RTvkC4w+KNXrM39/lWCUaG0IbRkWdCv7W/IOW9oU6SawyxulvkQy5HQPVTKxEjczcUvapcrw3cFx/60VN/NRNw==} engines: {node: '>=0.4.0'} hasBin: true @@ -5205,12 +5614,26 @@ packages: ajv: optional: true + ajv-formats@3.0.1: + resolution: {integrity: sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + ajv@6.12.6: resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + ajv@8.12.0: + resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==} + ajv@8.13.0: resolution: {integrity: sha512-PRA911Blj99jR5RMeTunVbNXMF6Lp4vZXnk5GQjcnUWUTsrXtekg/pnmFFI2u/I36Y/2bITGS30GZCXei6uNkA==} + ajv@8.16.0: + resolution: {integrity: sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==} + ansi-colors@4.1.3: resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} engines: {node: '>=6'} @@ -5290,9 +5713,16 @@ packages: argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + aria-hidden@1.2.4: + resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} + engines: {node: '>=10'} + aria-query@5.1.3: resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} @@ -5368,6 +5798,9 @@ packages: async-mutex@0.5.0: resolution: {integrity: sha512-1A94B18jkJ3DYq284ohPxoXbfTA5HsQ7/Mf4DEhcyLx3Bz27Rh59iScbB6EPiP+B+joue6YCxcMXSbFC1tZKwA==} + async@0.2.10: + resolution: {integrity: sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==} + async@3.2.4: resolution: {integrity: sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==} @@ -5389,8 +5822,8 @@ packages: avvio@8.3.0: resolution: {integrity: sha512-VBVH0jubFr9LdFASy/vNtm5giTrnbVquWBhT0fyizuNK2rQ7e7ONU2plZQWUNqtE1EmxFEb+kbSkFRkstiaS9Q==} - aws-sdk-client-mock@3.0.1: - resolution: {integrity: sha512-9VAzJLl8mz99KP9HjOm/93d8vznRRUTpJooPBOunRdUAnVYopCe9xmMuu7eVemu8fQ+w6rP7o5bBK1kAFkB2KQ==} + aws-sdk-client-mock@4.0.1: + resolution: {integrity: sha512-yD2mmgy73Xce097G5hIpr1k7j50qzvJ49/+6osGZiCyk4m6cwhb+2x7kKFY1gEMwTzaS8+m8fXv9SB29SkRYyQ==} aws-sign2@0.7.0: resolution: {integrity: sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==} @@ -5426,18 +5859,18 @@ packages: resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} - babel-plugin-polyfill-corejs2@0.4.6: - resolution: {integrity: sha512-jhHiWVZIlnPbEUKSSNb9YoWcQGdlTLq7z1GHL4AjFxaoOUMuuEVJ+Y4pAaQUGOGk93YsVCKPbqbfw3m0SM6H8Q==} + babel-plugin-polyfill-corejs2@0.4.11: + resolution: {integrity: sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-corejs3@0.8.6: - resolution: {integrity: sha512-leDIc4l4tUgU7str5BWLS2h8q2N4Nf6lGZP6UrNDxdtfF2g69eJ5L0H7S8A5Ln/arfFAfHor5InAdZuIOwZdgQ==} + babel-plugin-polyfill-corejs3@0.10.4: + resolution: {integrity: sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 - babel-plugin-polyfill-regenerator@0.5.3: - resolution: {integrity: sha512-8sHeDOmXC8csczMrYEOf0UTNa4yE2SxV5JGeT/LP1n0OYVDUUFPxG9vdk2AlDlIit4t+Kf0xCtpgXPBwnn/9pw==} + babel-plugin-polyfill-regenerator@0.6.2: + resolution: {integrity: sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==} peerDependencies: '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 @@ -5510,10 +5943,6 @@ packages: bn.js@4.12.0: resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} - body-parser@1.20.1: - resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} - engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} - body-parser@1.20.2: resolution: {integrity: sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -5538,6 +5967,10 @@ packages: resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} engines: {node: '>=8'} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + broadcast-channel@7.0.0: resolution: {integrity: sha512-a2tW0Ia1pajcPBOGUF2jXlDnvE9d5/dg6BG9h60OmRUcZVr/veUrU8vEQFwwQIhwG3KVzYwSk3v2nRRGFgQDXQ==} @@ -5586,8 +6019,8 @@ packages: resolution: {integrity: sha512-kukuqc39WOHtdxtw4UScxF/WVnMFVSQVKhtx3AjZJzhd0RGZZldcrfSEbVsWWe6KNH253574cq5F+wpv0G9pJw==} engines: {node: '>=6.14.2'} - bullmq@5.7.8: - resolution: {integrity: sha512-F/Haeu6AVHkFrfeaU/kLOjhfrH6x3CaKAZlQQ+76fa8l3kfI9oaUHeFMW+1mYVz0NtYPF7PNTWFq4ylAHYcCgA==} + bullmq@5.8.3: + resolution: {integrity: sha512-RJgQu/vgSZqjOYrZ7F1UJsSAzveNx7FFpR3Tp/1TxOMXXN9TtZMSly5MT+vjzOhQX//3+YWNRbMWpC1mkqBc9w==} buraha@0.0.1: resolution: {integrity: sha512-G563A0mTbzknm2jDaNxfZuNKIdeArs8T+XQN6t+KbmgnOoevXSXhKDkyf8Md/36Jrx99ikwbCag37VGe3myExQ==} @@ -5624,6 +6057,10 @@ packages: resolution: {integrity: sha512-zkDT5WAF4hSSoUgyfg5tFIxz8XQK+25W/TLVojJTMKBaxevLBBtLxgqguAuVQB8PVW79FVjHcU+GJ9tVbDZ9mQ==} engines: {node: '>=14.16'} + cacheable-request@12.0.1: + resolution: {integrity: sha512-Yo9wGIQUaAfIbk+qY0X4cDQgCosecfBe3V9NSyeY4qPC2SAkbCS4Xj79VP8WOzitpJUZKc/wsRCYF5ariDIwkg==} + engines: {node: '>=18'} + cacheable-request@7.0.2: resolution: {integrity: sha512-pouW8/FmiPQbuGpkXQ9BAPv/Mo5xDGANgSNXzTzJ8DrKGuXOssM4wIQRjfanNRh3Yu5cfYPvcorqbhg2KIJtew==} engines: {node: '>=8'} @@ -5713,8 +6150,8 @@ packages: character-parser@2.2.0: resolution: {integrity: sha512-+UqJQjFEFaTAs3bNsF2j2kEN1baG/zghZbdqoYEDxGZtJo9LBzl1A+m0D4n3qKx8N2FNv8/Xp6yV9mQmBuptaw==} - chart.js@4.4.2: - resolution: {integrity: sha512-6GD7iKwFpP5kbSD4MeRRRlTnQvxfQREy36uEtm1hzHzcOqwWx0YEHuspuoNlslu+nciLIB7fjjsHkUv/FzFcOg==} + chart.js@4.4.3: + resolution: {integrity: sha512-qK1gkGSRYcJzqrrzdR6a+I0vQ4/R+SoODXyAjscQ/4mzuNzySaMCd+hyVxitSY1+L2fjPD1Gbn+ibNqRmwQeLw==} engines: {pnpm: '>=8'} chartjs-adapter-date-fns@3.0.0: @@ -5763,8 +6200,8 @@ packages: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} - chromatic@11.3.0: - resolution: {integrity: sha512-q1ZtJDJrjLGnz60ivpC16gmd7KFzcaA4eTb7gcytCqbaKqlHhCFr1xQmcUDsm14CK7JsqdkFU6S+JQdOd2ZNJg==} + chromatic@11.5.4: + resolution: {integrity: sha512-+J+CopeUSyGUIQJsU6X7CfvSmeVBs0j6LZ9AgF4+XTjI4pFmUiUXsTc00rH9x9W1jCppOaqDXv2kqJJXGDK3mA==} hasBin: true peerDependencies: '@chromatic-com/cypress': ^0.*.* || ^1.0.0 @@ -5799,10 +6236,6 @@ packages: engines: {node: '>=8.0.0', npm: '>=5.0.0'} hasBin: true - cli-spinners@2.7.0: - resolution: {integrity: sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==} - engines: {node: '>=6'} - cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} @@ -5982,8 +6415,8 @@ packages: resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==} engines: {node: '>= 0.6'} - core-js-compat@3.33.3: - resolution: {integrity: sha512-cNzGqFsh3Ot+529GIXacjTJ7kegdt5fPXxCBVS1G0iaZpuo/tBz399ymceLJveQhFFZ8qThHiP3fzuoQjKN2ow==} + core-js-compat@3.37.1: + resolution: {integrity: sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==} core-js@3.29.1: resolution: {integrity: sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==} @@ -6037,9 +6470,9 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - crypto-random-string@2.0.0: - resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} - engines: {node: '>=8'} + crypto-random-string@4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} css-declaration-sorter@7.2.0: resolution: {integrity: sha512-h70rUM+3PNFuaBDTLe8wF/cdWu+dOZmb7pJt8Z2sedYbAcQVQV/tEchueg3GWxwqS0cxtbxmaHEdkNACqcvsow==} @@ -6102,13 +6535,8 @@ packages: cwise-compiler@1.1.3: resolution: {integrity: sha512-WXlK/m+Di8DMMcCjcWr4i+XzcQra9eCdXIJrgh4TUgh0pIS/yJduLxS9JgefsHJ/YVLdgPtXm9r62W92MvanEQ==} - cypress@13.7.3: - resolution: {integrity: sha512-uoecY6FTCAuIEqLUYkTrxamDBjMHTYak/1O7jtgwboHiTnS1NaMOoR08KcTrbRZFCBvYOiS4tEkQRmsV+xcrag==} - engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} - hasBin: true - - cypress@13.8.1: - resolution: {integrity: sha512-Uk6ovhRbTg6FmXjeZW/TkbRM07KPtvM5gah1BIMp4Y2s+i/NMxgaLw0+PbYTOdw1+egE0FP3mWRiGcRkjjmhzA==} + cypress@13.13.0: + resolution: {integrity: sha512-ou/MQUDq4tcDJI2FsPaod2FZpex4kpIK43JJlcBgWrX8WX7R/05ZxGTuxedOuZBfxjZxja+fbijZGyxiLP6CFA==} engines: {node: ^16.0.0 || ^18.0.0 || >=20.0.0} hasBin: true @@ -6162,6 +6590,15 @@ packages: supports-color: optional: true + debug@4.3.5: + resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + decamelize-keys@1.1.1: resolution: {integrity: sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==} engines: {node: '>=0.10.0'} @@ -6235,10 +6672,6 @@ packages: defu@6.1.4: resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==} - del@6.1.1: - resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} - engines: {node: '>=10'} - delayed-stream@1.0.0: resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} engines: {node: '>=0.4.0'} @@ -6278,6 +6711,9 @@ packages: resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} engines: {node: '>=8'} + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + detect-package-manager@2.0.1: resolution: {integrity: sha512-j/lJHyoLlWi6G1LDdLgvUtz60Zo5GEj+sVYtTVXnYLDPuzgC3llMxonXym9zIwhhUII8vjdw0LXxavpLqTbl1A==} engines: {node: '>=12'} @@ -6300,6 +6736,10 @@ packages: resolution: {integrity: sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==} engines: {node: '>=0.3.1'} + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + dijkstrajs@1.0.2: resolution: {integrity: sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg==} @@ -6371,8 +6811,8 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - ejs@3.1.9: - resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} hasBin: true @@ -6438,8 +6878,8 @@ packages: es-get-iterator@1.1.3: resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} - es-module-lexer@0.9.3: - resolution: {integrity: sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==} + es-module-lexer@1.5.4: + resolution: {integrity: sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==} es-set-tostringtag@2.0.1: resolution: {integrity: sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==} @@ -6476,11 +6916,16 @@ packages: engines: {node: '>=12'} hasBin: true - esbuild@0.20.2: - resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==} + esbuild@0.21.5: + resolution: {integrity: sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==} engines: {node: '>=12'} hasBin: true + esbuild@0.22.0: + resolution: {integrity: sha512-zNYA6bFZsVnsU481FnGAQjLDW0Pl/8BGG7EvAp15RzUvGC+ME7hf1q7LvIfStEQBz/iEHuBJCYcOwPmNCf1Tlw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.1.1: resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} engines: {node: '>=6'} @@ -6550,8 +6995,8 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-vue@9.25.0: - resolution: {integrity: sha512-tDWlx14bVe6Bs+Nnh3IGrD+hb11kf2nukfm6jLsmJIhmiRQ1SUaksvwY9U5MvPB0pcrg0QK0xapQkfITs3RKOA==} + eslint-plugin-vue@9.26.0: + resolution: {integrity: sha512-eTvlxXgd4ijE1cdur850G6KalZqk65k1JKoOI2d1kT3hr8sPD07j1q98FRFdNnpxBELGPWxZmInxeHGF/GxtqQ==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: ^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 @@ -6563,19 +7008,26 @@ packages: resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-scope@8.0.1: + resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + eslint-visitor-keys@3.4.3: resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - eslint@8.53.0: - resolution: {integrity: sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + eslint-visitor-keys@4.0.0: + resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint@9.6.0: + resolution: {integrity: sha512-ElQkdLMEEqQNM9Njff+2Y4q2afHk7JpkPvrd7Xh7xefwgQynqPxwf55J7di9+MEibWUGdNjFF9ITG9Pck5M84w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true - eslint@8.57.0: - resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==} - engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - hasBin: true + espree@10.1.0: + resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} @@ -6590,6 +7042,10 @@ packages: resolution: {integrity: sha512-JVSoLdTlTDkmjFmab7H/9SL9qGSyjElT3myyKp7krqjVFQCDLmj1QFaCLRFBszBKI0XVZaiiXvuPIX3ZwHe1Ng==} engines: {node: '>=0.10'} + esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -6652,6 +7108,10 @@ packages: resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} engines: {node: '>=16.17'} + execa@9.2.0: + resolution: {integrity: sha512-vpOyYg7UAVKLAWWtRS2gAdgkT7oJbCn0me3gmUmxZih4kd3MF/oo8kNTBTIbkO3yuuF5uB4ZCZfn8BOolITYhg==} + engines: {node: ^18.19.0 || >=20.5.0} + executable@4.1.1: resolution: {integrity: sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==} engines: {node: '>=4'} @@ -6667,10 +7127,6 @@ packages: exponential-backoff@3.1.1: resolution: {integrity: sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==} - express@4.18.2: - resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} - engines: {node: '>= 0.10.0'} - express@4.19.2: resolution: {integrity: sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==} engines: {node: '>= 0.10.0'} @@ -6744,11 +7200,8 @@ packages: resolution: {integrity: sha512-F4o8ZIMVx4YoxGfwrZys6wyjl40gF3Yv6AWWRy62ozFAyZBSS831/uyyCAqKYw3tR73g180ryG98yih6To1PUQ==} engines: {node: '>= 10'} - fastify@4.26.2: - resolution: {integrity: sha512-90pjTuPGrfVKtdpLeLzND5nyC4woXZN5VadiNQCicj/iJU4viNHKhsAnb7jmv1vu2IzkLXyBiCzdWuzeXgQ5Ug==} - - fastq@1.15.0: - resolution: {integrity: sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==} + fastify@4.28.1: + resolution: {integrity: sha512-kFWUtpNr4i7t5vY2EJPCN2KgMVpuqfU4NjnJNCgiNB900oiDeYqaNDRcAfeBbOF5hGixixxcKnOU4KN9z6QncQ==} fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} @@ -6774,9 +7227,13 @@ packages: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} - file-entry-cache@6.0.1: - resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} - engines: {node: ^10.12.0 || >=12.0.0} + figures@6.1.0: + resolution: {integrity: sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg==} + engines: {node: '>=18'} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} file-system-cache@2.3.0: resolution: {integrity: sha512-l4DMNdsIPsVnKrgEXbJwDJsA5mB8rGwHYERMgqQx/xAUtChPJMre1bXBzDEqqVbWv9AIbFezXMxeEkZDSrXUOQ==} @@ -6804,6 +7261,10 @@ packages: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + finalhandler@1.2.0: resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} engines: {node: '>= 0.8'} @@ -6843,20 +7304,20 @@ packages: resolution: {integrity: sha512-MdYSsbdCaIRjzo5edthZtWmEZVMfr1qrtYZUHIdO3swCE+CoZA8S5l0s4jDsYlTa9ZiXv0pTgpzE7s4N8NeUOA==} engines: {node: '>=18'} - flat-cache@3.0.4: - resolution: {integrity: sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==} - engines: {node: ^10.12.0 || >=12.0.0} + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} - flatted@3.2.7: - resolution: {integrity: sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==} + flatted@3.3.1: + resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} flow-parser@0.202.0: resolution: {integrity: sha512-ZiXxSIXK3zPmY3zrzCofFonM2T+/3Jz5QZKJyPVtUERQEJUnYkXBQ+0H3FzyqiyJs+VXqb/UNU6/K6sziVYdxw==} engines: {node: '>=0.4.0'} - fluent-ffmpeg@2.1.2: - resolution: {integrity: sha512-IZTB4kq5GK0DPp7sGQ0q/BWurGHffRtQQwVkiqDgeO6wYJLLV5ZhgNOQ65loZxxuPMKZKZcICCUnaGtlxBiR0Q==} - engines: {node: '>=0.8.0'} + fluent-ffmpeg@2.1.3: + resolution: {integrity: sha512-Be3narBNt2s6bsaqP6Jzq91heDgOEaDCJAXcE3qcma/EJBSy5FB4cvO31XBInuAuKBx8Kptf8dkhjK0IOru39Q==} + engines: {node: '>=18'} follow-redirects@1.15.2: resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==} @@ -6978,6 +7439,10 @@ packages: get-intrinsic@1.2.1: resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + get-npm-tarball-url@2.0.3: resolution: {integrity: sha512-R/PW6RqyaBQNWYaSyfrh54/qtcnOp22FHCCiRhSSZj0FP3KQWCsxxt0DzIdVTbwTqe9CtQfvl/FPD4UIPt4pqw==} engines: {node: '>=12.17'} @@ -7005,6 +7470,10 @@ packages: resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} engines: {node: '>=16'} + get-stream@9.0.1: + resolution: {integrity: sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA==} + engines: {node: '>=18'} + get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -7056,12 +7525,19 @@ packages: engines: {node: '>=16 || 14 >=14.17'} hasBin: true + glob@10.4.2: + resolution: {integrity: sha512-GwMlUF6PkPo3Gk21UxkCohOv0PLcIXVtKyLlpEI28R/cO/4eNOdmLk3CMW1wROV/WR/EsZOWAfBbBOqYvs88/w==} + engines: {node: '>=16 || 14 >=14.18'} + hasBin: true + glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported global-dirs@3.0.1: resolution: {integrity: sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==} @@ -7071,14 +7547,18 @@ packages: resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} engines: {node: '>=4'} - globals@13.19.0: - resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==} - engines: {node: '>=8'} - globals@13.24.0: resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} engines: {node: '>=8'} + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.7.0: + resolution: {integrity: sha512-ivatRXWwKC6ImcdKO7dOwXuXR5XFrdwo45qFwD7D0qOkEPzzJdLXC3BHceBdyrPOD3p1suPaWi4Y4NMm2D++AQ==} + engines: {node: '>=18'} + globalthis@1.0.3: resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} engines: {node: '>= 0.4'} @@ -7087,6 +7567,10 @@ packages: resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} engines: {node: '>=10'} + globby@14.0.1: + resolution: {integrity: sha512-jOMLD2Z7MAhyG8aJpNOpmziMOP4rPLcc95oQPKXBazW82z+CEgPFBQvEpRUa1KeIMUJo4Wsm+q6uzO/Q/4BksQ==} + engines: {node: '>=18'} + google-protobuf@3.21.2: resolution: {integrity: sha512-3MSOYFO5U9mPGikIYCzK0SaThypfGgS6bHqrUGXG3DPHCrb+txNqeEcns1W0lkGfk0rCyNXm7xB9rMxnCiZOoA==} @@ -7101,8 +7585,8 @@ packages: resolution: {integrity: sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ==} engines: {node: '>=14.16'} - got@14.2.1: - resolution: {integrity: sha512-KOaPMremmsvx6l9BLC04LYE6ZFW4x7e4HkTe3LwBmtuYYQwpeS4XKqzhubTIkaQ1Nr+eXxeori0zuwupXMovBQ==} + got@14.4.1: + resolution: {integrity: sha512-IvDJbJBUeexX74xNQuMIVgCRRuNOm5wuK+OC3Dc2pnSoh1AOmgc7JVj7WC+cJ4u0aPcO9KZ2frTXcqK4W/5qTQ==} engines: {node: '>=20'} graceful-fs@4.2.11: @@ -7260,6 +7744,10 @@ packages: resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} engines: {node: '>= 14'} + http-proxy-agent@7.0.2: + resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} + engines: {node: '>= 14'} + http-signature@1.2.0: resolution: {integrity: sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==} engines: {node: '>=0.8', npm: '>=1.3.7'} @@ -7292,6 +7780,10 @@ packages: resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} engines: {node: '>= 14'} + https-proxy-agent@7.0.4: + resolution: {integrity: sha512-wlwpilI7YdjSkWaQ/7omYBMTliDcmCN8OLihO6I9B86g06lMyAoqgoDpV0XqoaPOKj+0DIdAvnsWfyAAhmimcg==} + engines: {node: '>= 14'} + human-signals@1.1.1: resolution: {integrity: sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==} engines: {node: '>=8.12.0'} @@ -7308,6 +7800,10 @@ packages: resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} engines: {node: '>=16.17.0'} + human-signals@7.0.0: + resolution: {integrity: sha512-74kytxOUSvNbjrT9KisAbaTZ/eJwD/LrbM/kh5j0IhPuJzwuA19dWvniFGwBzN9rVjg+O/e+F310PjObDXS+9Q==} + engines: {node: '>=18.18.0'} + iconv-lite@0.4.24: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} @@ -7347,8 +7843,8 @@ packages: import-in-the-middle@1.4.2: resolution: {integrity: sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw==} - import-in-the-middle@1.7.4: - resolution: {integrity: sha512-Lk+qzWmiQuRPPulGQeK5qq0v32k2bHnWrRPFgqyvhw7Kkov5L6MOLOIU3pcWeujc9W4q54Cp3Q2WV16eQkc7Bg==} + import-in-the-middle@1.8.1: + resolution: {integrity: sha512-yhRwoHtiLGvmSozNOALgjRPFI6uYsds60EoMqqnXyyv+JOIW/BrrLejuTGBt+bq0T5tLzOHrN0T7xYTm4Qt/ng==} import-lazy@4.0.0: resolution: {integrity: sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==} @@ -7398,6 +7894,9 @@ packages: intersection-observer@0.12.2: resolution: {integrity: sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==} + invariant@2.2.4: + resolution: {integrity: sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==} + ioredis@5.4.1: resolution: {integrity: sha512-2YZsvl7jopIa1gaePkeMtd9rAcSjOOjPtpcLlOeusyO+XH2SK5ZcT+UCrElPP+WVIInh2TzeI4XW9ENaSLVVHA==} engines: {node: '>=12.22.0'} @@ -7405,13 +7904,13 @@ packages: iota-array@1.0.0: resolution: {integrity: sha512-pZ2xT+LOHckCatGQ3DcG/a+QuEqvoxqkiL7tvE8nn3uuu+f6i1TtpB5/FtWFbxUuVr5PZCx8KskuGatbJDXOWA==} - ip-address@7.1.0: - resolution: {integrity: sha512-V9pWC/VJf2lsXqP7IWJ+pe3P1/HCYGBMZrrnT62niLGjAfCbeiwXMUxaeHvnVlz19O27pvXP4azs+Pj/A0x+SQ==} - engines: {node: '>= 10'} + ip-address@9.0.5: + resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} + engines: {node: '>= 12'} - ip-cidr@3.1.0: - resolution: {integrity: sha512-HUCn4snshEX1P8cja/IyU3qk8FVDW8T5zZcegDFbu4w7NojmAhk5NcOgj3M8+0fmumo1afJTPDtJlzsxLdOjtg==} - engines: {node: '>=10.0.0'} + ip-cidr@4.0.1: + resolution: {integrity: sha512-V5Nce94SVJ7NtyT/UKUeTM7sY3V7TEk48hURhtBgTiGduOa5t6p9Hd+zBOGvr4Gu7iWPxFVYNl017p0akQA84w==} + engines: {node: '>=16.14.0'} ip-regex@4.3.0: resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} @@ -7553,10 +8052,6 @@ packages: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} - is-path-cwd@2.2.0: - resolution: {integrity: sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==} - engines: {node: '>=6'} - is-path-inside@3.0.3: resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} engines: {node: '>=8'} @@ -7605,12 +8100,16 @@ packages: resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + is-stream@4.0.1: + resolution: {integrity: sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A==} + engines: {node: '>=18'} + is-string@1.0.7: resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} engines: {node: '>= 0.4'} - is-svg@5.0.0: - resolution: {integrity: sha512-sRl7J0oX9yUNamSdc8cwgzh9KBLnQXNzGmW0RVHwg/jEYjGNYHC6UvnYD8+hAeut9WwxRvhG9biK7g/wDGxcMw==} + is-svg@5.0.1: + resolution: {integrity: sha512-mLYxDsfisQWdS4+gSblAwhATDoNMS/tx8G7BKA+aBIf7F0m1iUwMvuKAo6mW4WMleQAEE50I1Zqef9yMMfHk3w==} engines: {node: '>=14.16'} is-symbol@1.0.4: @@ -7628,6 +8127,10 @@ packages: resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} engines: {node: '>=10'} + is-unicode-supported@2.0.0: + resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} + engines: {node: '>=18'} + is-weakmap@2.0.1: resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} @@ -7684,6 +8187,10 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} + istanbul-lib-source-maps@5.0.4: + resolution: {integrity: sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==} + engines: {node: '>=10'} + istanbul-reports@3.1.6: resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} engines: {node: '>=8'} @@ -7696,6 +8203,10 @@ packages: resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} engines: {node: '>=14'} + jackspeak@3.4.0: + resolution: {integrity: sha512-JVYhQnN59LVPFCEcVa2C3CrEKYacvjRfqIQl+h8oi91aLYQVWRYbxjPcv1bUiUy/kLmQaANrYfNMCO3kuEDHfw==} + engines: {node: '>=14'} + jake@10.8.5: resolution: {integrity: sha512-sVpxYeuAhWt0OTWITwT98oyV0GsXyMlXCF+3L1SuafBVUIr/uILGRB+NqwkzhgXKvoJpDIpQvqkUALgdmQsQxw==} engines: {node: '>=10'} @@ -7856,6 +8367,9 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.0: + resolution: {integrity: sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==} + js-yaml@3.14.1: resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} hasBin: true @@ -7883,8 +8397,8 @@ packages: '@babel/preset-env': optional: true - jsdom@24.0.0: - resolution: {integrity: sha512-UDS2NayCvmXSXVP6mpTj+73JnNQadZlr9N68189xib2tx5Mls7swlTNao26IoHv46BZJFvXygyRtyXd1feAk1A==} + jsdom@24.1.0: + resolution: {integrity: sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==} engines: {node: '>=18'} peerDependencies: canvas: ^2.11.2 @@ -7966,9 +8480,6 @@ packages: jsrsasign@11.1.0: resolution: {integrity: sha512-Ov74K9GihaK9/9WncTe1mPmvrO7Py665TUfUKvraXBpu+xcTWitrtuOwcjf4KMU9maPaYn0OuaWy0HOzy/GBXg==} - jssha@3.3.1: - resolution: {integrity: sha512-VCMZj12FCFMQYcFLPRm/0lOBbLi8uM2BhXPTqw3U4YAfs4AZfiApOoBLoN8cQE60Z50m1MYMTQVCfgF/KaCVhQ==} - jstransformer@1.0.0: resolution: {integrity: sha512-C9YK3Rf8q6VAPDCCU9fnqo3mAfOH6vUGnMcP4AQAYIEpWtfGLpwOTmZ+igtdK5y+VvI2n3CyYSzy4Qh34eq24A==} @@ -8045,8 +8556,8 @@ packages: enquirer: optional: true - local-pkg@0.4.3: - resolution: {integrity: sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==} + local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} engines: {node: '>=14'} locate-path@3.0.0: @@ -8073,9 +8584,6 @@ packages: lodash.isarguments@3.1.0: resolution: {integrity: sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg==} - lodash.isequal@4.5.0: - resolution: {integrity: sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==} - lodash.memoize@4.1.2: resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} @@ -8157,9 +8665,8 @@ packages: magic-string@0.30.10: resolution: {integrity: sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==} - magic-string@0.30.7: - resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==} - engines: {node: '>=12'} + magicast@0.3.4: + resolution: {integrity: sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==} mailcheck@1.1.1: resolution: {integrity: sha512-3WjL8+ZDouZwKlyJBMp/4LeziLFXgleOdsYu87piGcMLqhBzCsy2QFdbtAwv757TFC/rtqd738fgJw1tFQCSgA==} @@ -8252,8 +8759,8 @@ packages: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} - meilisearch@0.38.0: - resolution: {integrity: sha512-bHaq8nYxSKw9/Qslq1Zes5g9tHgFkxy/I9o8942wv2PqlNOT0CzptIkh/x98N52GikoSZOXSQkgt6oMjtf5uZw==} + meilisearch@0.41.0: + resolution: {integrity: sha512-5KcGLxEXD7E+uNO7R68rCbGSHgCqeM3Q3RFFLSsN7ZrIgr8HPDXVAIlP4LHggAZfk0FkSzo8VSXifHCwa2k80g==} memoizerific@1.11.3: resolution: {integrity: sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==} @@ -8367,8 +8874,8 @@ packages: micromark@4.0.0: resolution: {integrity: sha512-o/sd0nMof8kYff+TqcDx3VSrgBTcZpSvYcAHIfHhv5VAuNmisCxjhx6YmxS8PFEpb9z5WKWKPdzf0jM23ro3RQ==} - micromatch@4.0.5: - resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + micromatch@4.0.7: + resolution: {integrity: sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==} engines: {node: '>=8.6'} mime-db@1.52.0: @@ -8480,6 +8987,10 @@ packages: resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} engines: {node: '>=16 || 14 >=14.17'} + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + minizlib@1.3.3: resolution: {integrity: sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q==} @@ -8541,13 +9052,13 @@ packages: msgpackr@1.10.1: resolution: {integrity: sha512-r5VRLv9qouXuLiIBrLpl2d5ZvPt8svdQTl5/vMvE4nzDMyEX4sgW5yWhuBBj5UmgwOTWj8CIdSXn5sAfsHAWIQ==} - msw-storybook-addon@2.0.1: - resolution: {integrity: sha512-pZ3JDQ9HkGQ3XDMIHvMcDSI4Vbp/LHmwHwiZu+pHLzimtI1vhAo1swjFEDAEJuBcozljYvREEC4sS7rQHPNtWg==} + msw-storybook-addon@2.0.2: + resolution: {integrity: sha512-sdw++X+AoUbaG2ku493ViVqCA/LfqnybXsKXyPUrF3ZS/x8BqGBnkBLmT/0SHCC5zIO3Vfm5zlclAxnhqOOikQ==} peerDependencies: msw: ^2.0.0 - msw@2.2.14: - resolution: {integrity: sha512-64i8rNCa1xzDK8ZYsTrVMli05D687jty8+Th+PU5VTbJ2/4P7fkQFVyDQ6ZFT5FrNR8z2BHhbY47fKNvfHrumA==} + msw@2.3.1: + resolution: {integrity: sha512-ocgvBCLn/5l3jpl1lssIb3cniuACJLoOfZu01e3n5dbJrpA5PeeWn28jCLgQDNt6d7QT8tF2fYRzm9JoEHtiig==} engines: {node: '>=18'} hasBin: true peerDependencies: @@ -8701,8 +9212,8 @@ packages: node-releases@2.0.14: resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} - nodemailer@6.9.13: - resolution: {integrity: sha512-7o38Yogx6krdoBf3jCAqnIN4oSQFx+fMa0I7dK1D+me9kBxx12D+/33wSb+fhOCtIxvYJ+4x4IMEhmhCKfAiOA==} + nodemailer@6.9.14: + resolution: {integrity: sha512-Dobp/ebDKBvz91sbtRKhcznLThrKxKt97GI2FAlAyy+fk19j73Uz3sBXolVtmcXjaorivqsbbbjDY+Jkt4/bQA==} engines: {node: '>=6.0.0'} nodemon@3.0.2: @@ -8710,8 +9221,8 @@ packages: engines: {node: '>=10'} hasBin: true - nodemon@3.1.0: - resolution: {integrity: sha512-xqlktYlDMCepBJd43ZQhjWwMw2obW/JRvkrLxq5RCNcuDDX1DbcPT+qT1IlIIdf+DhnWs90JpTMe+Y5KxOchvA==} + nodemon@3.1.4: + resolution: {integrity: sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==} engines: {node: '>=10'} hasBin: true @@ -8757,6 +9268,10 @@ packages: resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} engines: {node: '>=14.16'} + normalize-url@8.0.1: + resolution: {integrity: sha512-IO9QvjUMWxPQQhs60oOu10CRkWCiZzSUkzbXGGV9pviYl1fXYcvkzQ5jV9z8Y6un8ARoVRl4EtC6v6jNqbaJ/w==} + engines: {node: '>=14.16'} + npm-run-path@2.0.2: resolution: {integrity: sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==} engines: {node: '>=4'} @@ -8769,6 +9284,10 @@ packages: resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + npm-run-path@5.3.0: + resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + npmlog@5.0.1: resolution: {integrity: sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==} @@ -8780,8 +9299,8 @@ packages: nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} - nwsapi@2.2.9: - resolution: {integrity: sha512-2f3F0SEEer8bBu0dsNCFF50N0cTThV1nWFYcEYFZttdW0lDAoybv9cQoK7X7/68Z89S7FoRrVjP1LPX4XRf9vg==} + nwsapi@2.2.10: + resolution: {integrity: sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==} oauth-sign@0.9.0: resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} @@ -8894,8 +9413,8 @@ packages: ospath@1.2.2: resolution: {integrity: sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==} - otpauth@9.2.3: - resolution: {integrity: sha512-oAG55Ch4MBL5Jdg+RXfKiRCZ2lCwa/UIQKsmSfYbGGLSI4dErY1HPZv0JGPPESIYGyDO3s9iJqM4HU/1IppMoQ==} + otpauth@9.3.1: + resolution: {integrity: sha512-E6d2tMxPofHNk4sRFp+kqW7vQ+WJGO9VLI2N/W00DnI+ThskU12Qa10kyNSGklrzhN5c+wRUsN4GijVgCU2N9w==} outvariant@1.4.2: resolution: {integrity: sha512-Ou3dJ6bA/UJ5GVHxah4LnqDwZRwAmWxrG3wtrHrbGnP4RnLCtA64A4F+ae7Y8ww660JaddSoArUR5HjipWSHAQ==} @@ -8924,9 +9443,9 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} - p-limit@4.0.0: - resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} p-locate@3.0.0: resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} @@ -8956,6 +9475,9 @@ packages: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} + package-json-from-dist@1.0.0: + resolution: {integrity: sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==} + pako@0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} @@ -8970,6 +9492,10 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parse-ms@4.0.0: + resolution: {integrity: sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw==} + engines: {node: '>=18'} + parse-srcset@1.0.2: resolution: {integrity: sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==} @@ -9030,6 +9556,10 @@ packages: resolution: {integrity: sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==} engines: {node: '>=16 || 14 >=14.17'} + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@0.1.7: resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} @@ -9046,6 +9576,10 @@ packages: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + path-type@5.0.0: + resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} + engines: {node: '>=12'} + pathe@1.1.2: resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==} @@ -9087,9 +9621,6 @@ packages: peerDependencies: pg: '>=8.0' - pg-protocol@1.6.0: - resolution: {integrity: sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==} - pg-protocol@1.6.1: resolution: {integrity: sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==} @@ -9101,8 +9632,8 @@ packages: resolution: {integrity: sha512-hRCSDuLII9/LE3smys1hRHcu5QGcLs9ggT7I/TCs0IE+2Eesxi9+9RWAAwZ0yaGjxoWICF/YHLOEjydGujoJ+g==} engines: {node: '>=10'} - pg@8.11.5: - resolution: {integrity: sha512-jqgNHSKL5cbDjFlHyYsCXmQDrfIX/3RsNwYqpd4N0Kt8niLuNoRNH+aazv6cOd43gPh9Y4DjQCtb+X0MH0Hvnw==} + pg@8.12.0: + resolution: {integrity: sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==} engines: {node: '>= 8.0.0'} peerDependencies: pg-native: '>=3.0.1' @@ -9113,8 +9644,8 @@ packages: pgpass@1.0.5: resolution: {integrity: sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==} - photoswipe@5.4.3: - resolution: {integrity: sha512-9UC6oJBK4oXFZ5HcdlcvGkfEHsVrmE4csUdCQhEjHYb3PvPLO3PG7UhnPuOgjxwmhq5s17Un5NUdum01LgBDng==} + photoswipe@5.4.4: + resolution: {integrity: sha512-WNFHoKrkZNnvFFhbHL93WDkW3ifwVOXSW3w1UuZZelSmgXpIGiZSNlZJq37rR8YejqME2rHs9EhH9ZvlvFH2NA==} engines: {node: '>= 0.12.0'} picocolors@1.0.0: @@ -9136,14 +9667,14 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} - pino-abstract-transport@1.1.0: - resolution: {integrity: sha512-lsleG3/2a/JIWUtf9Q5gUNErBqwIu1tUKTT3dUzaf5DySw9ra1wcqKjJjLX1VTY64Wk1eEOYsVGSaGfCK85ekA==} + pino-abstract-transport@1.2.0: + resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} - pino-std-serializers@6.1.0: - resolution: {integrity: sha512-KO0m2f1HkrPe9S0ldjx7za9BJjeHqBku5Ch8JyxETxT8dEFGz1PwgrHaOQupVYitpzbFSYm7nnljxD8dik2c+g==} + pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} - pino@8.17.0: - resolution: {integrity: sha512-ey+Mku+PVPhvxglLXMg1l1zQMwSHuNrKC3MD40EDZbkckJmmuY7DYZLIOwwjZ8ix/Nvhe9dZt5H99cgkot9bAw==} + pino@9.2.0: + resolution: {integrity: sha512-g3/hpwfujK5a4oVbaefoJxezLzsDgLcNJeITvC6yrfwYeT9la+edCK42j5QpEQSQCZgTKapXvnQIdgZwvRaZug==} hasBin: true pirates@4.0.5: @@ -9411,8 +9942,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier@3.2.5: - resolution: {integrity: sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A==} + prettier@3.3.2: + resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==} engines: {node: '>=14'} hasBin: true @@ -9432,6 +9963,10 @@ packages: resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==} engines: {node: '>= 0.8'} + pretty-ms@9.0.0: + resolution: {integrity: sha512-E9e9HJ9R9NasGOgPaPE8VMeiPKAyWR5jcFpNnwIejslIhWqdqOrb2wShBsncMPUb+BcCd2OPYfh7p2W6oemTng==} + engines: {node: '>=18'} + private-ip@2.3.3: resolution: {integrity: sha512-5zyFfekIVUOTVbL92hc8LJOtE/gyGHeREHkJ2yTyByP8Q2YZVoBqLg3EfYLeF0oVvGqtaEX2t2Qovja0/gStXw==} @@ -9517,12 +10052,15 @@ packages: pug-attrs@3.0.0: resolution: {integrity: sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA==} - pug-code-gen@3.0.2: - resolution: {integrity: sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg==} + pug-code-gen@3.0.3: + resolution: {integrity: sha512-cYQg0JW0w32Ux+XTeZnBEeuWrAY7/HNE6TWnhiHGnnRYlCgyAUPoyh9KzCMa9WhcJlJ1AtQqpEYHc+vbCzA+Aw==} pug-error@2.0.0: resolution: {integrity: sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ==} + pug-error@2.1.0: + resolution: {integrity: sha512-lv7sU9e5Jk8IeUheHata6/UThZ7RK2jnaaNztxfPYUY+VxZyk/ePVaNZ/vwmH8WqGvDz3LrNYt/+gA55NDg6Pg==} + pug-filters@4.0.0: resolution: {integrity: sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A==} @@ -9547,8 +10085,8 @@ packages: pug-walk@2.0.0: resolution: {integrity: sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ==} - pug@3.0.2: - resolution: {integrity: sha512-bp0I/hiK1D1vChHh6EfDxtndHji55XP/ZJKwsRqrz6lRia6ZC2OZbdAymlxdVFwd1L70ebrVJw4/eZ79skrIaw==} + pug@3.0.3: + resolution: {integrity: sha512-uBi6kmc9f3SZ3PXxqcHiUZLmIXgfgWooKWXcwSGwQd2Zi5Rb0bT14+8CJjJgI8AB+nndLaNgHGrcc6bPIB665g==} pump@2.0.1: resolution: {integrity: sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==} @@ -9631,10 +10169,6 @@ packages: ratelimiter@3.4.1: resolution: {integrity: sha512-5FJbRW/Jkkdk29ksedAfWFkQkhbUrMx3QJGwMKAypeIiQf4yrLW+gtPKZiaWt4zPrtw1uGufOjGO7UGM6VllsQ==} - raw-body@2.5.1: - resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} - engines: {node: '>= 0.8'} - raw-body@2.5.2: resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} engines: {node: '>= 0.8'} @@ -9643,8 +10177,8 @@ packages: resolution: {integrity: sha512-fUeWjrkOO0t1rg7B2fdyDTvngj+9RlUyL92vOdiB7c0FPguWVsniIMjEtHH+meLBO9rzkUlUzBVXgWrjI8P9LA==} engines: {node: '>=12'} - re2@1.21.2: - resolution: {integrity: sha512-f8jqI0vCbwDhzY66Fgx1V2RoNDdmAupKkqRqR/AEF+2/MZNRbtEOjax6oHSht95MU40vx6+2ITsJr/9esukckg==} + re2@1.21.3: + resolution: {integrity: sha512-GI+KoGkHT4kxTaX+9p0FgNB1XUnCndO9slG5qqeEoZ7kbf6Dk6ohQVpmwKVeSp7LPLn+g6Q3BaCopz4oHuBDuQ==} react-colorful@5.6.1: resolution: {integrity: sha512-1exovf0uGTGyq5mXQT0zgQ80uvj2PCwvF8zY1RN9/vbJVSjSo3fsB/4L3ObbF7u70NduSiK4xu4Y6q1MHoUGEw==} @@ -9684,6 +10218,36 @@ packages: react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + react-remove-scroll-bar@2.3.6: + resolution: {integrity: sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.5.7: + resolution: {integrity: sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-style-singleton@2.2.1: + resolution: {integrity: sha512-ZWj0fHEMyWkHzKYUr2Bs/4zU6XLmq9HsgBURm7g5pAVfyn49DgUiNgY2d4lXRlYSiCif9YBGpQleewkcqddc7g==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + react@18.3.1: resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} engines: {node: '>=0.10.0'} @@ -9725,10 +10289,6 @@ packages: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} - recast@0.23.4: - resolution: {integrity: sha512-qtEDqIZGVcSZCHniWwZWbRy79Dc6Wp3kT/UmDA2RJKBPg7+7k51aQBZirHmUGn5uvHf2rg8DkjizrN26k61ATw==} - engines: {node: '>= 4'} - recast@0.23.6: resolution: {integrity: sha512-9FHoNjX1yjuesMwuthAmPKabxYQdOgihFYmT5ebXfYGBcnqXZf3WOVz+5foEZ8Y83P4ZY6yQD5GMmtV+pgCCAQ==} engines: {node: '>= 4'} @@ -9852,9 +10412,6 @@ packages: resolution: {integrity: sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==} engines: {node: '>=10'} - resolve@1.19.0: - resolution: {integrity: sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==} - resolve@1.22.8: resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} hasBin: true @@ -9887,6 +10444,7 @@ packages: rimraf@2.6.3: resolution: {integrity: sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==} + deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true rimraf@2.7.1: @@ -9897,14 +10455,17 @@ packages: resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} hasBin: true - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} + rollup@4.18.0: + resolution: {integrity: sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + rrweb-cssom@0.7.1: + resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} + rss-parser@3.13.0: resolution: {integrity: sha512-7jWUBV5yGN3rqMMj7CZufl/291QAhvrrGpDNE4k/02ZchL0npisiYYqULF71jCEKoIiHvK/Q2e6IkDwPziT7+w==} @@ -9940,8 +10501,8 @@ packages: sanitize-html@2.13.0: resolution: {integrity: sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA==} - sass@1.76.0: - resolution: {integrity: sha512-nc3LeqvF2FNW5xGF1zxZifdW3ffIz5aBb7I7tSvOoNu7z1RQ6pFt9MBuiPtjgaI62YWrM/txjWlOCFiGtf2xpw==} + sass@1.77.6: + resolution: {integrity: sha512-ByXE1oLD79GVq9Ht1PeHWCPMPB8XHpBuz1r85oByKHjZY6qV6rWnQovQzXJXuQ/XyE1Oj3iPk3lo28uzaRA2/Q==} engines: {node: '>=14.0.0'} hasBin: true @@ -10015,8 +10576,8 @@ packages: resolution: {integrity: sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==} engines: {node: '>=8'} - sharp@0.33.3: - resolution: {integrity: sha512-vHUeXJU1UvlO/BNwTpT0x/r53WkLUVxrmb5JTgW92fdFCFk0ispLMAeu/jPO2vjkXM1fYUi3K7/qcLF47pwM1A==} + sharp@0.33.4: + resolution: {integrity: sha512-7i/dt5kGl7qR4gwPRD2biwD2/SvBn3O04J77XKFgL2OnZtQw+AG9wnuS/csmu80nPRHLYE9E41fyEiG8nhH6/Q==} engines: {libvips: '>=8.15.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0} shebang-command@1.2.0: @@ -10035,8 +10596,8 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - shiki@1.4.0: - resolution: {integrity: sha512-5WIn0OL8PWm7JhnTwRWXniy6eEDY234mRrERVlFa646V2ErQqwIFd2UML7e0Pq9eqSKLoMa3Ke+xbsF+DAuy+Q==} + shiki@1.10.0: + resolution: {integrity: sha512-YD2sXQ+TMD/F9BimV9Jn0wj35pqOvywvOG/3PB6hGHyGKlM7TJ9tyJ02jOb2kF8F0HfJwKNYrh3sW7jEcuRlXA==} shimmer@1.2.1: resolution: {integrity: sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==} @@ -10054,8 +10615,8 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-oauth2@5.0.0: - resolution: {integrity: sha512-8291lo/z5ZdpmiOFzOs1kF3cxn22bMj5FFH+DNUppLJrpoIlM1QnFiE7KpshHu3J3i21TVcx4yW+gXYjdCKDLQ==} + simple-oauth2@5.0.1: + resolution: {integrity: sha512-JcmGdzvbHKU3GegF3BK6zNi46DqFTxPMjwYddu2bgYqZuy7Gtm8U8wdedkVE4lI4LEqXocmPBLAvC4BIiiBc5w==} simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} @@ -10155,6 +10716,10 @@ packages: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} + slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + slice-ansi@3.0.0: resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==} engines: {node: '>=8'} @@ -10175,8 +10740,8 @@ packages: resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==} engines: {node: '>= 10.13.0', npm: '>= 3.0.0'} - sonic-boom@3.7.0: - resolution: {integrity: sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==} + sonic-boom@4.0.1: + resolution: {integrity: sha512-hTSD/6JMLyT4r9zeof6UtuBDpjJ9sO08/nmS5djaA9eozT9oOlNdpXSnzcgj4FTqpk3nkLrs61l4gip9r1HCrQ==} sort-keys-length@1.0.1: resolution: {integrity: sha512-GRbEOUqCxemTAk/b32F2xa8wDTs+Z1QHOkbhJDQTvv/6G3ZkbJ+frYWsTcc7cBB3Fu4wy4XlLCuNtJuMn7Gsvw==} @@ -10236,8 +10801,8 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} - sprintf-js@1.1.2: - resolution: {integrity: sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==} + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} sshpk@1.17.0: resolution: {integrity: sha512-/9HIEs1ZXGhSPE8X6Ccm7Nam1z8KcoCqPdI7ecm1N33EzAetWahvQWVqLZtaZQ+IDKX4IyA2o0gBzqIMkAagHQ==} @@ -10258,8 +10823,8 @@ packages: standard-as-callback@2.1.0: resolution: {integrity: sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A==} - start-server-and-test@2.0.3: - resolution: {integrity: sha512-QsVObjfjFZKJE6CS6bSKNwWZCKBG6975/jKRPPGFfFh+yOQglSeGXiNWjzgQNXdphcBI9nXbyso9tPfX4YAUhg==} + start-server-and-test@2.0.4: + resolution: {integrity: sha512-CKNeBTcP0hVqIlNismHMudb9q3lLdAjcVPO13/7gfI66fcJpeIb/o4NzQd1JK/CD+lfWVqr10ZH9Y14+OwlJuw==} engines: {node: '>=16'} hasBin: true @@ -10296,8 +10861,8 @@ packages: react-dom: optional: true - storybook@8.0.9: - resolution: {integrity: sha512-/Mvij0Br5bUwJpCvqAUZMEDIWmdRxEyllvVj8Ukw5lIWJePxfpSsz4px5jg9+R6B9tO8sQSqjg4HJvQ/pZk8Tg==} + storybook@8.1.11: + resolution: {integrity: sha512-3KjIhF8lczXhKKHyHbOqV30dvuRYJSxc0d1as/C8kybuwE7cLaydhWGma7VBv5bTSPv0rDzucx7KcO+achArPg==} hasBin: true stream-browserify@3.0.0: @@ -10395,6 +10960,10 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + strip-final-newline@4.0.0: + resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} + engines: {node: '>=18'} + strip-indent@3.0.0: resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} engines: {node: '>=8'} @@ -10407,8 +10976,8 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - strip-literal@1.3.0: - resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} + strip-literal@2.1.0: + resolution: {integrity: sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==} strip-outer@2.0.0: resolution: {integrity: sha512-A21Xsm1XzUkK0qK1ZrytDUvqsQWict2Cykhvi0fBQntGG5JSprESasEyV1EZ/4CiR5WB5KjzLTrP/bO37B0wPg==} @@ -10459,8 +11028,8 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} - systeminformation@5.22.7: - resolution: {integrity: sha512-AWxlP05KeHbpGdgvZkcudJpsmChc2Y5Eo/GvxG/iUA/Aws5LZKHAMSeAo+V+nD+nxWZaxrwpWcnx4SH3oxNL3A==} + systeminformation@5.22.11: + resolution: {integrity: sha512-aLws5yi4KCHTb0BVvbodQY5bY8eW4asMRDTxTW46hqw9lGjACX6TlLdJrkdoHYRB0qs+MekqEq1zG7WDnWE8Ug==} engines: {node: '>=8.0.0'} os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android] hasBin: true @@ -10490,20 +11059,20 @@ packages: telejson@7.2.0: resolution: {integrity: sha512-1QTEcJkJEhc8OnStBx/ILRu5J2p0GjvWsBx56bmZRqnrkdBMUe+nX92jxV+p3dB4CP6PZCdJMQJwCggkNBMzkQ==} - temp-dir@2.0.0: - resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} - engines: {node: '>=8'} + temp-dir@3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} temp@0.8.4: resolution: {integrity: sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==} engines: {node: '>=6.0.0'} - tempy@1.0.1: - resolution: {integrity: sha512-biM9brNqxSc04Ee71hzFbryD11nX7VPhQQY32AdDmjFvodsRFz/3ufeoTZ6uYkRFfGo188tENcASNs3vTdsM0w==} - engines: {node: '>=10'} + tempy@3.1.0: + resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} + engines: {node: '>=14.16'} - terser@5.30.3: - resolution: {integrity: sha512-STdUgOUx8rLbMGO9IOwHLpCqolkDITFFQSMYYwKE1N2lY6MVSaeoi10z/EhWxRc6ybqoVmKSkhKYH/XUpl7vSA==} + terser@5.31.1: + resolution: {integrity: sha512-37upzU1+viGvuFtBo9NPufCb9dwM0+l9hMxYyWfBA+fbwrPqNJAhbZ6W47bBFnZHKHTUBnMvi87434qq+qnxOg==} engines: {node: '>=10'} hasBin: true @@ -10524,14 +11093,14 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} - thread-stream@2.3.0: - resolution: {integrity: sha512-kaDqm1DET9pp3NXwR8382WHbnpXnRkN9xGN9dQt3B2+dmXiW8X1SOwmFOxAErEQ47ObhZ96J6yhZNXuyCOL7KA==} + thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} - three@0.164.1: - resolution: {integrity: sha512-iC/hUBbl1vzFny7f5GtqzVXYjMJKaTPxiCxXfrvVdBi1Sf+jhd1CAkitiFwC7mIBFCo3MrDLJG97yisoaWig0w==} + three@0.165.0: + resolution: {integrity: sha512-cc96IlVYGydeceu0e5xq70H8/yoVT/tXBxV/W8A/U6uOq7DXc4/s1Mkmnu6SqoYGhSRWWYFOhVwvq6V0VtbplA==} - throttle-debounce@5.0.0: - resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==} + throttle-debounce@5.0.2: + resolution: {integrity: sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==} engines: {node: '>=12.22'} throttleit@1.0.0: @@ -10546,9 +11115,6 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} - tiny-invariant@1.3.1: - resolution: {integrity: sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw==} - tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -10562,8 +11128,8 @@ packages: tinycolor2@1.6.0: resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} - tinypool@0.7.0: - resolution: {integrity: sha512-zSYNUlYSMhJ6Zdou4cJwo/p7w5nmAH17GRfU/ui3ctvjXFErXXkruT4MWW6poDeXgCaIBlGLrfU6TbTXxyGMww==} + tinypool@0.8.4: + resolution: {integrity: sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==} engines: {node: '>=14.0.0'} tinyspy@2.2.0: @@ -10588,10 +11154,6 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} - toad-cache@3.3.0: - resolution: {integrity: sha512-3oDzcogWGHZdkwrHyvJVpPjA7oNzY6ENOV3PsWJY9XYPZ6INo94Yd47s5may1U+nleBPwDhrRiTPMIvKaa3MQg==} - engines: {node: '>=12'} - toad-cache@3.7.0: resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} engines: {node: '>=12'} @@ -10618,8 +11180,8 @@ packages: resolution: {integrity: sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==} engines: {node: '>=0.8'} - tough-cookie@4.1.3: - resolution: {integrity: sha512-aX/y5pVRkfRnfmuX+OdbSdXvPe6ieKX/G2s7e98f4poJHnqH3281gDPm/metm6E/WRamfx7WC4HUqkWHfQHprw==} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} engines: {node: '>=6'} tr46@0.0.3: @@ -10666,8 +11228,8 @@ packages: ts-map@1.0.3: resolution: {integrity: sha512-vDWbsl26LIcPGmDpoVzjEP6+hvHZkBkLW7JpvwbCv/5IYPJlsbzCVXY3wsCeAxAUeTclNOUZxnLdGh3VBD/J6w==} - tsc-alias@1.8.8: - resolution: {integrity: sha512-OYUOd2wl0H858NvABWr/BoSKNERw3N9GTi3rHPK8Iv4O1UyUXIrTTOAZNHsjlVpXFOhpJBVARI1s+rzwLivN3Q==} + tsc-alias@1.8.10: + resolution: {integrity: sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==} hasBin: true tsconfig-paths@3.15.0: @@ -10677,8 +11239,8 @@ packages: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} - tsd@0.30.7: - resolution: {integrity: sha512-oTiJ28D6B/KXoU3ww/Eji+xqHJojiuPVMwA12g4KYX1O72N93Nb6P3P3h2OAhhf92Xl8NIhb/xFmBZd5zw/xUw==} + tsd@0.31.1: + resolution: {integrity: sha512-sSL84A0SFwx2xGMWrxlGaarKFSQszWjJS2vgNDDLwatytzg2aq6ShlwHsBYxRNmjzXISODwMva5ZOdAg/4AoOA==} engines: {node: '>=14.16'} hasBin: true @@ -10688,6 +11250,9 @@ packages: tslib@2.6.2: resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} + tsx@4.4.0: resolution: {integrity: sha512-4fwcEjRUxW20ciSaMB8zkpGwCPxuRGnadDuj/pBk5S9uT29zvWz15PK36GrKJo45mSJomDxVejZ73c6lr3811Q==} engines: {node: '>=18.0.0'} @@ -10707,10 +11272,6 @@ packages: resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} engines: {node: '>=4'} - type-fest@0.16.0: - resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} - engines: {node: '>=10'} - type-fest@0.18.1: resolution: {integrity: sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==} engines: {node: '>=10'} @@ -10731,10 +11292,18 @@ packages: resolution: {integrity: sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==} engines: {node: '>=8'} + type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + type-fest@2.19.0: resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} engines: {node: '>=12.20'} + type-fest@4.20.1: + resolution: {integrity: sha512-R6wDsVsoS9xYOpy8vgeBlqpdOyzJ12HNfQhC/aAKWM3YoCV9TtunJzh/QpkMgeDhkoynDcw5f1y+qF9yc/HHyg==} + engines: {node: '>=16'} + type-fest@4.9.0: resolution: {integrity: sha512-KS/6lh/ynPGiHD/LnAobrEFq3Ad4pBzOlJ1wAnJx9N4EYoqFhMfLIBjUT2UEx4wg5ZE+cC1ob6DCSpppVo+rtg==} engines: {node: '>=16'} @@ -10829,8 +11398,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - typescript@5.5.2: - resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==} + typescript@5.5.3: + resolution: {integrity: sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==} engines: {node: '>=14.17'} hasBin: true @@ -10882,6 +11451,10 @@ packages: resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} engines: {node: '>=4'} + unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + unified@11.0.4: resolution: {integrity: sha512-apMPnyLjAX+ty4OrNap7yumyVAMlKx5IWU2wlzzUdYJO9A8f1p9m/gywF/GM2ZDFcjQPrx59Mc90KwmxsoklxQ==} @@ -10896,9 +11469,9 @@ packages: resolution: {integrity: sha512-WrcA6AyEfqDX5bWige/4NQfPZMtASNVxdmWR76WESYQVAACSgWcR6e9i0mofqqBxYFtL4oAxPIptY73/0YE1DQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} - unique-string@2.0.0: - resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} - engines: {node: '>=8'} + unique-string@3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} unist-util-is@6.0.0: resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} @@ -10950,6 +11523,26 @@ packages: url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + use-callback-ref@1.3.2: + resolution: {integrity: sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.8.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + use-sidecar@1.1.2: + resolution: {integrity: sha512-epTbsLuzZ7lPClpz2TyryBfztm7m+28DlEv2ZCQ3MDr5ssiwyOwGH/e5F9CkfWjJ1t4clvI58yF822/GUkjjhw==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': ^16.9.0 || ^17.0.0 || ^18.0.0 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + utf-8-validate@6.0.3: resolution: {integrity: sha512-uIuGf9TWQ/y+0Lp+KGZCMuJWc3N9BHA+l/UmHd/oUHwJJDeysyTRxNQVkbzsIWfGFbRe3OcgML/i0mvVRPOyDA==} engines: {node: '>=6.14.2'} @@ -10964,6 +11557,10 @@ packages: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} engines: {node: '>= 0.4.0'} + uuid@10.0.0: + resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==} + hasBin: true + uuid@3.4.0: resolution: {integrity: sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==} deprecated: Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details. @@ -10977,8 +11574,8 @@ packages: resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} hasBin: true - v-code-diff@1.11.0: - resolution: {integrity: sha512-lBlO+FXw3I3qFKbnlorXZ4sb5cFnrdxlc6lj3Y1CWrbn2LC7PoVbGlwH0W+nvAVX1rdJhhc15rKIQdHyMkXe/w==} + v-code-diff@1.12.0: + resolution: {integrity: sha512-vvdCBG02mIIiW6Gx6jF119hzxELt+6TlJIwchglR1JYzboHePNxIkVBjR/aoAOVlsGa+5Vtb77cd/N84nrXWPA==} peerDependencies: '@vue/composition-api': ^1.4.9 vue: ^2.6.0 || >=3.0.0 @@ -10993,10 +11590,6 @@ packages: validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} - validator@13.9.0: - resolution: {integrity: sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==} - engines: {node: '>= 0.10'} - vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -11011,16 +11604,16 @@ packages: vfile@6.0.1: resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} - vite-node@0.34.6: - resolution: {integrity: sha512-nlBMJ9x6n7/Amaz6F3zJ97EBwR2FkzhBRxF5e+jE6LA3yi6Wtc2lyTij1OnDMIr34v5g/tVQtsVAzhT0jc5ygA==} - engines: {node: '>=v14.18.0'} + vite-node@1.6.0: + resolution: {integrity: sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true vite-plugin-turbosnap@1.0.3: resolution: {integrity: sha512-p4D8CFVhZS412SyQX125qxyzOgIFouwOcvjZWk6bQbNPR1wtaEzFT6jZxAjf1dejlGqa6fqHcuCvQea6EWUkUA==} - vite@5.2.11: - resolution: {integrity: sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==} + vite@5.3.2: + resolution: {integrity: sha512-6lA7OBHBlXUxiJxbO5aAY2fsHHzDr1q7DvXYnyZycRs2Dz+dXBWuhpWHvmljTRTpQC2uvGmUFFkSHF2vGo90MA==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -11053,22 +11646,22 @@ packages: peerDependencies: vitest: '>=0.16.0' - vitest@0.34.6: - resolution: {integrity: sha512-+5CALsOvbNKnS+ZHMXtuUC7nL8/7F1F2DnHGjSsszX8zCjWSSviphCb/NuS9Nzf4Q03KyyDRBAXhF/8lffME4Q==} - engines: {node: '>=v14.18.0'} + vitest@1.6.0: + resolution: {integrity: sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==} + engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: '@edge-runtime/vm': '*' - '@vitest/browser': '*' - '@vitest/ui': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': 1.6.0 + '@vitest/ui': 1.6.0 happy-dom: '*' jsdom: '*' - playwright: '*' - safaridriver: '*' - webdriverio: '*' peerDependenciesMeta: '@edge-runtime/vm': optional: true + '@types/node': + optional: true '@vitest/browser': optional: true '@vitest/ui': @@ -11077,12 +11670,6 @@ packages: optional: true jsdom: optional: true - playwright: - optional: true - safaridriver: - optional: true - webdriverio: - optional: true void-elements@3.1.0: resolution: {integrity: sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==} @@ -11109,6 +11696,9 @@ packages: resolution: {integrity: sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==} hasBin: true + vscode-uri@3.0.8: + resolution: {integrity: sha512-AyFQ0EVmsOZOlAnxoFOGOq1SQDWAB7C6aqMGS23svWAllfOaxbuFvcT8D1i8z3Gyn8fraVeZNNmN6e9bxxXkKw==} + vue-component-meta@2.0.16: resolution: {integrity: sha512-IyIMClUMYcKxAL34GqdPbR4V45MUeHXqQiZlHxeYMV5Qcqp4M+CEmtGpF//XBSS138heDkYkceHAtJQjLUB1Lw==} peerDependencies: @@ -11123,8 +11713,8 @@ packages: vue-component-type-helpers@2.0.16: resolution: {integrity: sha512-qisL/iAfdO++7w+SsfYQJVPj6QKvxp4i1MMxvsNO41z/8zu3KuAw9LkhKUfP/kcOWGDxESp+pQObWppXusejCA==} - vue-component-type-helpers@2.0.21: - resolution: {integrity: sha512-3NaicyZ7N4B6cft4bfb7dOnPbE9CjLcx+6wZWAg5zwszfO4qXRh+U52dN5r5ZZfc6iMaxKCEcoH9CmxxoFZHLg==} + vue-component-type-helpers@2.0.24: + resolution: {integrity: sha512-Jr5N8QVYEcbQuMN1LRgvg61758G8HTnzUlQsAFOxx6Y6X8kmhJ7C+jOvWsQruYxi3uHhhS6BghyRlyiwO99DBg==} vue-demi@0.14.7: resolution: {integrity: sha512-EOG8KXDQNwkJILkx/gPcoL/7vH+hORoBaKgGe+6W7VFMvCYJfmF2dGbvgDroVnI8LU7/kTu8mbjRZGBU1z9NTA==} @@ -11142,8 +11732,8 @@ packages: peerDependencies: vue: '>=2' - vue-eslint-parser@9.4.2: - resolution: {integrity: sha512-Ry9oiGmCAK91HrKMtCrKFWmSFWvYkpGglCeFAIqDdr9zdXmMMpJOmUJS7WWsW7fX81h6mwHmUZCQQ1E0PkSwYQ==} + vue-eslint-parser@9.4.3: + resolution: {integrity: sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==} engines: {node: ^14.17.0 || >=16.0.0} peerDependencies: eslint: '>=6.0.0' @@ -11162,14 +11752,14 @@ packages: vue-template-compiler@2.7.14: resolution: {integrity: sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==} - vue-tsc@2.0.16: - resolution: {integrity: sha512-/gHAWJa216PeEhfxtAToIbxdWgw01wuQzo48ZUqMYVEyNqDp+OYV9xMO5HaPS2P3Ls0+EsjguMZLY4cGobX4Ew==} + vue-tsc@2.0.24: + resolution: {integrity: sha512-1qi4P8L7yS78A7OJ7CDDxUIZPD6nVxoQEgX3DkRZNi1HI1qOfzOJwQlNpmwkogSVD6S/XcanbW9sktzpSxz6rA==} hasBin: true peerDependencies: - typescript: '*' + typescript: '>=5.0.0' - vue@3.4.26: - resolution: {integrity: sha512-bUIq/p+VB+0xrJubaemrfhk1/FiW9iX+pDV+62I/XJ6EkspAO9/DXEjbDFoe8pIfOZBqfk45i9BMc41ptP/uRg==} + vue@3.4.31: + resolution: {integrity: sha512-njqRrOy7W3YLAlVqSKpBebtZpDVg21FPoaq1I7f/+qqBThK9ChAIjkRWgeP6Eat+8C+iia4P3OYqpATP21BCoQ==} peerDependencies: typescript: '*' peerDependenciesMeta: @@ -11310,8 +11900,8 @@ packages: resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} - ws@8.17.0: - resolution: {integrity: sha512-uJq6108EgZMAl20KagGkzCKfMEjxmKvZHG7Tlq0Z6nOky7YF7aq4mOx6xK8TJ/i1LeK4Qus7INktacctDgY8Ow==} + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} engines: {node: '>=10.0.0'} peerDependencies: bufferutil: ^4.0.1 @@ -11403,10 +11993,9 @@ packages: resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} engines: {node: '>=12.20'} - z-schema@5.0.5: - resolution: {integrity: sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==} - engines: {node: '>=8.0.0'} - hasBin: true + yoctocolors@2.0.2: + resolution: {integrity: sha512-Ct97huExsu7cWeEjmrXlofevF8CvzUglJ4iGUet5B8xn1oumtAZBpHU4GzYuoE6PVqcZ5hghtBrSlhwHuR1Jmw==} + engines: {node: '>=18'} zip-stream@6.0.1: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} @@ -11442,458 +12031,510 @@ snapshots: dependencies: default-browser-id: 3.0.0 - '@aws-crypto/crc32@3.0.0': + '@aws-crypto/crc32@5.2.0': dependencies: - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.413.0 - tslib: 1.14.1 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.598.0 + tslib: 2.6.2 - '@aws-crypto/crc32c@3.0.0': + '@aws-crypto/crc32c@5.2.0': dependencies: - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.413.0 - tslib: 1.14.1 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.598.0 + tslib: 2.6.2 - '@aws-crypto/ie11-detection@3.0.0': + '@aws-crypto/sha1-browser@5.2.0': dependencies: - tslib: 1.14.1 - - '@aws-crypto/sha1-browser@3.0.0': - dependencies: - '@aws-crypto/ie11-detection': 3.0.0 - '@aws-crypto/supports-web-crypto': 3.0.0 - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.413.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.598.0 '@aws-sdk/util-locate-window': 3.208.0 - '@aws-sdk/util-utf8-browser': 3.259.0 - tslib: 1.14.1 - - '@aws-crypto/sha256-browser@3.0.0': - dependencies: - '@aws-crypto/ie11-detection': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-crypto/supports-web-crypto': 3.0.0 - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.413.0 - '@aws-sdk/util-locate-window': 3.208.0 - '@aws-sdk/util-utf8-browser': 3.259.0 - tslib: 1.14.1 - - '@aws-crypto/sha256-js@3.0.0': - dependencies: - '@aws-crypto/util': 3.0.0 - '@aws-sdk/types': 3.413.0 - tslib: 1.14.1 - - '@aws-crypto/supports-web-crypto@3.0.0': - dependencies: - tslib: 1.14.1 - - '@aws-crypto/util@3.0.0': - dependencies: - '@aws-sdk/types': 3.413.0 - '@aws-sdk/util-utf8-browser': 3.259.0 - tslib: 1.14.1 - - '@aws-sdk/client-s3@3.412.0': - dependencies: - '@aws-crypto/sha1-browser': 3.0.0 - '@aws-crypto/sha256-browser': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/client-sts': 3.410.0 - '@aws-sdk/credential-provider-node': 3.410.0 - '@aws-sdk/middleware-bucket-endpoint': 3.410.0 - '@aws-sdk/middleware-expect-continue': 3.410.0 - '@aws-sdk/middleware-flexible-checksums': 3.410.0 - '@aws-sdk/middleware-host-header': 3.410.0 - '@aws-sdk/middleware-location-constraint': 3.410.0 - '@aws-sdk/middleware-logger': 3.410.0 - '@aws-sdk/middleware-recursion-detection': 3.410.0 - '@aws-sdk/middleware-sdk-s3': 3.410.0 - '@aws-sdk/middleware-signing': 3.410.0 - '@aws-sdk/middleware-ssec': 3.410.0 - '@aws-sdk/middleware-user-agent': 3.410.0 - '@aws-sdk/signature-v4-multi-region': 3.412.0 - '@aws-sdk/types': 3.410.0 - '@aws-sdk/util-endpoints': 3.410.0 - '@aws-sdk/util-user-agent-browser': 3.410.0 - '@aws-sdk/util-user-agent-node': 3.410.0 - '@aws-sdk/xml-builder': 3.310.0 - '@smithy/config-resolver': 2.0.9 - '@smithy/eventstream-serde-browser': 2.0.8 - '@smithy/eventstream-serde-config-resolver': 2.0.8 - '@smithy/eventstream-serde-node': 2.0.8 - '@smithy/fetch-http-handler': 2.1.4 - '@smithy/hash-blob-browser': 2.0.8 - '@smithy/hash-node': 2.0.8 - '@smithy/hash-stream-node': 2.0.8 - '@smithy/invalid-dependency': 2.0.8 - '@smithy/md5-js': 2.0.8 - '@smithy/middleware-content-length': 2.0.10 - '@smithy/middleware-endpoint': 2.0.8 - '@smithy/middleware-retry': 2.0.11 - '@smithy/middleware-serde': 2.0.8 - '@smithy/middleware-stack': 2.0.1 - '@smithy/node-config-provider': 2.0.11 - '@smithy/node-http-handler': 2.5.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/smithy-client': 2.1.5 - '@smithy/types': 2.6.0 - '@smithy/url-parser': 2.0.8 - '@smithy/util-base64': 2.0.0 - '@smithy/util-body-length-browser': 2.0.0 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.9 - '@smithy/util-defaults-mode-node': 2.0.11 - '@smithy/util-retry': 2.0.1 - '@smithy/util-stream': 2.0.11 '@smithy/util-utf8': 2.0.0 - '@smithy/util-waiter': 2.0.8 + tslib: 2.6.2 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-locate-window': 3.208.0 + '@smithy/util-utf8': 2.0.0 + tslib: 2.6.2 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.598.0 + tslib: 2.6.2 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.6.2 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.598.0 + '@smithy/util-utf8': 2.0.0 + tslib: 2.6.2 + + '@aws-sdk/client-s3@3.600.0': + dependencies: + '@aws-crypto/sha1-browser': 5.2.0 + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.600.0(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/client-sts': 3.600.0 + '@aws-sdk/core': 3.598.0 + '@aws-sdk/credential-provider-node': 3.600.0(@aws-sdk/client-sso-oidc@3.600.0)(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/middleware-bucket-endpoint': 3.598.0 + '@aws-sdk/middleware-expect-continue': 3.598.0 + '@aws-sdk/middleware-flexible-checksums': 3.598.0 + '@aws-sdk/middleware-host-header': 3.598.0 + '@aws-sdk/middleware-location-constraint': 3.598.0 + '@aws-sdk/middleware-logger': 3.598.0 + '@aws-sdk/middleware-recursion-detection': 3.598.0 + '@aws-sdk/middleware-sdk-s3': 3.598.0 + '@aws-sdk/middleware-signing': 3.598.0 + '@aws-sdk/middleware-ssec': 3.598.0 + '@aws-sdk/middleware-user-agent': 3.598.0 + '@aws-sdk/region-config-resolver': 3.598.0 + '@aws-sdk/signature-v4-multi-region': 3.598.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-endpoints': 3.598.0 + '@aws-sdk/util-user-agent-browser': 3.598.0 + '@aws-sdk/util-user-agent-node': 3.598.0 + '@aws-sdk/xml-builder': 3.598.0 + '@smithy/config-resolver': 3.0.4 + '@smithy/core': 2.2.4 + '@smithy/eventstream-serde-browser': 3.0.4 + '@smithy/eventstream-serde-config-resolver': 3.0.3 + '@smithy/eventstream-serde-node': 3.0.4 + '@smithy/fetch-http-handler': 3.2.0 + '@smithy/hash-blob-browser': 3.1.2 + '@smithy/hash-node': 3.0.3 + '@smithy/hash-stream-node': 3.1.2 + '@smithy/invalid-dependency': 3.0.3 + '@smithy/md5-js': 3.0.3 + '@smithy/middleware-content-length': 3.0.3 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-retry': 3.0.7 + '@smithy/middleware-serde': 3.0.3 + '@smithy/middleware-stack': 3.0.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/node-http-handler': 3.1.1 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.7 + '@smithy/util-defaults-mode-node': 3.0.7 + '@smithy/util-endpoints': 2.0.4 + '@smithy/util-retry': 3.0.3 + '@smithy/util-stream': 3.0.5 + '@smithy/util-utf8': 3.0.0 + '@smithy/util-waiter': 3.1.2 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso-oidc@3.600.0(@aws-sdk/client-sts@3.600.0)': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sts': 3.600.0 + '@aws-sdk/core': 3.598.0 + '@aws-sdk/credential-provider-node': 3.600.0(@aws-sdk/client-sso-oidc@3.600.0)(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/middleware-host-header': 3.598.0 + '@aws-sdk/middleware-logger': 3.598.0 + '@aws-sdk/middleware-recursion-detection': 3.598.0 + '@aws-sdk/middleware-user-agent': 3.598.0 + '@aws-sdk/region-config-resolver': 3.598.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-endpoints': 3.598.0 + '@aws-sdk/util-user-agent-browser': 3.598.0 + '@aws-sdk/util-user-agent-node': 3.598.0 + '@smithy/config-resolver': 3.0.4 + '@smithy/core': 2.2.4 + '@smithy/fetch-http-handler': 3.2.0 + '@smithy/hash-node': 3.0.3 + '@smithy/invalid-dependency': 3.0.3 + '@smithy/middleware-content-length': 3.0.3 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-retry': 3.0.7 + '@smithy/middleware-serde': 3.0.3 + '@smithy/middleware-stack': 3.0.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/node-http-handler': 3.1.1 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.7 + '@smithy/util-defaults-mode-node': 3.0.7 + '@smithy/util-endpoints': 2.0.4 + '@smithy/util-middleware': 3.0.3 + '@smithy/util-retry': 3.0.3 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.2 + transitivePeerDependencies: + - '@aws-sdk/client-sts' + - aws-crt + + '@aws-sdk/client-sso@3.598.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.598.0 + '@aws-sdk/middleware-host-header': 3.598.0 + '@aws-sdk/middleware-logger': 3.598.0 + '@aws-sdk/middleware-recursion-detection': 3.598.0 + '@aws-sdk/middleware-user-agent': 3.598.0 + '@aws-sdk/region-config-resolver': 3.598.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-endpoints': 3.598.0 + '@aws-sdk/util-user-agent-browser': 3.598.0 + '@aws-sdk/util-user-agent-node': 3.598.0 + '@smithy/config-resolver': 3.0.4 + '@smithy/core': 2.2.4 + '@smithy/fetch-http-handler': 3.2.0 + '@smithy/hash-node': 3.0.3 + '@smithy/invalid-dependency': 3.0.3 + '@smithy/middleware-content-length': 3.0.3 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-retry': 3.0.7 + '@smithy/middleware-serde': 3.0.3 + '@smithy/middleware-stack': 3.0.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/node-http-handler': 3.1.1 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.7 + '@smithy/util-defaults-mode-node': 3.0.7 + '@smithy/util-endpoints': 2.0.4 + '@smithy/util-middleware': 3.0.3 + '@smithy/util-retry': 3.0.3 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sts@3.600.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/client-sso-oidc': 3.600.0(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/core': 3.598.0 + '@aws-sdk/credential-provider-node': 3.600.0(@aws-sdk/client-sso-oidc@3.600.0)(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/middleware-host-header': 3.598.0 + '@aws-sdk/middleware-logger': 3.598.0 + '@aws-sdk/middleware-recursion-detection': 3.598.0 + '@aws-sdk/middleware-user-agent': 3.598.0 + '@aws-sdk/region-config-resolver': 3.598.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-endpoints': 3.598.0 + '@aws-sdk/util-user-agent-browser': 3.598.0 + '@aws-sdk/util-user-agent-node': 3.598.0 + '@smithy/config-resolver': 3.0.4 + '@smithy/core': 2.2.4 + '@smithy/fetch-http-handler': 3.2.0 + '@smithy/hash-node': 3.0.3 + '@smithy/invalid-dependency': 3.0.3 + '@smithy/middleware-content-length': 3.0.3 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-retry': 3.0.7 + '@smithy/middleware-serde': 3.0.3 + '@smithy/middleware-stack': 3.0.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/node-http-handler': 3.1.1 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 + '@smithy/util-base64': 3.0.0 + '@smithy/util-body-length-browser': 3.0.0 + '@smithy/util-body-length-node': 3.0.0 + '@smithy/util-defaults-mode-browser': 3.0.7 + '@smithy/util-defaults-mode-node': 3.0.7 + '@smithy/util-endpoints': 2.0.4 + '@smithy/util-middleware': 3.0.3 + '@smithy/util-retry': 3.0.3 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.2 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.598.0': + dependencies: + '@smithy/core': 2.2.4 + '@smithy/protocol-http': 4.0.3 + '@smithy/signature-v4': 3.1.2 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 fast-xml-parser: 4.2.5 tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - '@aws-sdk/client-sso@3.410.0': + '@aws-sdk/credential-provider-env@3.598.0': dependencies: - '@aws-crypto/sha256-browser': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/middleware-host-header': 3.410.0 - '@aws-sdk/middleware-logger': 3.410.0 - '@aws-sdk/middleware-recursion-detection': 3.410.0 - '@aws-sdk/middleware-user-agent': 3.410.0 - '@aws-sdk/types': 3.410.0 - '@aws-sdk/util-endpoints': 3.410.0 - '@aws-sdk/util-user-agent-browser': 3.410.0 - '@aws-sdk/util-user-agent-node': 3.410.0 - '@smithy/config-resolver': 2.0.9 - '@smithy/fetch-http-handler': 2.1.4 - '@smithy/hash-node': 2.0.8 - '@smithy/invalid-dependency': 2.0.8 - '@smithy/middleware-content-length': 2.0.10 - '@smithy/middleware-endpoint': 2.0.8 - '@smithy/middleware-retry': 2.0.11 - '@smithy/middleware-serde': 2.0.8 - '@smithy/middleware-stack': 2.0.1 - '@smithy/node-config-provider': 2.0.11 - '@smithy/node-http-handler': 2.5.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/smithy-client': 2.1.5 - '@smithy/types': 2.6.0 - '@smithy/url-parser': 2.0.8 - '@smithy/util-base64': 2.0.0 - '@smithy/util-body-length-browser': 2.0.0 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.9 - '@smithy/util-defaults-mode-node': 2.0.11 - '@smithy/util-retry': 2.0.1 - '@smithy/util-utf8': 2.0.0 + '@aws-sdk/types': 3.598.0 + '@smithy/property-provider': 3.1.3 + '@smithy/types': 3.3.0 + tslib: 2.6.2 + + '@aws-sdk/credential-provider-http@3.598.0': + dependencies: + '@aws-sdk/types': 3.598.0 + '@smithy/fetch-http-handler': 3.2.0 + '@smithy/node-http-handler': 3.1.1 + '@smithy/property-provider': 3.1.3 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 + '@smithy/util-stream': 3.0.5 + tslib: 2.6.2 + + '@aws-sdk/credential-provider-ini@3.598.0(@aws-sdk/client-sso-oidc@3.600.0)(@aws-sdk/client-sts@3.600.0)': + dependencies: + '@aws-sdk/client-sts': 3.600.0 + '@aws-sdk/credential-provider-env': 3.598.0 + '@aws-sdk/credential-provider-http': 3.598.0 + '@aws-sdk/credential-provider-process': 3.598.0 + '@aws-sdk/credential-provider-sso': 3.598.0(@aws-sdk/client-sso-oidc@3.600.0) + '@aws-sdk/credential-provider-web-identity': 3.598.0(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/types': 3.598.0 + '@smithy/credential-provider-imds': 3.1.3 + '@smithy/property-provider': 3.1.3 + '@smithy/shared-ini-file-loader': 3.1.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/client-sts@3.410.0': + '@aws-sdk/credential-provider-node@3.600.0(@aws-sdk/client-sso-oidc@3.600.0)(@aws-sdk/client-sts@3.600.0)': dependencies: - '@aws-crypto/sha256-browser': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/credential-provider-node': 3.410.0 - '@aws-sdk/middleware-host-header': 3.410.0 - '@aws-sdk/middleware-logger': 3.410.0 - '@aws-sdk/middleware-recursion-detection': 3.410.0 - '@aws-sdk/middleware-sdk-sts': 3.410.0 - '@aws-sdk/middleware-signing': 3.410.0 - '@aws-sdk/middleware-user-agent': 3.410.0 - '@aws-sdk/types': 3.410.0 - '@aws-sdk/util-endpoints': 3.410.0 - '@aws-sdk/util-user-agent-browser': 3.410.0 - '@aws-sdk/util-user-agent-node': 3.410.0 - '@smithy/config-resolver': 2.0.9 - '@smithy/fetch-http-handler': 2.1.4 - '@smithy/hash-node': 2.0.8 - '@smithy/invalid-dependency': 2.0.8 - '@smithy/middleware-content-length': 2.0.10 - '@smithy/middleware-endpoint': 2.0.8 - '@smithy/middleware-retry': 2.0.11 - '@smithy/middleware-serde': 2.0.8 - '@smithy/middleware-stack': 2.0.1 - '@smithy/node-config-provider': 2.0.11 - '@smithy/node-http-handler': 2.5.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/smithy-client': 2.1.5 - '@smithy/types': 2.6.0 - '@smithy/url-parser': 2.0.8 - '@smithy/util-base64': 2.0.0 - '@smithy/util-body-length-browser': 2.0.0 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.9 - '@smithy/util-defaults-mode-node': 2.0.11 - '@smithy/util-retry': 2.0.1 - '@smithy/util-utf8': 2.0.0 - fast-xml-parser: 4.2.5 + '@aws-sdk/credential-provider-env': 3.598.0 + '@aws-sdk/credential-provider-http': 3.598.0 + '@aws-sdk/credential-provider-ini': 3.598.0(@aws-sdk/client-sso-oidc@3.600.0)(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/credential-provider-process': 3.598.0 + '@aws-sdk/credential-provider-sso': 3.598.0(@aws-sdk/client-sso-oidc@3.600.0) + '@aws-sdk/credential-provider-web-identity': 3.598.0(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/types': 3.598.0 + '@smithy/credential-provider-imds': 3.1.3 + '@smithy/property-provider': 3.1.3 + '@smithy/shared-ini-file-loader': 3.1.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' + - '@aws-sdk/client-sts' - aws-crt - '@aws-sdk/credential-provider-env@3.410.0': + '@aws-sdk/credential-provider-process@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/property-provider': 2.0.9 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/property-provider': 3.1.3 + '@smithy/shared-ini-file-loader': 3.1.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/credential-provider-ini@3.410.0': + '@aws-sdk/credential-provider-sso@3.598.0(@aws-sdk/client-sso-oidc@3.600.0)': dependencies: - '@aws-sdk/credential-provider-env': 3.410.0 - '@aws-sdk/credential-provider-process': 3.410.0 - '@aws-sdk/credential-provider-sso': 3.410.0 - '@aws-sdk/credential-provider-web-identity': 3.410.0 - '@aws-sdk/types': 3.410.0 - '@smithy/credential-provider-imds': 2.0.11 - '@smithy/property-provider': 2.0.9 - '@smithy/shared-ini-file-loader': 2.0.10 - '@smithy/types': 2.6.0 + '@aws-sdk/client-sso': 3.598.0 + '@aws-sdk/token-providers': 3.598.0(@aws-sdk/client-sso-oidc@3.600.0) + '@aws-sdk/types': 3.598.0 + '@smithy/property-provider': 3.1.3 + '@smithy/shared-ini-file-loader': 3.1.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 transitivePeerDependencies: + - '@aws-sdk/client-sso-oidc' - aws-crt - '@aws-sdk/credential-provider-node@3.410.0': + '@aws-sdk/credential-provider-web-identity@3.598.0(@aws-sdk/client-sts@3.600.0)': dependencies: - '@aws-sdk/credential-provider-env': 3.410.0 - '@aws-sdk/credential-provider-ini': 3.410.0 - '@aws-sdk/credential-provider-process': 3.410.0 - '@aws-sdk/credential-provider-sso': 3.410.0 - '@aws-sdk/credential-provider-web-identity': 3.410.0 - '@aws-sdk/types': 3.410.0 - '@smithy/credential-provider-imds': 2.0.11 - '@smithy/property-provider': 2.0.9 - '@smithy/shared-ini-file-loader': 2.0.10 - '@smithy/types': 2.6.0 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-process@3.410.0': - dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/property-provider': 2.0.9 - '@smithy/shared-ini-file-loader': 2.0.10 - '@smithy/types': 2.6.0 + '@aws-sdk/client-sts': 3.600.0 + '@aws-sdk/types': 3.598.0 + '@smithy/property-provider': 3.1.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/credential-provider-sso@3.410.0': + '@aws-sdk/lib-storage@3.600.0(@aws-sdk/client-s3@3.600.0)': dependencies: - '@aws-sdk/client-sso': 3.410.0 - '@aws-sdk/token-providers': 3.410.0 - '@aws-sdk/types': 3.410.0 - '@smithy/property-provider': 2.0.9 - '@smithy/shared-ini-file-loader': 2.0.10 - '@smithy/types': 2.6.0 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/credential-provider-web-identity@3.410.0': - dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/property-provider': 2.0.9 - '@smithy/types': 2.6.0 - tslib: 2.6.2 - - '@aws-sdk/lib-storage@3.412.0(@aws-sdk/client-s3@3.412.0)': - dependencies: - '@aws-sdk/client-s3': 3.412.0 - '@smithy/abort-controller': 2.0.14 - '@smithy/middleware-endpoint': 2.0.8 - '@smithy/smithy-client': 2.1.5 + '@aws-sdk/client-s3': 3.600.0 + '@smithy/abort-controller': 3.1.1 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/smithy-client': 3.1.5 buffer: 5.6.0 events: 3.3.0 stream-browserify: 3.0.0 tslib: 2.6.2 - '@aws-sdk/middleware-bucket-endpoint@3.410.0': + '@aws-sdk/middleware-bucket-endpoint@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@aws-sdk/util-arn-parser': 3.310.0 - '@smithy/node-config-provider': 2.0.11 - '@smithy/protocol-http': 3.0.10 - '@smithy/types': 2.6.0 - '@smithy/util-config-provider': 2.0.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-arn-parser': 3.568.0 + '@smithy/node-config-provider': 3.1.3 + '@smithy/protocol-http': 4.0.3 + '@smithy/types': 3.3.0 + '@smithy/util-config-provider': 3.0.0 tslib: 2.6.2 - '@aws-sdk/middleware-expect-continue@3.410.0': + '@aws-sdk/middleware-expect-continue@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/protocol-http': 4.0.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/middleware-flexible-checksums@3.410.0': + '@aws-sdk/middleware-flexible-checksums@3.598.0': dependencies: - '@aws-crypto/crc32': 3.0.0 - '@aws-crypto/crc32c': 3.0.0 - '@aws-sdk/types': 3.410.0 - '@smithy/is-array-buffer': 2.0.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/types': 2.6.0 - '@smithy/util-utf8': 2.0.0 + '@aws-crypto/crc32': 5.2.0 + '@aws-crypto/crc32c': 5.2.0 + '@aws-sdk/types': 3.598.0 + '@smithy/is-array-buffer': 3.0.0 + '@smithy/protocol-http': 4.0.3 + '@smithy/types': 3.3.0 + '@smithy/util-utf8': 3.0.0 tslib: 2.6.2 - '@aws-sdk/middleware-host-header@3.410.0': + '@aws-sdk/middleware-host-header@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/protocol-http': 4.0.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/middleware-location-constraint@3.410.0': + '@aws-sdk/middleware-location-constraint@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/middleware-logger@3.410.0': + '@aws-sdk/middleware-logger@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/middleware-recursion-detection@3.410.0': + '@aws-sdk/middleware-recursion-detection@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/protocol-http': 4.0.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/middleware-sdk-s3@3.410.0': + '@aws-sdk/middleware-sdk-s3@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@aws-sdk/util-arn-parser': 3.310.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-arn-parser': 3.568.0 + '@smithy/node-config-provider': 3.1.3 + '@smithy/protocol-http': 4.0.3 + '@smithy/signature-v4': 3.1.2 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 + '@smithy/util-config-provider': 3.0.0 tslib: 2.6.2 - '@aws-sdk/middleware-sdk-sts@3.410.0': + '@aws-sdk/middleware-signing@3.598.0': dependencies: - '@aws-sdk/middleware-signing': 3.410.0 - '@aws-sdk/types': 3.410.0 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/property-provider': 3.1.3 + '@smithy/protocol-http': 4.0.3 + '@smithy/signature-v4': 3.1.2 + '@smithy/types': 3.3.0 + '@smithy/util-middleware': 3.0.3 tslib: 2.6.2 - '@aws-sdk/middleware-signing@3.410.0': + '@aws-sdk/middleware-ssec@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/property-provider': 2.0.9 - '@smithy/protocol-http': 3.0.10 - '@smithy/signature-v4': 2.0.5 - '@smithy/types': 2.6.0 - '@smithy/util-middleware': 2.0.1 + '@aws-sdk/types': 3.598.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/middleware-ssec@3.410.0': + '@aws-sdk/middleware-user-agent@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@aws-sdk/util-endpoints': 3.598.0 + '@smithy/protocol-http': 4.0.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/middleware-user-agent@3.410.0': + '@aws-sdk/region-config-resolver@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@aws-sdk/util-endpoints': 3.410.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/node-config-provider': 3.1.3 + '@smithy/types': 3.3.0 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.3 tslib: 2.6.2 - '@aws-sdk/signature-v4-multi-region@3.412.0': + '@aws-sdk/signature-v4-multi-region@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/protocol-http': 3.0.10 - '@smithy/signature-v4': 2.0.5 - '@smithy/types': 2.6.0 + '@aws-sdk/middleware-sdk-s3': 3.598.0 + '@aws-sdk/types': 3.598.0 + '@smithy/protocol-http': 4.0.3 + '@smithy/signature-v4': 3.1.2 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/token-providers@3.410.0': + '@aws-sdk/token-providers@3.598.0(@aws-sdk/client-sso-oidc@3.600.0)': dependencies: - '@aws-crypto/sha256-browser': 3.0.0 - '@aws-crypto/sha256-js': 3.0.0 - '@aws-sdk/middleware-host-header': 3.410.0 - '@aws-sdk/middleware-logger': 3.410.0 - '@aws-sdk/middleware-recursion-detection': 3.410.0 - '@aws-sdk/middleware-user-agent': 3.410.0 - '@aws-sdk/types': 3.410.0 - '@aws-sdk/util-endpoints': 3.410.0 - '@aws-sdk/util-user-agent-browser': 3.410.0 - '@aws-sdk/util-user-agent-node': 3.410.0 - '@smithy/config-resolver': 2.0.9 - '@smithy/fetch-http-handler': 2.1.4 - '@smithy/hash-node': 2.0.8 - '@smithy/invalid-dependency': 2.0.8 - '@smithy/middleware-content-length': 2.0.10 - '@smithy/middleware-endpoint': 2.0.8 - '@smithy/middleware-retry': 2.0.11 - '@smithy/middleware-serde': 2.0.8 - '@smithy/middleware-stack': 2.0.1 - '@smithy/node-config-provider': 2.0.11 - '@smithy/node-http-handler': 2.5.0 - '@smithy/property-provider': 2.0.9 - '@smithy/protocol-http': 3.0.10 - '@smithy/shared-ini-file-loader': 2.0.10 - '@smithy/smithy-client': 2.1.5 - '@smithy/types': 2.6.0 - '@smithy/url-parser': 2.0.8 - '@smithy/util-base64': 2.0.0 - '@smithy/util-body-length-browser': 2.0.0 - '@smithy/util-body-length-node': 2.1.0 - '@smithy/util-defaults-mode-browser': 2.0.9 - '@smithy/util-defaults-mode-node': 2.0.11 - '@smithy/util-retry': 2.0.1 - '@smithy/util-utf8': 2.0.0 - tslib: 2.6.2 - transitivePeerDependencies: - - aws-crt - - '@aws-sdk/types@3.410.0': - dependencies: - '@smithy/types': 2.6.0 + '@aws-sdk/client-sso-oidc': 3.600.0(@aws-sdk/client-sts@3.600.0) + '@aws-sdk/types': 3.598.0 + '@smithy/property-provider': 3.1.3 + '@smithy/shared-ini-file-loader': 3.1.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/types@3.413.0': + '@aws-sdk/types@3.598.0': dependencies: - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/util-arn-parser@3.310.0': + '@aws-sdk/util-arn-parser@3.568.0': dependencies: tslib: 2.6.2 - '@aws-sdk/util-endpoints@3.410.0': + '@aws-sdk/util-endpoints@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 + '@aws-sdk/types': 3.598.0 + '@smithy/types': 3.3.0 + '@smithy/util-endpoints': 2.0.4 tslib: 2.6.2 '@aws-sdk/util-locate-window@3.208.0': dependencies: tslib: 2.6.2 - '@aws-sdk/util-user-agent-browser@3.410.0': + '@aws-sdk/util-user-agent-browser@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/types': 3.3.0 bowser: 2.11.0 tslib: 2.6.2 - '@aws-sdk/util-user-agent-node@3.410.0': + '@aws-sdk/util-user-agent-node@3.598.0': dependencies: - '@aws-sdk/types': 3.410.0 - '@smithy/node-config-provider': 2.0.11 - '@smithy/types': 2.6.0 + '@aws-sdk/types': 3.598.0 + '@smithy/node-config-provider': 3.1.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@aws-sdk/util-utf8-browser@3.259.0': - dependencies: - tslib: 2.6.2 - - '@aws-sdk/xml-builder@3.310.0': + '@aws-sdk/xml-builder@3.598.0': dependencies: + '@smithy/types': 3.3.0 tslib: 2.6.2 '@babel/code-frame@7.23.5': @@ -11901,8 +12542,15 @@ snapshots: '@babel/highlight': 7.23.4 chalk: 2.4.2 + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.0 + '@babel/compat-data@7.23.5': {} + '@babel/compat-data@7.24.7': {} + '@babel/core@7.23.5': dependencies: '@ampproject/remapping': 2.2.1 @@ -11916,27 +12564,27 @@ snapshots: '@babel/traverse': 7.23.5 '@babel/types': 7.23.5 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/core@7.24.0': + '@babel/core@7.24.7': dependencies: '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.0) - '@babel/helpers': 7.24.0 - '@babel/parser': 7.24.0 - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helpers': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/template': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11950,20 +12598,23 @@ snapshots: '@jridgewell/trace-mapping': 0.3.18 jsesc: 2.5.2 - '@babel/generator@7.23.6': + '@babel/generator@7.24.7': dependencies: - '@babel/types': 7.24.0 - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.18 + '@babel/types': 7.24.7 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 - '@babel/helper-annotate-as-pure@7.22.5': + '@babel/helper-annotate-as-pure@7.24.7': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.7 - '@babel/helper-builder-binary-assignment-operator-visitor@7.22.15': + '@babel/helper-builder-binary-assignment-operator-visitor@7.24.7': dependencies: - '@babel/types': 7.24.0 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color '@babel/helper-compilation-targets@7.22.15': dependencies: @@ -11973,40 +12624,42 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-compilation-targets@7.23.6': + '@babel/helper-compilation-targets@7.24.7': dependencies: - '@babel/compat-data': 7.23.5 - '@babel/helper-validator-option': 7.23.5 + '@babel/compat-data': 7.24.7 + '@babel/helper-validator-option': 7.24.7 browserslist: 4.23.0 lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.23.5(@babel/core@7.24.0)': + '@babel/helper-create-class-features-plugin@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.24.0) - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 + '@babel/core': 7.24.7 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-member-expression-to-functions': 7.24.7 + '@babel/helper-optimise-call-expression': 7.24.7 + '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 semver: 6.3.1 + transitivePeerDependencies: + - supports-color - '@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.24.0)': + '@babel/helper-create-regexp-features-plugin@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-annotate-as-pure': 7.24.7 regexpu-core: 5.3.2 semver: 6.3.1 - '@babel/helper-define-polyfill-provider@0.4.3(@babel/core@7.24.0)': + '@babel/helper-define-polyfill-provider@0.6.2(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.22.5 - debug: 4.3.4(supports-color@8.1.1) + '@babel/core': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + debug: 4.3.5(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -12014,23 +12667,46 @@ snapshots: '@babel/helper-environment-visitor@7.22.20': {} + '@babel/helper-environment-visitor@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@babel/helper-function-name@7.23.0': dependencies: - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 + + '@babel/helper-function-name@7.24.7': + dependencies: + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 '@babel/helper-hoist-variables@7.22.5': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.7 - '@babel/helper-member-expression-to-functions@7.23.0': + '@babel/helper-hoist-variables@7.24.7': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.7 + + '@babel/helper-member-expression-to-functions@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color '@babel/helper-module-imports@7.22.15': dependencies: '@babel/types': 7.23.5 + '@babel/helper-module-imports@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.23.3(@babel/core@7.23.5)': dependencies: '@babel/core': 7.23.5 @@ -12040,58 +12716,89 @@ snapshots: '@babel/helper-split-export-declaration': 7.22.6 '@babel/helper-validator-identifier': 7.22.20 - '@babel/helper-module-transforms@7.23.3(@babel/core@7.24.0)': + '@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 + '@babel/core': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/helper-optimise-call-expression@7.22.5': + '@babel/helper-optimise-call-expression@7.24.7': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.7 '@babel/helper-plugin-utils@7.22.5': {} - '@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.24.0)': - dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-wrap-function': 7.22.20 + '@babel/helper-plugin-utils@7.24.7': {} - '@babel/helper-replace-supers@7.22.20(@babel/core@7.24.0)': + '@babel/helper-remap-async-to-generator@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-member-expression-to-functions': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-wrap-function': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-member-expression-to-functions': 7.24.7 + '@babel/helper-optimise-call-expression': 7.24.7 + transitivePeerDependencies: + - supports-color '@babel/helper-simple-access@7.22.5': dependencies: '@babel/types': 7.23.5 - '@babel/helper-skip-transparent-expression-wrappers@7.22.5': + '@babel/helper-simple-access@7.24.7': dependencies: - '@babel/types': 7.24.0 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color '@babel/helper-split-export-declaration@7.22.6': dependencies: '@babel/types': 7.23.5 + '@babel/helper-split-export-declaration@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@babel/helper-string-parser@7.23.4': {} + '@babel/helper-string-parser@7.24.7': {} + '@babel/helper-validator-identifier@7.22.20': {} + '@babel/helper-validator-identifier@7.24.7': {} + '@babel/helper-validator-option@7.23.5': {} - '@babel/helper-wrap-function@7.22.20': + '@babel/helper-validator-option@7.24.7': {} + + '@babel/helper-wrap-function@7.24.7': dependencies: - '@babel/helper-function-name': 7.23.0 - '@babel/template': 7.24.0 - '@babel/types': 7.24.0 + '@babel/helper-function-name': 7.24.7 + '@babel/template': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color '@babel/helpers@7.23.5': dependencies: @@ -12101,13 +12808,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helpers@7.24.0': + '@babel/helpers@7.24.7': dependencies: - '@babel/template': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 - transitivePeerDependencies: - - supports-color + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 '@babel/highlight@7.23.4': dependencies: @@ -12115,48 +12819,63 @@ snapshots: chalk: 2.4.2 js-tokens: 4.0.0 + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.0 + '@babel/parser@7.23.9': dependencies: '@babel/types': 7.23.5 - '@babel/parser@7.24.0': - dependencies: - '@babel/types': 7.24.0 - '@babel/parser@7.24.5': dependencies: '@babel/types': 7.24.0 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.24.0)': + '@babel/parser@7.24.7': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/types': 7.24.7 - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.0)': + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.5)': dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.0)': + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.23.5)': @@ -12169,49 +12888,49 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.0)': + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.0)': + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-flow@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-flow@7.23.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-import-assertions@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-syntax-import-attributes@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-import-attributes@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.5)': dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.0)': + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.5)': @@ -12219,9 +12938,9 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.5)': @@ -12229,9 +12948,9 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.5)': @@ -12239,9 +12958,9 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.0)': + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.5)': @@ -12249,9 +12968,9 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.5)': @@ -12259,9 +12978,9 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.0)': + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.5)': @@ -12269,9 +12988,9 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.5)': @@ -12279,9 +12998,9 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.5)': @@ -12289,24 +13008,24 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.0)': + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.5)': dependencies: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.0)': + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 '@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.5)': @@ -12314,435 +13033,471 @@ snapshots: '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.0)': + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-arrow-functions@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-async-generator-functions@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-async-generator-functions@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.0) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-async-to-generator@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-async-to-generator@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-imports': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-remap-async-to-generator': 7.24.7(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-block-scoped-functions@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-block-scoping@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-class-properties@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-class-static-block@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-class-static-block@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-classes@7.23.5(@babel/core@7.24.0)': + '@babel/plugin-transform-classes@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-optimise-call-expression': 7.22.5 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.24.0) - '@babel/helper-split-export-declaration': 7.22.6 + '@babel/core': 7.24.7 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.7) + '@babel/helper-split-export-declaration': 7.24.7 globals: 11.12.0 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-computed-properties@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/template': 7.24.0 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/template': 7.24.7 - '@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-destructuring@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-dotall-regex@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-duplicate-keys@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-duplicate-keys@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-dynamic-import@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-dynamic-import@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-transform-exponentiation-operator@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-exponentiation-operator@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-export-namespace-from@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-export-namespace-from@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-transform-flow-strip-types@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-flow-strip-types@7.23.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-flow': 7.23.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-flow': 7.23.3(@babel/core@7.24.7) - '@babel/plugin-transform-for-of@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-for-of@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-function-name@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-function-name@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-json-strings@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-json-strings@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-transform-literals@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-literals@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-logical-assignment-operators@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-logical-assignment-operators@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.7) - '@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-member-expression-literals@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-modules-amd@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-modules-commonjs@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-simple-access': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-modules-systemjs@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-modules-systemjs@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-identifier': 7.22.20 + '@babel/core': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-modules-umd@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-modules-umd@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-module-transforms': 7.23.3(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.24.0)': + '@babel/plugin-transform-named-capturing-groups-regex@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-new-target@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-new-target@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-nullish-coalescing-operator@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-nullish-coalescing-operator@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-transform-numeric-separator@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-numeric-separator@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.7) - '@babel/plugin-transform-object-rest-spread@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-object-rest-spread@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/compat-data': 7.23.5 - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.24.7) - '@babel/plugin-transform-object-super@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-object-super@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-replace-supers': 7.22.20(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-replace-supers': 7.24.7(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-optional-catch-binding@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-optional-catch-binding@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.7) - '@babel/plugin-transform-optional-chaining@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-optional-chaining@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-parameters@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-parameters@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-private-methods@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-private-property-in-object@7.23.4(@babel/core@7.24.0)': + '@babel/plugin-transform-private-property-in-object@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-property-literals@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-regenerator@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-regenerator@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 regenerator-transform: 0.15.2 - '@babel/plugin-transform-reserved-words@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-reserved-words@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-shorthand-properties@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-spread@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-spread@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-skip-transparent-expression-wrappers': 7.24.7 + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-sticky-regex@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-template-literals@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-typeof-symbol@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-typescript@7.23.5(@babel/core@7.24.0)': + '@babel/plugin-transform-typescript@7.23.5(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-annotate-as-pure': 7.22.5 - '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 - '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-annotate-as-pure': 7.24.7 + '@babel/helper-create-class-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color - '@babel/plugin-transform-unicode-escapes@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-unicode-escapes@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-unicode-property-regex@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-unicode-property-regex@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-unicode-regex@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-unicode-regex@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 - '@babel/plugin-transform-unicode-sets-regex@7.23.3(@babel/core@7.24.0)': + '@babel/plugin-transform-unicode-sets-regex@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.24.0) - '@babel/helper-plugin-utils': 7.22.5 + '@babel/core': 7.24.7 + '@babel/helper-create-regexp-features-plugin': 7.24.7(@babel/core@7.24.7) + '@babel/helper-plugin-utils': 7.24.7 - '@babel/preset-env@7.23.5(@babel/core@7.24.0)': + '@babel/preset-env@7.24.7(@babel/core@7.24.7)': dependencies: - '@babel/compat-data': 7.23.5 - '@babel/core': 7.24.0 - '@babel/helper-compilation-targets': 7.23.6 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.0) - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.0) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.0) - '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.0) - '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-syntax-import-attributes': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.0) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.0) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.0) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.0) - '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.0) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.0) - '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.0) - '@babel/plugin-transform-arrow-functions': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-async-generator-functions': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-async-to-generator': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-block-scoped-functions': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-block-scoping': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-class-static-block': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-classes': 7.23.5(@babel/core@7.24.0) - '@babel/plugin-transform-computed-properties': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-destructuring': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-dotall-regex': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-duplicate-keys': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-dynamic-import': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-exponentiation-operator': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-export-namespace-from': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-for-of': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-function-name': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-json-strings': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-literals': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-logical-assignment-operators': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-member-expression-literals': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-modules-amd': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-modules-systemjs': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-modules-umd': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.24.0) - '@babel/plugin-transform-new-target': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-numeric-separator': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-object-rest-spread': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-object-super': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-optional-catch-binding': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-private-property-in-object': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-property-literals': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-regenerator': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-reserved-words': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-shorthand-properties': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-sticky-regex': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-typeof-symbol': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-unicode-escapes': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-unicode-property-regex': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-unicode-regex': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-unicode-sets-regex': 7.23.3(@babel/core@7.24.0) - '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.0) - babel-plugin-polyfill-corejs2: 0.4.6(@babel/core@7.24.0) - babel-plugin-polyfill-corejs3: 0.8.6(@babel/core@7.24.0) - babel-plugin-polyfill-regenerator: 0.5.3(@babel/core@7.24.0) - core-js-compat: 3.33.3 + '@babel/compat-data': 7.24.7 + '@babel/core': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.24.7) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.24.7) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.24.7) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.24.7) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-import-assertions': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-syntax-import-attributes': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.24.7) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.24.7) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.24.7) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.24.7) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.24.7) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.24.7) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.24.7) + '@babel/plugin-transform-arrow-functions': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-async-generator-functions': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-async-to-generator': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-block-scoped-functions': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-block-scoping': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-class-static-block': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-classes': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-computed-properties': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-destructuring': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-dotall-regex': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-duplicate-keys': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-dynamic-import': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-exponentiation-operator': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-export-namespace-from': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-for-of': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-function-name': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-json-strings': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-literals': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-logical-assignment-operators': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-member-expression-literals': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-modules-amd': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-modules-commonjs': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-modules-systemjs': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-modules-umd': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-named-capturing-groups-regex': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-new-target': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-numeric-separator': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-object-rest-spread': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-object-super': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-optional-catch-binding': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-parameters': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-private-property-in-object': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-property-literals': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-regenerator': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-reserved-words': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-shorthand-properties': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-spread': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-sticky-regex': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-template-literals': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-typeof-symbol': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-unicode-escapes': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-unicode-property-regex': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-unicode-regex': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-unicode-sets-regex': 7.24.7(@babel/core@7.24.7) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.24.7) + babel-plugin-polyfill-corejs2: 0.4.11(@babel/core@7.24.7) + babel-plugin-polyfill-corejs3: 0.10.4(@babel/core@7.24.7) + babel-plugin-polyfill-regenerator: 0.6.2(@babel/core@7.24.7) + core-js-compat: 3.37.1 semver: 6.3.1 transitivePeerDependencies: - supports-color - '@babel/preset-flow@7.23.3(@babel/core@7.24.0)': + '@babel/preset-flow@7.23.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-transform-flow-strip-types': 7.23.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + '@babel/plugin-transform-flow-strip-types': 7.23.3(@babel/core@7.24.7) - '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.0)': + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/types': 7.24.0 + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/types': 7.24.7 esutils: 2.0.3 - '@babel/preset-typescript@7.23.3(@babel/core@7.24.0)': + '@babel/preset-typescript@7.23.3(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 - '@babel/helper-plugin-utils': 7.22.5 - '@babel/helper-validator-option': 7.23.5 - '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-typescript': 7.23.5(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.24.7) + '@babel/plugin-transform-modules-commonjs': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-typescript': 7.23.5(@babel/core@7.24.7) + transitivePeerDependencies: + - supports-color - '@babel/register@7.22.15(@babel/core@7.24.0)': + '@babel/register@7.22.15(@babel/core@7.24.7)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 clone-deep: 4.0.1 find-cache-dir: 2.1.0 make-dir: 2.1.0 @@ -12763,9 +13518,15 @@ snapshots: '@babel/template@7.24.0': dependencies: - '@babel/code-frame': 7.23.5 - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + + '@babel/template@7.24.7': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 '@babel/traverse@7.23.5': dependencies: @@ -12777,22 +13538,22 @@ snapshots: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.23.9 '@babel/types': 7.23.5 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color - '@babel/traverse@7.24.0': + '@babel/traverse@7.24.7': dependencies: - '@babel/code-frame': 7.23.5 - '@babel/generator': 7.23.6 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 - debug: 4.3.4(supports-color@8.1.1) + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + debug: 4.3.5(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -12809,26 +13570,32 @@ snapshots: '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + '@babel/types@7.24.7': + dependencies: + '@babel/helper-string-parser': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + '@base2/pretty-print-object@1.0.1': {} '@bcoe/v8-coverage@0.2.3': {} - '@bull-board/api@5.17.0(@bull-board/ui@5.17.0)': + '@bull-board/api@5.20.5(@bull-board/ui@5.20.5)': dependencies: - '@bull-board/ui': 5.17.0 + '@bull-board/ui': 5.20.5 redis-info: 3.1.0 - '@bull-board/fastify@5.17.0': + '@bull-board/fastify@5.20.5': dependencies: - '@bull-board/api': 5.17.0(@bull-board/ui@5.17.0) - '@bull-board/ui': 5.17.0 + '@bull-board/api': 5.20.5(@bull-board/ui@5.20.5) + '@bull-board/ui': 5.20.5 '@fastify/static': 6.12.0 '@fastify/view': 8.2.0 - ejs: 3.1.9 + ejs: 3.1.10 - '@bull-board/ui@5.17.0': + '@bull-board/ui@5.20.5': dependencies: - '@bull-board/api': 5.17.0(@bull-board/ui@5.17.0) + '@bull-board/api': 5.20.5(@bull-board/ui@5.20.5) '@bundled-es-modules/cookie@2.0.0': dependencies: @@ -12926,7 +13693,7 @@ snapshots: performance-now: 2.1.0 qs: 6.10.4 safe-buffer: 5.2.1 - tough-cookie: 4.1.3 + tough-cookie: 4.1.4 tunnel-agent: 0.6.0 uuid: 8.3.2 @@ -12966,7 +13733,10 @@ snapshots: '@esbuild/aix-ppc64@0.19.11': optional: true - '@esbuild/aix-ppc64@0.20.2': + '@esbuild/aix-ppc64@0.21.5': + optional: true + + '@esbuild/aix-ppc64@0.22.0': optional: true '@esbuild/android-arm64@0.18.20': @@ -12975,7 +13745,10 @@ snapshots: '@esbuild/android-arm64@0.19.11': optional: true - '@esbuild/android-arm64@0.20.2': + '@esbuild/android-arm64@0.21.5': + optional: true + + '@esbuild/android-arm64@0.22.0': optional: true '@esbuild/android-arm@0.18.20': @@ -12984,7 +13757,10 @@ snapshots: '@esbuild/android-arm@0.19.11': optional: true - '@esbuild/android-arm@0.20.2': + '@esbuild/android-arm@0.21.5': + optional: true + + '@esbuild/android-arm@0.22.0': optional: true '@esbuild/android-x64@0.18.20': @@ -12993,7 +13769,10 @@ snapshots: '@esbuild/android-x64@0.19.11': optional: true - '@esbuild/android-x64@0.20.2': + '@esbuild/android-x64@0.21.5': + optional: true + + '@esbuild/android-x64@0.22.0': optional: true '@esbuild/darwin-arm64@0.18.20': @@ -13002,7 +13781,10 @@ snapshots: '@esbuild/darwin-arm64@0.19.11': optional: true - '@esbuild/darwin-arm64@0.20.2': + '@esbuild/darwin-arm64@0.21.5': + optional: true + + '@esbuild/darwin-arm64@0.22.0': optional: true '@esbuild/darwin-x64@0.18.20': @@ -13011,7 +13793,10 @@ snapshots: '@esbuild/darwin-x64@0.19.11': optional: true - '@esbuild/darwin-x64@0.20.2': + '@esbuild/darwin-x64@0.21.5': + optional: true + + '@esbuild/darwin-x64@0.22.0': optional: true '@esbuild/freebsd-arm64@0.18.20': @@ -13020,7 +13805,10 @@ snapshots: '@esbuild/freebsd-arm64@0.19.11': optional: true - '@esbuild/freebsd-arm64@0.20.2': + '@esbuild/freebsd-arm64@0.21.5': + optional: true + + '@esbuild/freebsd-arm64@0.22.0': optional: true '@esbuild/freebsd-x64@0.18.20': @@ -13029,7 +13817,10 @@ snapshots: '@esbuild/freebsd-x64@0.19.11': optional: true - '@esbuild/freebsd-x64@0.20.2': + '@esbuild/freebsd-x64@0.21.5': + optional: true + + '@esbuild/freebsd-x64@0.22.0': optional: true '@esbuild/linux-arm64@0.18.20': @@ -13038,7 +13829,10 @@ snapshots: '@esbuild/linux-arm64@0.19.11': optional: true - '@esbuild/linux-arm64@0.20.2': + '@esbuild/linux-arm64@0.21.5': + optional: true + + '@esbuild/linux-arm64@0.22.0': optional: true '@esbuild/linux-arm@0.18.20': @@ -13047,7 +13841,10 @@ snapshots: '@esbuild/linux-arm@0.19.11': optional: true - '@esbuild/linux-arm@0.20.2': + '@esbuild/linux-arm@0.21.5': + optional: true + + '@esbuild/linux-arm@0.22.0': optional: true '@esbuild/linux-ia32@0.18.20': @@ -13056,7 +13853,10 @@ snapshots: '@esbuild/linux-ia32@0.19.11': optional: true - '@esbuild/linux-ia32@0.20.2': + '@esbuild/linux-ia32@0.21.5': + optional: true + + '@esbuild/linux-ia32@0.22.0': optional: true '@esbuild/linux-loong64@0.18.20': @@ -13065,7 +13865,10 @@ snapshots: '@esbuild/linux-loong64@0.19.11': optional: true - '@esbuild/linux-loong64@0.20.2': + '@esbuild/linux-loong64@0.21.5': + optional: true + + '@esbuild/linux-loong64@0.22.0': optional: true '@esbuild/linux-mips64el@0.18.20': @@ -13074,7 +13877,10 @@ snapshots: '@esbuild/linux-mips64el@0.19.11': optional: true - '@esbuild/linux-mips64el@0.20.2': + '@esbuild/linux-mips64el@0.21.5': + optional: true + + '@esbuild/linux-mips64el@0.22.0': optional: true '@esbuild/linux-ppc64@0.18.20': @@ -13083,7 +13889,10 @@ snapshots: '@esbuild/linux-ppc64@0.19.11': optional: true - '@esbuild/linux-ppc64@0.20.2': + '@esbuild/linux-ppc64@0.21.5': + optional: true + + '@esbuild/linux-ppc64@0.22.0': optional: true '@esbuild/linux-riscv64@0.18.20': @@ -13092,7 +13901,10 @@ snapshots: '@esbuild/linux-riscv64@0.19.11': optional: true - '@esbuild/linux-riscv64@0.20.2': + '@esbuild/linux-riscv64@0.21.5': + optional: true + + '@esbuild/linux-riscv64@0.22.0': optional: true '@esbuild/linux-s390x@0.18.20': @@ -13101,7 +13913,10 @@ snapshots: '@esbuild/linux-s390x@0.19.11': optional: true - '@esbuild/linux-s390x@0.20.2': + '@esbuild/linux-s390x@0.21.5': + optional: true + + '@esbuild/linux-s390x@0.22.0': optional: true '@esbuild/linux-x64@0.18.20': @@ -13110,7 +13925,10 @@ snapshots: '@esbuild/linux-x64@0.19.11': optional: true - '@esbuild/linux-x64@0.20.2': + '@esbuild/linux-x64@0.21.5': + optional: true + + '@esbuild/linux-x64@0.22.0': optional: true '@esbuild/netbsd-x64@0.18.20': @@ -13119,7 +13937,13 @@ snapshots: '@esbuild/netbsd-x64@0.19.11': optional: true - '@esbuild/netbsd-x64@0.20.2': + '@esbuild/netbsd-x64@0.21.5': + optional: true + + '@esbuild/netbsd-x64@0.22.0': + optional: true + + '@esbuild/openbsd-arm64@0.22.0': optional: true '@esbuild/openbsd-x64@0.18.20': @@ -13128,7 +13952,10 @@ snapshots: '@esbuild/openbsd-x64@0.19.11': optional: true - '@esbuild/openbsd-x64@0.20.2': + '@esbuild/openbsd-x64@0.21.5': + optional: true + + '@esbuild/openbsd-x64@0.22.0': optional: true '@esbuild/sunos-x64@0.18.20': @@ -13137,7 +13964,10 @@ snapshots: '@esbuild/sunos-x64@0.19.11': optional: true - '@esbuild/sunos-x64@0.20.2': + '@esbuild/sunos-x64@0.21.5': + optional: true + + '@esbuild/sunos-x64@0.22.0': optional: true '@esbuild/win32-arm64@0.18.20': @@ -13146,7 +13976,10 @@ snapshots: '@esbuild/win32-arm64@0.19.11': optional: true - '@esbuild/win32-arm64@0.20.2': + '@esbuild/win32-arm64@0.21.5': + optional: true + + '@esbuild/win32-arm64@0.22.0': optional: true '@esbuild/win32-ia32@0.18.20': @@ -13155,7 +13988,10 @@ snapshots: '@esbuild/win32-ia32@0.19.11': optional: true - '@esbuild/win32-ia32@0.20.2': + '@esbuild/win32-ia32@0.21.5': + optional: true + + '@esbuild/win32-ia32@0.22.0': optional: true '@esbuild/win32-x64@0.18.20': @@ -13164,30 +14000,38 @@ snapshots: '@esbuild/win32-x64@0.19.11': optional: true - '@esbuild/win32-x64@0.20.2': + '@esbuild/win32-x64@0.21.5': optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.53.0)': - dependencies: - eslint: 8.53.0 - eslint-visitor-keys: 3.4.3 + '@esbuild/win32-x64@0.22.0': + optional: true - '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.6.0)': dependencies: - eslint: 8.57.0 + eslint: 9.6.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.10.0': {} '@eslint-community/regexpp@4.6.2': {} - '@eslint/eslintrc@2.1.4': + '@eslint/compat@1.1.0': {} + + '@eslint/config-array@0.17.0': + dependencies: + '@eslint/object-schema': 2.1.4 + debug: 4.3.5(supports-color@8.1.1) + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) - espree: 9.6.1 - globals: 13.19.0 - ignore: 5.2.4 + debug: 4.3.5(supports-color@8.1.1) + espree: 10.1.0 + globals: 14.0.0 + ignore: 5.3.1 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -13195,9 +14039,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@8.53.0': {} + '@eslint/js@9.6.0': {} - '@eslint/js@8.57.0': {} + '@eslint/object-schema@2.1.4': {} '@fal-works/esbuild-plugin-global-externals@2.1.2': {} @@ -13210,8 +14054,8 @@ snapshots: '@fastify/ajv-compiler@3.5.0': dependencies: - ajv: 8.13.0 - ajv-formats: 2.1.1(ajv@8.13.0) + ajv: 8.16.0 + ajv-formats: 2.1.1(ajv@8.16.0) fast-uri: 2.2.0 '@fastify/busboy@2.1.0': {} @@ -13246,12 +14090,12 @@ snapshots: '@fastify/reply-from': 9.0.1 fast-querystring: 1.1.2 fastify-plugin: 4.5.0 - ws: 8.17.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) + ws: 8.17.1(bufferutil@4.0.7)(utf-8-validate@6.0.3) transitivePeerDependencies: - bufferutil - utf-8-validate - '@fastify/multipart@8.2.0': + '@fastify/multipart@8.3.0': dependencies: '@fastify/busboy': 2.1.0 '@fastify/deepmerge': 1.3.0 @@ -13287,14 +14131,14 @@ snapshots: glob: 8.1.0 p-limit: 3.1.0 - '@fastify/static@7.0.3': + '@fastify/static@7.0.4': dependencies: '@fastify/accept-negotiator': 1.0.0 '@fastify/send': 2.0.1 content-disposition: 0.5.4 fastify-plugin: 4.5.0 fastq: 1.17.1 - glob: 10.3.12 + glob: 10.4.2 '@fastify/view@8.2.0': dependencies: @@ -13310,13 +14154,11 @@ snapshots: '@hapi/boom@10.0.1': dependencies: - '@hapi/hoek': 11.0.2 + '@hapi/hoek': 11.0.4 '@hapi/bourne@3.0.0': {} - '@hapi/hoek@10.0.1': {} - - '@hapi/hoek@11.0.2': {} + '@hapi/hoek@11.0.4': {} '@hapi/hoek@9.3.0': {} @@ -13328,40 +14170,22 @@ snapshots: dependencies: '@hapi/boom': 10.0.1 '@hapi/bourne': 3.0.0 - '@hapi/hoek': 11.0.2 + '@hapi/hoek': 11.0.4 '@hexagon/base64@1.1.27': {} - '@humanwhocodes/config-array@0.11.13': - dependencies: - '@humanwhocodes/object-schema': 2.0.1 - debug: 4.3.4(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - - '@humanwhocodes/config-array@0.11.14': - dependencies: - '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4(supports-color@8.1.1) - minimatch: 3.1.2 - transitivePeerDependencies: - - supports-color - '@humanwhocodes/module-importer@1.0.1': {} '@humanwhocodes/momoa@2.0.4': {} - '@humanwhocodes/object-schema@2.0.1': {} + '@humanwhocodes/retry@0.3.0': {} - '@humanwhocodes/object-schema@2.0.2': {} - - '@img/sharp-darwin-arm64@0.33.3': + '@img/sharp-darwin-arm64@0.33.4': optionalDependencies: '@img/sharp-libvips-darwin-arm64': 1.0.2 optional: true - '@img/sharp-darwin-x64@0.33.3': + '@img/sharp-darwin-x64@0.33.4': optionalDependencies: '@img/sharp-libvips-darwin-x64': 1.0.2 optional: true @@ -13390,45 +14214,45 @@ snapshots: '@img/sharp-libvips-linuxmusl-x64@1.0.2': optional: true - '@img/sharp-linux-arm64@0.33.3': + '@img/sharp-linux-arm64@0.33.4': optionalDependencies: '@img/sharp-libvips-linux-arm64': 1.0.2 optional: true - '@img/sharp-linux-arm@0.33.3': + '@img/sharp-linux-arm@0.33.4': optionalDependencies: '@img/sharp-libvips-linux-arm': 1.0.2 optional: true - '@img/sharp-linux-s390x@0.33.3': + '@img/sharp-linux-s390x@0.33.4': optionalDependencies: '@img/sharp-libvips-linux-s390x': 1.0.2 optional: true - '@img/sharp-linux-x64@0.33.3': + '@img/sharp-linux-x64@0.33.4': optionalDependencies: '@img/sharp-libvips-linux-x64': 1.0.2 optional: true - '@img/sharp-linuxmusl-arm64@0.33.3': + '@img/sharp-linuxmusl-arm64@0.33.4': optionalDependencies: '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 optional: true - '@img/sharp-linuxmusl-x64@0.33.3': + '@img/sharp-linuxmusl-x64@0.33.4': optionalDependencies: '@img/sharp-libvips-linuxmusl-x64': 1.0.2 optional: true - '@img/sharp-wasm32@0.33.3': + '@img/sharp-wasm32@0.33.4': dependencies: '@emnapi/runtime': 1.1.1 optional: true - '@img/sharp-win32-ia32@0.33.3': + '@img/sharp-win32-ia32@0.33.4': optional: true - '@img/sharp-win32-x64@0.33.3': + '@img/sharp-win32-x64@0.33.4': optional: true '@inquirer/confirm@3.1.6': @@ -13441,7 +14265,7 @@ snapshots: '@inquirer/figures': 1.0.1 '@inquirer/type': 1.3.1 '@types/mute-stream': 0.0.4 - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/wrap-ansi': 3.0.0 ansi-escapes: 4.3.2 chalk: 4.1.2 @@ -13464,7 +14288,7 @@ snapshots: '@intlify/message-compiler@9.13.1': dependencies: '@intlify/shared': 9.13.1 - source-map-js: 1.0.2 + source-map-js: 1.2.0 '@intlify/shared@9.13.1': {} @@ -13492,7 +14316,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -13505,14 +14329,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.7.1 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.12.7) + jest-config: 29.7.0(@types/node@20.14.9) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -13524,7 +14348,7 @@ snapshots: jest-util: 29.7.0 jest-validate: 29.7.0 jest-watcher: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.7 pretty-format: 29.7.0 slash: 3.0.0 strip-ansi: 6.0.1 @@ -13541,7 +14365,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -13559,7 +14383,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.12.7 + '@types/node': 20.14.9 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -13581,7 +14405,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.18 - '@types/node': 20.12.7 + '@types/node': 20.14.9 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -13639,7 +14463,7 @@ snapshots: jest-haste-map: 29.7.0 jest-regex-util: 29.6.3 jest-util: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.7 pirates: 4.0.5 slash: 3.0.0 write-file-atomic: 4.0.2 @@ -13651,19 +14475,19 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.4 '@types/istanbul-reports': 3.0.1 - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/yargs': 17.0.19 chalk: 4.1.2 - '@joshwooding/vite-plugin-react-docgen-typescript@0.3.0(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))': + '@joshwooding/vite-plugin-react-docgen-typescript@0.3.1(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))': dependencies: glob: 7.2.3 glob-promise: 4.2.2(glob@7.2.3) magic-string: 0.27.0 - react-docgen-typescript: 2.2.2(typescript@5.5.2) - vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) + react-docgen-typescript: 2.2.2(typescript@5.5.3) + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 '@jridgewell/gen-mapping@0.3.2': dependencies: @@ -13671,14 +14495,22 @@ snapshots: '@jridgewell/sourcemap-codec': 1.4.15 '@jridgewell/trace-mapping': 0.3.18 + '@jridgewell/gen-mapping@0.3.5': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.25 + '@jridgewell/resolve-uri@3.1.0': {} '@jridgewell/set-array@1.1.2': {} + '@jridgewell/set-array@1.2.1': {} + '@jridgewell/source-map@0.3.5': dependencies: - '@jridgewell/gen-mapping': 0.3.2 - '@jridgewell/trace-mapping': 0.3.18 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 '@jridgewell/sourcemap-codec@1.4.14': {} @@ -13689,6 +14521,11 @@ snapshots: '@jridgewell/resolve-uri': 3.1.0 '@jridgewell/sourcemap-codec': 1.4.14 + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.0 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jsdevtools/ono@7.1.3': {} '@kurkle/color@0.3.2': {} @@ -13727,23 +14564,23 @@ snapshots: '@types/react': 18.0.28 react: 18.3.1 - '@microsoft/api-extractor-model@7.28.14(@types/node@20.12.7)': + '@microsoft/api-extractor-model@7.29.2(@types/node@20.14.9)': dependencies: - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - '@rushstack/node-core-library': 4.1.0(@types/node@20.12.7) + '@microsoft/tsdoc': 0.15.0 + '@microsoft/tsdoc-config': 0.17.0 + '@rushstack/node-core-library': 5.4.1(@types/node@20.14.9) transitivePeerDependencies: - '@types/node' - '@microsoft/api-extractor@7.43.1(@types/node@20.12.7)': + '@microsoft/api-extractor@7.47.0(@types/node@20.14.9)': dependencies: - '@microsoft/api-extractor-model': 7.28.14(@types/node@20.12.7) - '@microsoft/tsdoc': 0.14.2 - '@microsoft/tsdoc-config': 0.16.2 - '@rushstack/node-core-library': 4.1.0(@types/node@20.12.7) + '@microsoft/api-extractor-model': 7.29.2(@types/node@20.14.9) + '@microsoft/tsdoc': 0.15.0 + '@microsoft/tsdoc-config': 0.17.0 + '@rushstack/node-core-library': 5.4.1(@types/node@20.14.9) '@rushstack/rig-package': 0.5.2 - '@rushstack/terminal': 0.10.1(@types/node@20.12.7) - '@rushstack/ts-command-line': 4.19.2(@types/node@20.12.7) + '@rushstack/terminal': 0.13.0(@types/node@20.14.9) + '@rushstack/ts-command-line': 4.22.0(@types/node@20.14.9) lodash: 4.17.21 minimatch: 3.0.8 resolve: 1.22.8 @@ -13753,43 +14590,31 @@ snapshots: transitivePeerDependencies: - '@types/node' - '@microsoft/tsdoc-config@0.16.2': + '@microsoft/tsdoc-config@0.17.0': dependencies: - '@microsoft/tsdoc': 0.14.2 - ajv: 6.12.6 + '@microsoft/tsdoc': 0.15.0 + ajv: 8.12.0 jju: 1.4.0 - resolve: 1.19.0 + resolve: 1.22.8 - '@microsoft/tsdoc@0.14.2': {} + '@microsoft/tsdoc@0.15.0': {} '@misskey-dev/browser-image-resizer@2024.1.0': {} - '@misskey-dev/eslint-plugin@1.0.0(@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0)(typescript@5.3.3))(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0))(eslint@8.53.0)': + '@misskey-dev/eslint-plugin@2.0.2(@eslint/compat@1.1.0)(@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3))(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0))(eslint@9.6.0)(globals@15.7.0)': dependencies: - '@typescript-eslint/eslint-plugin': 6.11.0(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0)(typescript@5.3.3) - '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.3.3) - eslint: 8.53.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0) - - '@misskey-dev/eslint-plugin@1.0.0(@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3))(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0))(eslint@8.57.0)': - dependencies: - '@typescript-eslint/eslint-plugin': 7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3) - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.3.3) - eslint: 8.57.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0) - - '@misskey-dev/eslint-plugin@1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0)': - dependencies: - '@typescript-eslint/eslint-plugin': 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.2) - eslint: 8.57.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0) + '@eslint/compat': 1.1.0 + '@typescript-eslint/eslint-plugin': 7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3) + '@typescript-eslint/parser': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + eslint: 9.6.0 + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0) + globals: 15.7.0 '@misskey-dev/sharp-read-bmp@1.2.0': dependencies: decode-bmp: 0.2.1 decode-ico: 0.4.1 - sharp: 0.33.3 + sharp: 0.33.4 '@misskey-dev/summaly@5.1.0': dependencies: @@ -13833,7 +14658,7 @@ snapshots: '@mswjs/cookies@1.1.0': {} - '@mswjs/interceptors@0.26.15': + '@mswjs/interceptors@0.29.1': dependencies: '@open-draft/deferred-promise': 2.2.0 '@open-draft/logger': 0.3.0 @@ -13842,44 +14667,44 @@ snapshots: outvariant: 1.4.2 strict-event-emitter: 0.5.1 - '@napi-rs/canvas-android-arm64@0.1.52': + '@napi-rs/canvas-android-arm64@0.1.53': optional: true - '@napi-rs/canvas-darwin-arm64@0.1.52': + '@napi-rs/canvas-darwin-arm64@0.1.53': optional: true - '@napi-rs/canvas-darwin-x64@0.1.52': + '@napi-rs/canvas-darwin-x64@0.1.53': optional: true - '@napi-rs/canvas-linux-arm-gnueabihf@0.1.52': + '@napi-rs/canvas-linux-arm-gnueabihf@0.1.53': optional: true - '@napi-rs/canvas-linux-arm64-gnu@0.1.52': + '@napi-rs/canvas-linux-arm64-gnu@0.1.53': optional: true - '@napi-rs/canvas-linux-arm64-musl@0.1.52': + '@napi-rs/canvas-linux-arm64-musl@0.1.53': optional: true - '@napi-rs/canvas-linux-x64-gnu@0.1.52': + '@napi-rs/canvas-linux-x64-gnu@0.1.53': optional: true - '@napi-rs/canvas-linux-x64-musl@0.1.52': + '@napi-rs/canvas-linux-x64-musl@0.1.53': optional: true - '@napi-rs/canvas-win32-x64-msvc@0.1.52': + '@napi-rs/canvas-win32-x64-msvc@0.1.53': optional: true - '@napi-rs/canvas@0.1.52': + '@napi-rs/canvas@0.1.53': optionalDependencies: - '@napi-rs/canvas-android-arm64': 0.1.52 - '@napi-rs/canvas-darwin-arm64': 0.1.52 - '@napi-rs/canvas-darwin-x64': 0.1.52 - '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.52 - '@napi-rs/canvas-linux-arm64-gnu': 0.1.52 - '@napi-rs/canvas-linux-arm64-musl': 0.1.52 - '@napi-rs/canvas-linux-x64-gnu': 0.1.52 - '@napi-rs/canvas-linux-x64-musl': 0.1.52 - '@napi-rs/canvas-win32-x64-msvc': 0.1.52 + '@napi-rs/canvas-android-arm64': 0.1.53 + '@napi-rs/canvas-darwin-arm64': 0.1.53 + '@napi-rs/canvas-darwin-x64': 0.1.53 + '@napi-rs/canvas-linux-arm-gnueabihf': 0.1.53 + '@napi-rs/canvas-linux-arm64-gnu': 0.1.53 + '@napi-rs/canvas-linux-arm64-musl': 0.1.53 + '@napi-rs/canvas-linux-x64-gnu': 0.1.53 + '@napi-rs/canvas-linux-x64-musl': 0.1.53 + '@napi-rs/canvas-win32-x64-msvc': 0.1.53 '@ndelangen/get-tarball@3.0.7': dependencies: @@ -13887,49 +14712,51 @@ snapshots: pump: 3.0.0 tar-fs: 2.1.1 - '@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1)': + '@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1)': dependencies: iterare: 1.2.1 reflect-metadata: 0.2.2 rxjs: 7.8.1 - tslib: 2.6.2 + tslib: 2.6.3 uid: 2.0.2 - '@nestjs/core@10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.8)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)': + '@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1)': dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1) '@nuxtjs/opencollective': 0.3.2(encoding@0.1.13) fast-safe-stringify: 2.1.1 iterare: 1.2.1 path-to-regexp: 3.2.0 reflect-metadata: 0.2.2 rxjs: 7.8.1 - tslib: 2.6.2 + tslib: 2.6.3 uid: 2.0.2 optionalDependencies: - '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8) + '@nestjs/platform-express': 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10) transitivePeerDependencies: - encoding - '@nestjs/platform-express@10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8)': + '@nestjs/platform-express@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10)': dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/core': 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.8)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/common': 10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1) body-parser: 1.20.2 cors: 2.8.5 express: 4.19.2 multer: 1.4.4-lts.1 - tslib: 2.6.2 + tslib: 2.6.3 transitivePeerDependencies: - supports-color - '@nestjs/testing@10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.8)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8))': + '@nestjs/testing@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10))': dependencies: - '@nestjs/common': 10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1) - '@nestjs/core': 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.8)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1) - tslib: 2.6.2 + '@nestjs/common': 10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1) + '@nestjs/core': 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/platform-express@10.3.10)(encoding@0.1.13)(reflect-metadata@0.2.2)(rxjs@7.8.1) + tslib: 2.6.3 optionalDependencies: - '@nestjs/platform-express': 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8) + '@nestjs/platform-express': 10.3.10(@nestjs/common@10.3.10(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.10) + + '@noble/hashes@1.4.0': {} '@nodelib/fs.scandir@2.1.5': dependencies: @@ -13941,7 +14768,7 @@ snapshots: '@nodelib/fs.walk@1.2.8': dependencies: '@nodelib/fs.scandir': 2.1.5 - fastq: 1.15.0 + fastq: 1.17.1 '@npmcli/agent@2.2.0': dependencies: @@ -13990,153 +14817,167 @@ snapshots: '@open-draft/until@2.1.0': {} - '@opentelemetry/api-logs@0.51.1': + '@opentelemetry/api-logs@0.52.1': dependencies: - '@opentelemetry/api': 1.8.0 + '@opentelemetry/api': 1.9.0 - '@opentelemetry/api@1.8.0': {} + '@opentelemetry/api@1.9.0': {} - '@opentelemetry/context-async-hooks@1.24.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/context-async-hooks@1.25.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 + '@opentelemetry/api': 1.9.0 - '@opentelemetry/core@1.24.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/core@1.24.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 + '@opentelemetry/api': 1.9.0 '@opentelemetry/semantic-conventions': 1.24.1 - '@opentelemetry/instrumentation-connect@0.36.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/instrumentation-connect@0.37.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 '@types/connect': 3.4.36 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-express@0.39.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-express@0.40.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-fastify@0.36.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-fastify@0.37.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-graphql@0.40.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-graphql@0.41.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-hapi@0.38.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-hapi@0.39.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-http@0.51.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-http@0.52.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 semver: 7.6.0 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-ioredis@0.40.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-ioredis@0.41.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) '@opentelemetry/redis-common': 0.36.2 - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/semantic-conventions': 1.25.1 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-koa@0.40.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-koa@0.41.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 '@types/koa': 2.14.0 '@types/koa__router': 12.0.3 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mongodb@0.43.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-mongodb@0.45.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-metrics': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-metrics': 1.24.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mongoose@0.38.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-mongoose@0.39.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mysql2@0.38.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-mysql2@0.39.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 - '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.8.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-mysql@0.38.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-mysql@0.39.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 '@types/mysql': 2.15.22 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-nestjs-core@0.37.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-nestjs-core@0.38.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation-pg@0.41.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-pg@0.42.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 - '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.8.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + '@opentelemetry/sql-common': 0.40.1(@opentelemetry/api@1.9.0) '@types/pg': 8.6.1 '@types/pg-pool': 2.0.4 transitivePeerDependencies: - supports-color - '@opentelemetry/instrumentation@0.43.0(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation-redis-4@0.40.0(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/redis-common': 0.36.2 + '@opentelemetry/semantic-conventions': 1.25.1 + transitivePeerDependencies: + - supports-color + + '@opentelemetry/instrumentation@0.43.0(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 '@types/shimmer': 1.0.5 import-in-the-middle: 1.4.2 require-in-the-middle: 7.3.0 @@ -14146,12 +14987,12 @@ snapshots: - supports-color optional: true - '@opentelemetry/instrumentation@0.51.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/api-logs': 0.51.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/api-logs': 0.52.1 '@types/shimmer': 1.0.5 - import-in-the-middle: 1.7.4 + import-in-the-middle: 1.8.1 require-in-the-middle: 7.3.0 semver: 7.6.0 shimmer: 1.2.1 @@ -14160,32 +15001,40 @@ snapshots: '@opentelemetry/redis-common@0.36.2': {} - '@opentelemetry/resources@1.24.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/resources@1.24.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.9.0) '@opentelemetry/semantic-conventions': 1.24.1 - '@opentelemetry/sdk-metrics@1.24.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/resources@1.25.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.24.1(@opentelemetry/api@1.8.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + + '@opentelemetry/sdk-metrics@1.24.1(@opentelemetry/api@1.9.0)': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.24.1(@opentelemetry/api@1.9.0) lodash.merge: 4.6.2 - '@opentelemetry/sdk-trace-base@1.24.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 '@opentelemetry/semantic-conventions@1.24.1': {} - '@opentelemetry/sql-common@0.40.1(@opentelemetry/api@1.8.0)': + '@opentelemetry/semantic-conventions@1.25.1': {} + + '@opentelemetry/sql-common@0.40.1(@opentelemetry/api@1.9.0)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) '@peculiar/asn1-android@2.3.10': dependencies: @@ -14230,35 +15079,149 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@prisma/instrumentation@5.14.0': + '@prisma/instrumentation@5.16.0': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-trace-base': 1.24.1(@opentelemetry/api@1.8.0) + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) transitivePeerDependencies: - supports-color - '@radix-ui/react-compose-refs@1.0.1(@types/react@18.0.28)(react@18.3.1)': + '@radix-ui/primitive@1.1.0': {} + + '@radix-ui/react-compose-refs@1.1.0(@types/react@18.0.28)(react@18.3.1)': dependencies: - '@babel/runtime': 7.23.4 react: 18.3.1 optionalDependencies: '@types/react': 18.0.28 - '@radix-ui/react-slot@1.0.2(@types/react@18.0.28)(react@18.3.1)': + '@radix-ui/react-context@1.1.0(@types/react@18.0.28)(react@18.3.1)': dependencies: - '@babel/runtime': 7.23.4 - '@radix-ui/react-compose-refs': 1.0.1(@types/react@18.0.28)(react@18.3.1) react: 18.3.1 optionalDependencies: '@types/react': 18.0.28 - '@readme/better-ajv-errors@1.6.0(ajv@8.13.0)': + '@radix-ui/react-dialog@1.1.1(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-focus-scope': 1.1.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-portal': 1.1.1(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.0.28)(react@18.3.1) + aria-hidden: 1.2.4 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + react-remove-scroll: 2.5.7(@types/react@18.0.28)(react@18.3.1) + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-dismissable-layer@1.1.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-use-escape-keydown': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-focus-guards@1.1.0(@types/react@18.0.28)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-focus-scope@1.1.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-primitive': 2.0.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-id@1.1.0(@types/react@18.0.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-portal@1.1.1(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-primitive': 2.0.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-presence@1.1.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-primitive@2.0.0(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/react-slot': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-slot@1.1.0(@types/react@18.0.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.0.28)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.0.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-use-escape-keydown@1.1.0(@types/react@18.0.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.0.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.0.28 + + '@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.0.28)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.0.28 + + '@readme/better-ajv-errors@1.6.0(ajv@8.16.0)': dependencies: '@babel/code-frame': 7.23.5 '@babel/runtime': 7.23.4 '@humanwhocodes/momoa': 2.0.4 - ajv: 8.13.0 + ajv: 8.16.0 chalk: 4.1.2 json-to-ast: 2.1.0 jsonpointer: 5.0.1 @@ -14276,181 +15239,186 @@ snapshots: '@apidevtools/openapi-schemas': 2.1.0 '@apidevtools/swagger-methods': 3.0.2 '@jsdevtools/ono': 7.1.3 - '@readme/better-ajv-errors': 1.6.0(ajv@8.13.0) + '@readme/better-ajv-errors': 1.6.0(ajv@8.16.0) '@readme/json-schema-ref-parser': 1.2.0 - ajv: 8.13.0 - ajv-draft-04: 1.0.0(ajv@8.13.0) + ajv: 8.16.0 + ajv-draft-04: 1.0.0(ajv@8.16.0) call-me-maybe: 1.0.2 openapi-types: 12.1.3 - '@rollup/plugin-json@6.1.0(rollup@4.17.2)': + '@rollup/plugin-json@6.1.0(rollup@4.18.0)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/plugin-replace@5.0.5(rollup@4.17.2)': + '@rollup/plugin-replace@5.0.7(rollup@4.18.0)': dependencies: - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) - magic-string: 0.30.7 + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) + magic-string: 0.30.10 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/pluginutils@5.1.0(rollup@4.17.2)': + '@rollup/pluginutils@5.1.0(rollup@4.18.0)': dependencies: '@types/estree': 1.0.5 estree-walker: 2.0.2 picomatch: 2.3.1 optionalDependencies: - rollup: 4.17.2 + rollup: 4.18.0 - '@rollup/rollup-android-arm-eabi@4.17.2': + '@rollup/rollup-android-arm-eabi@4.18.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': + '@rollup/rollup-android-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': + '@rollup/rollup-darwin-arm64@4.18.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': + '@rollup/rollup-darwin-x64@4.18.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': + '@rollup/rollup-linux-arm-gnueabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': + '@rollup/rollup-linux-arm-musleabihf@4.18.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': + '@rollup/rollup-linux-arm64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': + '@rollup/rollup-linux-arm64-musl@4.18.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': + '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': + '@rollup/rollup-linux-riscv64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': + '@rollup/rollup-linux-s390x-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-gnu@4.17.2': + '@rollup/rollup-linux-x64-gnu@4.18.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': + '@rollup/rollup-linux-x64-musl@4.18.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': + '@rollup/rollup-win32-arm64-msvc@4.18.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': + '@rollup/rollup-win32-ia32-msvc@4.18.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': + '@rollup/rollup-win32-x64-msvc@4.18.0': optional: true - '@rushstack/node-core-library@4.1.0(@types/node@20.12.7)': + '@rushstack/node-core-library@5.4.1(@types/node@20.14.9)': dependencies: + ajv: 8.13.0 + ajv-draft-04: 1.0.0(ajv@8.13.0) + ajv-formats: 3.0.1(ajv@8.13.0) fs-extra: 7.0.1 import-lazy: 4.0.0 jju: 1.4.0 resolve: 1.22.8 semver: 7.5.4 - z-schema: 5.0.5 optionalDependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@rushstack/rig-package@0.5.2': dependencies: resolve: 1.22.8 strip-json-comments: 3.1.1 - '@rushstack/terminal@0.10.1(@types/node@20.12.7)': + '@rushstack/terminal@0.13.0(@types/node@20.14.9)': dependencies: - '@rushstack/node-core-library': 4.1.0(@types/node@20.12.7) + '@rushstack/node-core-library': 5.4.1(@types/node@20.14.9) supports-color: 8.1.1 optionalDependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 - '@rushstack/ts-command-line@4.19.2(@types/node@20.12.7)': + '@rushstack/ts-command-line@4.22.0(@types/node@20.14.9)': dependencies: - '@rushstack/terminal': 0.10.1(@types/node@20.12.7) + '@rushstack/terminal': 0.13.0(@types/node@20.14.9) '@types/argparse': 1.0.38 argparse: 1.0.10 string-argv: 0.3.1 transitivePeerDependencies: - '@types/node' - '@sentry/core@8.5.0': - dependencies: - '@sentry/types': 8.5.0 - '@sentry/utils': 8.5.0 + '@sec-ant/readable-stream@0.4.1': {} - '@sentry/node@8.5.0': + '@sentry/core@8.13.0': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/context-async-hooks': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-connect': 0.36.0(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-express': 0.39.0(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-fastify': 0.36.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-graphql': 0.40.0(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-hapi': 0.38.0(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-http': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-ioredis': 0.40.0(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-koa': 0.40.0(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-mongodb': 0.43.0(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-mongoose': 0.38.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-mysql': 0.38.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-mysql2': 0.38.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-nestjs-core': 0.37.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation-pg': 0.41.0(@opentelemetry/api@1.8.0) - '@opentelemetry/resources': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-trace-base': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 - '@prisma/instrumentation': 5.14.0 - '@sentry/core': 8.5.0 - '@sentry/opentelemetry': 8.5.0(@opentelemetry/api@1.8.0)(@opentelemetry/core@1.24.1(@opentelemetry/api@1.8.0))(@opentelemetry/instrumentation@0.51.1(@opentelemetry/api@1.8.0))(@opentelemetry/sdk-trace-base@1.24.1(@opentelemetry/api@1.8.0))(@opentelemetry/semantic-conventions@1.24.1) - '@sentry/types': 8.5.0 - '@sentry/utils': 8.5.0 + '@sentry/types': 8.13.0 + '@sentry/utils': 8.13.0 + + '@sentry/node@8.13.0': + dependencies: + '@opentelemetry/api': 1.9.0 + '@opentelemetry/context-async-hooks': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-connect': 0.37.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-express': 0.40.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-fastify': 0.37.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-graphql': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-hapi': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-http': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-ioredis': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-koa': 0.41.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongodb': 0.45.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mongoose': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-mysql2': 0.39.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-nestjs-core': 0.38.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-pg': 0.42.0(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation-redis-4': 0.40.0(@opentelemetry/api@1.9.0) + '@opentelemetry/resources': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + '@prisma/instrumentation': 5.16.0 + '@sentry/core': 8.13.0 + '@sentry/opentelemetry': 8.13.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1) + '@sentry/types': 8.13.0 + '@sentry/utils': 8.13.0 optionalDependencies: opentelemetry-instrumentation-fetch-node: 1.2.0 transitivePeerDependencies: - supports-color - '@sentry/opentelemetry@8.5.0(@opentelemetry/api@1.8.0)(@opentelemetry/core@1.24.1(@opentelemetry/api@1.8.0))(@opentelemetry/instrumentation@0.51.1(@opentelemetry/api@1.8.0))(@opentelemetry/sdk-trace-base@1.24.1(@opentelemetry/api@1.8.0))(@opentelemetry/semantic-conventions@1.24.1)': + '@sentry/opentelemetry@8.13.0(@opentelemetry/api@1.9.0)(@opentelemetry/core@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.52.1(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@1.25.1(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.25.1)': dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/core': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/instrumentation': 0.51.1(@opentelemetry/api@1.8.0) - '@opentelemetry/sdk-trace-base': 1.24.1(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 - '@sentry/core': 8.5.0 - '@sentry/types': 8.5.0 - '@sentry/utils': 8.5.0 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/core': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/instrumentation': 0.52.1(@opentelemetry/api@1.9.0) + '@opentelemetry/sdk-trace-base': 1.25.1(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 + '@sentry/core': 8.13.0 + '@sentry/types': 8.13.0 + '@sentry/utils': 8.13.0 - '@sentry/profiling-node@8.5.0': + '@sentry/profiling-node@8.13.0': dependencies: - '@sentry/core': 8.5.0 - '@sentry/node': 8.5.0 - '@sentry/types': 8.5.0 - '@sentry/utils': 8.5.0 + '@sentry/core': 8.13.0 + '@sentry/node': 8.13.0 + '@sentry/types': 8.13.0 + '@sentry/utils': 8.13.0 detect-libc: 2.0.3 node-abi: 3.62.0 transitivePeerDependencies: - supports-color - '@sentry/types@8.5.0': {} + '@sentry/types@8.13.0': {} - '@sentry/utils@8.5.0': + '@sentry/utils@8.13.0': dependencies: - '@sentry/types': 8.5.0 + '@sentry/types': 8.13.0 - '@shikijs/core@1.4.0': {} + '@shikijs/core@1.10.0': {} '@sideway/address@4.1.4': dependencies: @@ -14482,7 +15450,11 @@ snapshots: '@sindresorhus/is@5.3.0': {} - '@sindresorhus/is@6.1.0': {} + '@sindresorhus/is@6.3.1': {} + + '@sindresorhus/merge-streams@2.3.0': {} + + '@sindresorhus/merge-streams@4.0.0': {} '@sinonjs/commons@2.0.0': dependencies: @@ -14508,154 +15480,172 @@ snapshots: '@sinonjs/text-encoding@0.7.2': {} - '@smithy/abort-controller@2.0.14': - dependencies: - '@smithy/types': 2.6.0 - tslib: 2.6.2 - '@smithy/abort-controller@2.2.0': dependencies: '@smithy/types': 2.12.0 tslib: 2.6.2 - '@smithy/chunked-blob-reader-native@2.0.0': + '@smithy/abort-controller@3.1.1': dependencies: - '@smithy/util-base64': 2.0.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/chunked-blob-reader@2.0.0': + '@smithy/chunked-blob-reader-native@3.0.0': + dependencies: + '@smithy/util-base64': 3.0.0 + tslib: 2.6.2 + + '@smithy/chunked-blob-reader@3.0.0': dependencies: tslib: 2.6.2 - '@smithy/config-resolver@2.0.9': + '@smithy/config-resolver@3.0.4': dependencies: - '@smithy/node-config-provider': 2.0.11 - '@smithy/types': 2.6.0 - '@smithy/util-config-provider': 2.0.0 - '@smithy/util-middleware': 2.0.1 + '@smithy/node-config-provider': 3.1.3 + '@smithy/types': 3.3.0 + '@smithy/util-config-provider': 3.0.0 + '@smithy/util-middleware': 3.0.3 tslib: 2.6.2 - '@smithy/credential-provider-imds@2.0.11': + '@smithy/core@2.2.4': dependencies: - '@smithy/node-config-provider': 2.0.11 - '@smithy/property-provider': 2.0.9 - '@smithy/types': 2.6.0 - '@smithy/url-parser': 2.0.8 + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-retry': 3.0.7 + '@smithy/middleware-serde': 3.0.3 + '@smithy/protocol-http': 4.0.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 + '@smithy/util-middleware': 3.0.3 tslib: 2.6.2 - '@smithy/eventstream-codec@2.0.8': + '@smithy/credential-provider-imds@3.1.3': dependencies: - '@aws-crypto/crc32': 3.0.0 - '@smithy/types': 2.6.0 - '@smithy/util-hex-encoding': 2.0.0 + '@smithy/node-config-provider': 3.1.3 + '@smithy/property-provider': 3.1.3 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 tslib: 2.6.2 - '@smithy/eventstream-serde-browser@2.0.8': + '@smithy/eventstream-codec@3.1.2': dependencies: - '@smithy/eventstream-serde-universal': 2.0.8 - '@smithy/types': 2.6.0 + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 3.3.0 + '@smithy/util-hex-encoding': 3.0.0 tslib: 2.6.2 - '@smithy/eventstream-serde-config-resolver@2.0.8': + '@smithy/eventstream-serde-browser@3.0.4': dependencies: - '@smithy/types': 2.6.0 + '@smithy/eventstream-serde-universal': 3.0.4 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/eventstream-serde-node@2.0.8': + '@smithy/eventstream-serde-config-resolver@3.0.3': dependencies: - '@smithy/eventstream-serde-universal': 2.0.8 - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/eventstream-serde-universal@2.0.8': + '@smithy/eventstream-serde-node@3.0.4': dependencies: - '@smithy/eventstream-codec': 2.0.8 - '@smithy/types': 2.6.0 + '@smithy/eventstream-serde-universal': 3.0.4 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/fetch-http-handler@2.1.4': + '@smithy/eventstream-serde-universal@3.0.4': dependencies: - '@smithy/protocol-http': 3.0.10 - '@smithy/querystring-builder': 2.0.14 - '@smithy/types': 2.6.0 - '@smithy/util-base64': 2.0.0 + '@smithy/eventstream-codec': 3.1.2 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/hash-blob-browser@2.0.8': + '@smithy/fetch-http-handler@3.2.0': dependencies: - '@smithy/chunked-blob-reader': 2.0.0 - '@smithy/chunked-blob-reader-native': 2.0.0 - '@smithy/types': 2.6.0 + '@smithy/protocol-http': 4.0.3 + '@smithy/querystring-builder': 3.0.3 + '@smithy/types': 3.3.0 + '@smithy/util-base64': 3.0.0 tslib: 2.6.2 - '@smithy/hash-node@2.0.8': + '@smithy/hash-blob-browser@3.1.2': dependencies: - '@smithy/types': 2.6.0 - '@smithy/util-buffer-from': 2.0.0 - '@smithy/util-utf8': 2.0.0 + '@smithy/chunked-blob-reader': 3.0.0 + '@smithy/chunked-blob-reader-native': 3.0.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/hash-stream-node@2.0.8': + '@smithy/hash-node@3.0.3': dependencies: - '@smithy/types': 2.6.0 - '@smithy/util-utf8': 2.0.0 + '@smithy/types': 3.3.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 tslib: 2.6.2 - '@smithy/invalid-dependency@2.0.8': + '@smithy/hash-stream-node@3.1.2': dependencies: - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.2 + + '@smithy/invalid-dependency@3.0.3': + dependencies: + '@smithy/types': 3.3.0 tslib: 2.6.2 '@smithy/is-array-buffer@2.0.0': dependencies: tslib: 2.6.2 - '@smithy/md5-js@2.0.8': + '@smithy/is-array-buffer@3.0.0': dependencies: - '@smithy/types': 2.6.0 - '@smithy/util-utf8': 2.0.0 tslib: 2.6.2 - '@smithy/middleware-content-length@2.0.10': + '@smithy/md5-js@3.0.3': dependencies: - '@smithy/protocol-http': 3.0.10 - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 + '@smithy/util-utf8': 3.0.0 tslib: 2.6.2 - '@smithy/middleware-endpoint@2.0.8': + '@smithy/middleware-content-length@3.0.3': dependencies: - '@smithy/middleware-serde': 2.0.8 - '@smithy/types': 2.6.0 - '@smithy/url-parser': 2.0.8 - '@smithy/util-middleware': 2.0.1 + '@smithy/protocol-http': 4.0.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/middleware-retry@2.0.11': + '@smithy/middleware-endpoint@3.0.4': dependencies: - '@smithy/node-config-provider': 2.0.11 - '@smithy/protocol-http': 3.0.10 - '@smithy/service-error-classification': 2.0.1 - '@smithy/types': 2.6.0 - '@smithy/util-middleware': 2.0.1 - '@smithy/util-retry': 2.0.1 - tslib: 2.6.2 - uuid: 8.3.2 - - '@smithy/middleware-serde@2.0.8': - dependencies: - '@smithy/types': 2.6.0 + '@smithy/middleware-serde': 3.0.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/shared-ini-file-loader': 3.1.3 + '@smithy/types': 3.3.0 + '@smithy/url-parser': 3.0.3 + '@smithy/util-middleware': 3.0.3 tslib: 2.6.2 - '@smithy/middleware-stack@2.0.1': + '@smithy/middleware-retry@3.0.7': dependencies: - '@smithy/types': 2.6.0 + '@smithy/node-config-provider': 3.1.3 + '@smithy/protocol-http': 4.0.3 + '@smithy/service-error-classification': 3.0.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 + '@smithy/util-middleware': 3.0.3 + '@smithy/util-retry': 3.0.3 + tslib: 2.6.2 + uuid: 9.0.1 + + '@smithy/middleware-serde@3.0.3': + dependencies: + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/node-config-provider@2.0.11': + '@smithy/middleware-stack@3.0.3': dependencies: - '@smithy/property-provider': 2.0.9 - '@smithy/shared-ini-file-loader': 2.0.10 - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 + tslib: 2.6.2 + + '@smithy/node-config-provider@3.1.3': + dependencies: + '@smithy/property-provider': 3.1.3 + '@smithy/shared-ini-file-loader': 3.1.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 '@smithy/node-http-handler@2.5.0': @@ -14666,14 +15656,17 @@ snapshots: '@smithy/types': 2.12.0 tslib: 2.6.2 - '@smithy/property-provider@2.0.9': + '@smithy/node-http-handler@3.1.1': dependencies: - '@smithy/types': 2.6.0 + '@smithy/abort-controller': 3.1.1 + '@smithy/protocol-http': 4.0.3 + '@smithy/querystring-builder': 3.0.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/protocol-http@3.0.10': + '@smithy/property-provider@3.1.3': dependencies: - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 '@smithy/protocol-http@3.3.0': @@ -14681,10 +15674,9 @@ snapshots: '@smithy/types': 2.12.0 tslib: 2.6.2 - '@smithy/querystring-builder@2.0.14': + '@smithy/protocol-http@4.0.3': dependencies: - '@smithy/types': 2.6.0 - '@smithy/util-uri-escape': 2.0.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 '@smithy/querystring-builder@2.2.0': @@ -14693,62 +15685,70 @@ snapshots: '@smithy/util-uri-escape': 2.2.0 tslib: 2.6.2 - '@smithy/querystring-parser@2.0.8': + '@smithy/querystring-builder@3.0.3': dependencies: - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 + '@smithy/util-uri-escape': 3.0.0 tslib: 2.6.2 - '@smithy/service-error-classification@2.0.1': + '@smithy/querystring-parser@3.0.3': dependencies: - '@smithy/types': 2.6.0 - - '@smithy/shared-ini-file-loader@2.0.10': - dependencies: - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/signature-v4@2.0.5': + '@smithy/service-error-classification@3.0.3': dependencies: - '@smithy/eventstream-codec': 2.0.8 - '@smithy/is-array-buffer': 2.0.0 - '@smithy/types': 2.6.0 - '@smithy/util-hex-encoding': 2.0.0 - '@smithy/util-middleware': 2.0.1 - '@smithy/util-uri-escape': 2.0.0 - '@smithy/util-utf8': 2.0.0 + '@smithy/types': 3.3.0 + + '@smithy/shared-ini-file-loader@3.1.3': + dependencies: + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/smithy-client@2.1.5': + '@smithy/signature-v4@3.1.2': dependencies: - '@smithy/middleware-stack': 2.0.1 - '@smithy/types': 2.6.0 - '@smithy/util-stream': 2.0.11 + '@smithy/is-array-buffer': 3.0.0 + '@smithy/types': 3.3.0 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-middleware': 3.0.3 + '@smithy/util-uri-escape': 3.0.0 + '@smithy/util-utf8': 3.0.0 + tslib: 2.6.2 + + '@smithy/smithy-client@3.1.5': + dependencies: + '@smithy/middleware-endpoint': 3.0.4 + '@smithy/middleware-stack': 3.0.3 + '@smithy/protocol-http': 4.0.3 + '@smithy/types': 3.3.0 + '@smithy/util-stream': 3.0.5 tslib: 2.6.2 '@smithy/types@2.12.0': dependencies: tslib: 2.6.2 - '@smithy/types@2.6.0': + '@smithy/types@3.3.0': dependencies: tslib: 2.6.2 - '@smithy/url-parser@2.0.8': + '@smithy/url-parser@3.0.3': dependencies: - '@smithy/querystring-parser': 2.0.8 - '@smithy/types': 2.6.0 + '@smithy/querystring-parser': 3.0.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/util-base64@2.0.0': + '@smithy/util-base64@3.0.0': dependencies: - '@smithy/util-buffer-from': 2.0.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-utf8': 3.0.0 tslib: 2.6.2 - '@smithy/util-body-length-browser@2.0.0': + '@smithy/util-body-length-browser@3.0.0': dependencies: tslib: 2.6.2 - '@smithy/util-body-length-node@2.1.0': + '@smithy/util-body-length-node@3.0.0': dependencies: tslib: 2.6.2 @@ -14757,117 +15757,136 @@ snapshots: '@smithy/is-array-buffer': 2.0.0 tslib: 2.6.2 - '@smithy/util-config-provider@2.0.0': + '@smithy/util-buffer-from@3.0.0': + dependencies: + '@smithy/is-array-buffer': 3.0.0 + tslib: 2.6.2 + + '@smithy/util-config-provider@3.0.0': dependencies: tslib: 2.6.2 - '@smithy/util-defaults-mode-browser@2.0.9': + '@smithy/util-defaults-mode-browser@3.0.7': dependencies: - '@smithy/property-provider': 2.0.9 - '@smithy/smithy-client': 2.1.5 - '@smithy/types': 2.6.0 + '@smithy/property-provider': 3.1.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 bowser: 2.11.0 tslib: 2.6.2 - '@smithy/util-defaults-mode-node@2.0.11': + '@smithy/util-defaults-mode-node@3.0.7': dependencies: - '@smithy/config-resolver': 2.0.9 - '@smithy/credential-provider-imds': 2.0.11 - '@smithy/node-config-provider': 2.0.11 - '@smithy/property-provider': 2.0.9 - '@smithy/smithy-client': 2.1.5 - '@smithy/types': 2.6.0 + '@smithy/config-resolver': 3.0.4 + '@smithy/credential-provider-imds': 3.1.3 + '@smithy/node-config-provider': 3.1.3 + '@smithy/property-provider': 3.1.3 + '@smithy/smithy-client': 3.1.5 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/util-hex-encoding@2.0.0': + '@smithy/util-endpoints@2.0.4': + dependencies: + '@smithy/node-config-provider': 3.1.3 + '@smithy/types': 3.3.0 + tslib: 2.6.2 + + '@smithy/util-hex-encoding@3.0.0': dependencies: tslib: 2.6.2 - '@smithy/util-middleware@2.0.1': + '@smithy/util-middleware@3.0.3': dependencies: - '@smithy/types': 2.6.0 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/util-retry@2.0.1': + '@smithy/util-retry@3.0.3': dependencies: - '@smithy/service-error-classification': 2.0.1 - '@smithy/types': 2.6.0 + '@smithy/service-error-classification': 3.0.3 + '@smithy/types': 3.3.0 tslib: 2.6.2 - '@smithy/util-stream@2.0.11': - dependencies: - '@smithy/fetch-http-handler': 2.1.4 - '@smithy/node-http-handler': 2.5.0 - '@smithy/types': 2.6.0 - '@smithy/util-base64': 2.0.0 - '@smithy/util-buffer-from': 2.0.0 - '@smithy/util-hex-encoding': 2.0.0 - '@smithy/util-utf8': 2.0.0 - tslib: 2.6.2 - - '@smithy/util-uri-escape@2.0.0': + '@smithy/util-stream@3.0.5': dependencies: + '@smithy/fetch-http-handler': 3.2.0 + '@smithy/node-http-handler': 3.1.1 + '@smithy/types': 3.3.0 + '@smithy/util-base64': 3.0.0 + '@smithy/util-buffer-from': 3.0.0 + '@smithy/util-hex-encoding': 3.0.0 + '@smithy/util-utf8': 3.0.0 tslib: 2.6.2 '@smithy/util-uri-escape@2.2.0': dependencies: tslib: 2.6.2 + '@smithy/util-uri-escape@3.0.0': + dependencies: + tslib: 2.6.2 + '@smithy/util-utf8@2.0.0': dependencies: '@smithy/util-buffer-from': 2.0.0 tslib: 2.6.2 - '@smithy/util-waiter@2.0.8': + '@smithy/util-utf8@3.0.0': dependencies: - '@smithy/abort-controller': 2.0.14 - '@smithy/types': 2.6.0 + '@smithy/util-buffer-from': 3.0.0 + tslib: 2.6.2 + + '@smithy/util-waiter@3.1.2': + dependencies: + '@smithy/abort-controller': 3.1.1 + '@smithy/types': 3.3.0 tslib: 2.6.2 '@sqltools/formatter@1.2.5': {} - '@storybook/addon-actions@8.0.9': + '@storybook/addon-actions@8.1.11': dependencies: - '@storybook/core-events': 8.0.9 + '@storybook/core-events': 8.1.11 '@storybook/global': 5.0.0 '@types/uuid': 9.0.8 dequal: 2.0.3 polished: 4.2.2 uuid: 9.0.1 - '@storybook/addon-backgrounds@8.0.9': + '@storybook/addon-backgrounds@8.1.11': dependencies: '@storybook/global': 5.0.0 memoizerific: 1.11.3 ts-dedent: 2.2.0 - '@storybook/addon-controls@8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@storybook/addon-controls@8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@storybook/blocks': 8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/blocks': 8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + dequal: 2.0.3 lodash: 4.17.21 ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' + - '@types/react-dom' - encoding + - prettier - react - react-dom - supports-color - '@storybook/addon-docs@8.0.9(encoding@0.1.13)': + '@storybook/addon-docs@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 '@mdx-js/react': 3.0.1(@types/react@18.0.28)(react@18.3.1) - '@storybook/blocks': 8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/client-logger': 8.0.9 - '@storybook/components': 8.0.9(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/csf-plugin': 8.0.9 - '@storybook/csf-tools': 8.0.9 + '@storybook/blocks': 8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/client-logger': 8.1.11 + '@storybook/components': 8.1.11(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/csf-plugin': 8.1.11 + '@storybook/csf-tools': 8.1.11 '@storybook/global': 5.0.0 - '@storybook/node-logger': 8.0.9 - '@storybook/preview-api': 8.0.9 - '@storybook/react-dom-shim': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/theming': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/types': 8.0.9 + '@storybook/node-logger': 8.1.11 + '@storybook/preview-api': 8.1.11 + '@storybook/react-dom-shim': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/theming': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 8.1.11 '@types/react': 18.0.28 fs-extra: 11.1.1 react: 18.3.1 @@ -14876,42 +15895,46 @@ snapshots: rehype-slug: 6.0.0 ts-dedent: 2.2.0 transitivePeerDependencies: + - '@types/react-dom' - encoding + - prettier - supports-color - '@storybook/addon-essentials@8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@storybook/addon-essentials@8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@storybook/addon-actions': 8.0.9 - '@storybook/addon-backgrounds': 8.0.9 - '@storybook/addon-controls': 8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/addon-docs': 8.0.9(encoding@0.1.13) - '@storybook/addon-highlight': 8.0.9 - '@storybook/addon-measure': 8.0.9 - '@storybook/addon-outline': 8.0.9 - '@storybook/addon-toolbars': 8.0.9 - '@storybook/addon-viewport': 8.0.9 - '@storybook/core-common': 8.0.9(encoding@0.1.13) - '@storybook/manager-api': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/node-logger': 8.0.9 - '@storybook/preview-api': 8.0.9 + '@storybook/addon-actions': 8.1.11 + '@storybook/addon-backgrounds': 8.1.11 + '@storybook/addon-controls': 8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/addon-docs': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/addon-highlight': 8.1.11 + '@storybook/addon-measure': 8.1.11 + '@storybook/addon-outline': 8.1.11 + '@storybook/addon-toolbars': 8.1.11 + '@storybook/addon-viewport': 8.1.11 + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/manager-api': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/node-logger': 8.1.11 + '@storybook/preview-api': 8.1.11 ts-dedent: 2.2.0 transitivePeerDependencies: - '@types/react' + - '@types/react-dom' - encoding + - prettier - react - react-dom - supports-color - '@storybook/addon-highlight@8.0.9': + '@storybook/addon-highlight@8.1.11': dependencies: '@storybook/global': 5.0.0 - '@storybook/addon-interactions@8.0.9(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3))': + '@storybook/addon-interactions@8.1.11(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9))(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1))': dependencies: '@storybook/global': 5.0.0 - '@storybook/instrumenter': 8.0.9 - '@storybook/test': 8.0.9(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)) - '@storybook/types': 8.0.9 + '@storybook/instrumenter': 8.1.11 + '@storybook/test': 8.1.11(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9))(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1)) + '@storybook/types': 8.1.11 polished: 4.2.2 ts-dedent: 2.2.0 transitivePeerDependencies: @@ -14921,58 +15944,58 @@ snapshots: - jest - vitest - '@storybook/addon-links@8.0.9(react@18.3.1)': + '@storybook/addon-links@8.1.11(react@18.3.1)': dependencies: - '@storybook/csf': 0.1.6 + '@storybook/csf': 0.1.9 '@storybook/global': 5.0.0 ts-dedent: 2.2.0 optionalDependencies: react: 18.3.1 - '@storybook/addon-mdx-gfm@8.0.9': + '@storybook/addon-mdx-gfm@8.1.11': dependencies: - '@storybook/node-logger': 8.0.9 + '@storybook/node-logger': 8.1.11 remark-gfm: 4.0.0 ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color - '@storybook/addon-measure@8.0.9': + '@storybook/addon-measure@8.1.11': dependencies: '@storybook/global': 5.0.0 - tiny-invariant: 1.3.1 + tiny-invariant: 1.3.3 - '@storybook/addon-outline@8.0.9': + '@storybook/addon-outline@8.1.11': dependencies: '@storybook/global': 5.0.0 ts-dedent: 2.2.0 - '@storybook/addon-storysource@8.0.9': + '@storybook/addon-storysource@8.1.11': dependencies: - '@storybook/source-loader': 8.0.9 + '@storybook/source-loader': 8.1.11 estraverse: 5.3.0 - tiny-invariant: 1.3.1 + tiny-invariant: 1.3.3 - '@storybook/addon-toolbars@8.0.9': {} + '@storybook/addon-toolbars@8.1.11': {} - '@storybook/addon-viewport@8.0.9': + '@storybook/addon-viewport@8.1.11': dependencies: memoizerific: 1.11.3 - '@storybook/blocks@8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@storybook/blocks@8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@storybook/channels': 8.0.9 - '@storybook/client-logger': 8.0.9 - '@storybook/components': 8.0.9(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/core-events': 8.0.9 - '@storybook/csf': 0.1.6 - '@storybook/docs-tools': 8.0.9(encoding@0.1.13) + '@storybook/channels': 8.1.11 + '@storybook/client-logger': 8.1.11 + '@storybook/components': 8.1.11(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/core-events': 8.1.11 + '@storybook/csf': 0.1.9 + '@storybook/docs-tools': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/global': 5.0.0 '@storybook/icons': 1.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/manager-api': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/preview-api': 8.0.9 - '@storybook/theming': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/types': 8.0.9 + '@storybook/manager-api': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/preview-api': 8.1.11 + '@storybook/theming': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 8.1.11 '@types/lodash': 4.14.191 color-convert: 2.0.1 dequal: 2.0.3 @@ -14990,20 +16013,22 @@ snapshots: react-dom: 18.3.1(react@18.3.1) transitivePeerDependencies: - '@types/react' + - '@types/react-dom' - encoding + - prettier - supports-color - '@storybook/builder-manager@8.0.9(encoding@0.1.13)': + '@storybook/builder-manager@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: '@fal-works/esbuild-plugin-global-externals': 2.1.2 - '@storybook/core-common': 8.0.9(encoding@0.1.13) - '@storybook/manager': 8.0.9 - '@storybook/node-logger': 8.0.9 + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/manager': 8.1.11 + '@storybook/node-logger': 8.1.11 '@types/ejs': 3.1.2 - '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15(esbuild@0.20.2) + '@yarnpkg/esbuild-plugin-pnp': 3.0.0-rc.15(esbuild@0.19.11) browser-assert: 1.2.1 - ejs: 3.1.9 - esbuild: 0.20.2 + ejs: 3.1.10 + esbuild: 0.19.11 esbuild-plugin-alias: 0.2.1 express: 4.19.2 fs-extra: 11.1.1 @@ -15011,55 +16036,57 @@ snapshots: util: 0.12.5 transitivePeerDependencies: - encoding + - prettier - supports-color - '@storybook/builder-vite@8.0.9(encoding@0.1.13)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))': + '@storybook/builder-vite@8.1.11(encoding@0.1.13)(prettier@3.3.2)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))': dependencies: - '@storybook/channels': 8.0.9 - '@storybook/client-logger': 8.0.9 - '@storybook/core-common': 8.0.9(encoding@0.1.13) - '@storybook/core-events': 8.0.9 - '@storybook/csf-plugin': 8.0.9 - '@storybook/node-logger': 8.0.9 - '@storybook/preview': 8.0.9 - '@storybook/preview-api': 8.0.9 - '@storybook/types': 8.0.9 + '@storybook/channels': 8.1.11 + '@storybook/client-logger': 8.1.11 + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/core-events': 8.1.11 + '@storybook/csf-plugin': 8.1.11 + '@storybook/node-logger': 8.1.11 + '@storybook/preview': 8.1.11 + '@storybook/preview-api': 8.1.11 + '@storybook/types': 8.1.11 '@types/find-cache-dir': 3.2.1 browser-assert: 1.2.1 - es-module-lexer: 0.9.3 - express: 4.18.2 + es-module-lexer: 1.5.4 + express: 4.19.2 find-cache-dir: 3.3.2 fs-extra: 11.1.1 - magic-string: 0.30.7 + magic-string: 0.30.10 ts-dedent: 2.2.0 - vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - encoding + - prettier - supports-color - '@storybook/channels@8.0.9': + '@storybook/channels@8.1.11': dependencies: - '@storybook/client-logger': 8.0.9 - '@storybook/core-events': 8.0.9 + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 '@storybook/global': 5.0.0 telejson: 7.2.0 - tiny-invariant: 1.3.1 + tiny-invariant: 1.3.3 - '@storybook/cli@8.0.9(@babel/preset-env@7.23.5(@babel/core@7.24.0))(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)': + '@storybook/cli@8.1.11(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)': dependencies: - '@babel/core': 7.24.0 - '@babel/types': 7.24.0 + '@babel/core': 7.24.7 + '@babel/types': 7.24.7 '@ndelangen/get-tarball': 3.0.7 - '@storybook/codemod': 8.0.9 - '@storybook/core-common': 8.0.9(encoding@0.1.13) - '@storybook/core-events': 8.0.9 - '@storybook/core-server': 8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) - '@storybook/csf-tools': 8.0.9 - '@storybook/node-logger': 8.0.9 - '@storybook/telemetry': 8.0.9(encoding@0.1.13) - '@storybook/types': 8.0.9 + '@storybook/codemod': 8.1.11 + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/core-events': 8.1.11 + '@storybook/core-server': 8.1.11(bufferutil@4.0.7)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) + '@storybook/csf-tools': 8.1.11 + '@storybook/node-logger': 8.1.11 + '@storybook/telemetry': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/types': 8.1.11 '@types/semver': 7.5.8 '@yarnpkg/fslib': 2.10.3 '@yarnpkg/libzip': 2.3.0 @@ -15073,17 +16100,17 @@ snapshots: fs-extra: 11.1.1 get-npm-tarball-url: 2.0.3 giget: 1.1.2 - globby: 11.1.0 - jscodeshift: 0.15.1(@babel/preset-env@7.23.5(@babel/core@7.24.0)) + globby: 14.0.1 + jscodeshift: 0.15.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)) leven: 3.1.0 ora: 5.4.1 - prettier: 3.2.5 + prettier: 3.3.2 prompts: 2.4.2 read-pkg-up: 7.0.1 semver: 7.6.0 strip-json-comments: 3.1.1 - tempy: 1.0.1 - tiny-invariant: 1.3.1 + tempy: 3.1.0 + tiny-invariant: 1.3.3 ts-dedent: 2.2.0 transitivePeerDependencies: - '@babel/preset-env' @@ -15094,104 +16121,112 @@ snapshots: - supports-color - utf-8-validate - '@storybook/client-logger@8.0.9': + '@storybook/client-logger@8.1.11': dependencies: '@storybook/global': 5.0.0 - '@storybook/codemod@8.0.9': + '@storybook/codemod@8.1.11': dependencies: - '@babel/core': 7.24.0 - '@babel/preset-env': 7.23.5(@babel/core@7.24.0) - '@babel/types': 7.24.0 - '@storybook/csf': 0.1.6 - '@storybook/csf-tools': 8.0.9 - '@storybook/node-logger': 8.0.9 - '@storybook/types': 8.0.9 + '@babel/core': 7.24.7 + '@babel/preset-env': 7.24.7(@babel/core@7.24.7) + '@babel/types': 7.24.7 + '@storybook/csf': 0.1.9 + '@storybook/csf-tools': 8.1.11 + '@storybook/node-logger': 8.1.11 + '@storybook/types': 8.1.11 '@types/cross-spawn': 6.0.2 cross-spawn: 7.0.3 - globby: 11.1.0 - jscodeshift: 0.15.1(@babel/preset-env@7.23.5(@babel/core@7.24.0)) + globby: 14.0.1 + jscodeshift: 0.15.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)) lodash: 4.17.21 - prettier: 3.2.5 + prettier: 3.3.2 recast: 0.23.6 - tiny-invariant: 1.3.1 + tiny-invariant: 1.3.3 transitivePeerDependencies: - supports-color - '@storybook/components@8.0.9(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@storybook/components@8.1.11(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@radix-ui/react-slot': 1.0.2(@types/react@18.0.28)(react@18.3.1) - '@storybook/client-logger': 8.0.9 - '@storybook/csf': 0.1.6 + '@radix-ui/react-dialog': 1.1.1(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.1.0(@types/react@18.0.28)(react@18.3.1) + '@storybook/client-logger': 8.1.11 + '@storybook/csf': 0.1.9 '@storybook/global': 5.0.0 '@storybook/icons': 1.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/theming': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/types': 8.0.9 + '@storybook/theming': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 8.1.11 memoizerific: 1.11.3 react: 18.3.1 react-dom: 18.3.1(react@18.3.1) util-deprecate: 1.0.2 transitivePeerDependencies: - '@types/react' + - '@types/react-dom' - '@storybook/core-common@8.0.9(encoding@0.1.13)': + '@storybook/core-common@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: - '@storybook/core-events': 8.0.9 - '@storybook/csf-tools': 8.0.9 - '@storybook/node-logger': 8.0.9 - '@storybook/types': 8.0.9 + '@storybook/core-events': 8.1.11 + '@storybook/csf-tools': 8.1.11 + '@storybook/node-logger': 8.1.11 + '@storybook/types': 8.1.11 '@yarnpkg/fslib': 2.10.3 '@yarnpkg/libzip': 2.3.0 chalk: 4.1.2 cross-spawn: 7.0.3 - esbuild: 0.20.2 - esbuild-register: 3.5.0(esbuild@0.20.2) + esbuild: 0.19.11 + esbuild-register: 3.5.0(esbuild@0.19.11) execa: 5.1.1 file-system-cache: 2.3.0 find-cache-dir: 3.3.2 find-up: 5.0.0 fs-extra: 11.1.1 - glob: 10.3.12 + glob: 10.4.2 handlebars: 4.7.7 lazy-universal-dotenv: 4.0.0 node-fetch: 2.7.0(encoding@0.1.13) picomatch: 2.3.1 pkg-dir: 5.0.0 + prettier-fallback: prettier@3.3.2 pretty-hrtime: 1.0.3 resolve-from: 5.0.0 semver: 7.6.0 - tempy: 1.0.1 - tiny-invariant: 1.3.1 + tempy: 3.1.0 + tiny-invariant: 1.3.3 ts-dedent: 2.2.0 util: 0.12.5 + optionalDependencies: + prettier: 3.3.2 transitivePeerDependencies: - encoding - supports-color - '@storybook/core-events@8.0.9': + '@storybook/core-events@8.1.11': dependencies: + '@storybook/csf': 0.1.9 ts-dedent: 2.2.0 - '@storybook/core-server@8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)': + '@storybook/core-server@8.1.11(bufferutil@4.0.7)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)': dependencies: '@aw-web-design/x-default-browser': 1.4.126 - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 + '@babel/parser': 7.24.7 '@discoveryjs/json-ext': 0.5.7 - '@storybook/builder-manager': 8.0.9(encoding@0.1.13) - '@storybook/channels': 8.0.9 - '@storybook/core-common': 8.0.9(encoding@0.1.13) - '@storybook/core-events': 8.0.9 - '@storybook/csf': 0.1.6 - '@storybook/csf-tools': 8.0.9 - '@storybook/docs-mdx': 3.0.0 + '@storybook/builder-manager': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/channels': 8.1.11 + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/core-events': 8.1.11 + '@storybook/csf': 0.1.9 + '@storybook/csf-tools': 8.1.11 + '@storybook/docs-mdx': 3.1.0-next.0 '@storybook/global': 5.0.0 - '@storybook/manager': 8.0.9 - '@storybook/manager-api': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/node-logger': 8.0.9 - '@storybook/preview-api': 8.0.9 - '@storybook/telemetry': 8.0.9(encoding@0.1.13) - '@storybook/types': 8.0.9 + '@storybook/manager': 8.1.11 + '@storybook/manager-api': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/node-logger': 8.1.11 + '@storybook/preview-api': 8.1.11 + '@storybook/telemetry': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/types': 8.1.11 '@types/detect-port': 1.3.2 + '@types/diff': 5.2.1 '@types/node': 18.17.15 '@types/pretty-hrtime': 1.0.1 '@types/semver': 7.5.8 @@ -15200,10 +16235,10 @@ snapshots: cli-table3: 0.6.3 compression: 1.7.4 detect-port: 1.5.1 - express: 4.18.2 + diff: 5.2.0 + express: 4.19.2 fs-extra: 11.1.1 - globby: 11.1.0 - ip: 2.0.1 + globby: 14.0.1 lodash: 4.17.21 open: 8.4.2 pretty-hrtime: 1.0.3 @@ -15211,59 +16246,61 @@ snapshots: read-pkg-up: 7.0.1 semver: 7.6.0 telejson: 7.2.0 - tiny-invariant: 1.3.1 + tiny-invariant: 1.3.3 ts-dedent: 2.2.0 util: 0.12.5 util-deprecate: 1.0.2 watchpack: 2.4.0 - ws: 8.17.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) + ws: 8.17.1(bufferutil@4.0.7)(utf-8-validate@6.0.3) transitivePeerDependencies: - bufferutil - encoding + - prettier - react - react-dom - supports-color - utf-8-validate - '@storybook/csf-plugin@8.0.9': + '@storybook/csf-plugin@8.1.11': dependencies: - '@storybook/csf-tools': 8.0.9 + '@storybook/csf-tools': 8.1.11 unplugin: 1.4.0 transitivePeerDependencies: - supports-color - '@storybook/csf-tools@8.0.9': + '@storybook/csf-tools@8.1.11': dependencies: - '@babel/generator': 7.23.6 - '@babel/parser': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 - '@storybook/csf': 0.1.6 - '@storybook/types': 8.0.9 + '@babel/generator': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + '@storybook/csf': 0.1.9 + '@storybook/types': 8.1.11 fs-extra: 11.1.1 recast: 0.23.6 ts-dedent: 2.2.0 transitivePeerDependencies: - supports-color - '@storybook/csf@0.1.6': + '@storybook/csf@0.1.9': dependencies: type-fest: 2.19.0 - '@storybook/docs-mdx@3.0.0': {} + '@storybook/docs-mdx@3.1.0-next.0': {} - '@storybook/docs-tools@8.0.9(encoding@0.1.13)': + '@storybook/docs-tools@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: - '@storybook/core-common': 8.0.9(encoding@0.1.13) - '@storybook/core-events': 8.0.9 - '@storybook/preview-api': 8.0.9 - '@storybook/types': 8.0.9 + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/core-events': 8.1.11 + '@storybook/preview-api': 8.1.11 + '@storybook/types': 8.1.11 '@types/doctrine': 0.0.3 assert: 2.1.0 doctrine: 3.0.0 lodash: 4.17.21 transitivePeerDependencies: - encoding + - prettier - supports-color '@storybook/global@5.0.0': {} @@ -15273,27 +16310,27 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/instrumenter@8.0.9': + '@storybook/instrumenter@8.1.11': dependencies: - '@storybook/channels': 8.0.9 - '@storybook/client-logger': 8.0.9 - '@storybook/core-events': 8.0.9 + '@storybook/channels': 8.1.11 + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 '@storybook/global': 5.0.0 - '@storybook/preview-api': 8.0.9 + '@storybook/preview-api': 8.1.11 '@vitest/utils': 1.6.0 util: 0.12.5 - '@storybook/manager-api@8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@storybook/manager-api@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@storybook/channels': 8.0.9 - '@storybook/client-logger': 8.0.9 - '@storybook/core-events': 8.0.9 - '@storybook/csf': 0.1.6 + '@storybook/channels': 8.1.11 + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 + '@storybook/csf': 0.1.9 '@storybook/global': 5.0.0 '@storybook/icons': 1.2.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/router': 8.0.9 - '@storybook/theming': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/types': 8.0.9 + '@storybook/router': 8.1.11 + '@storybook/theming': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 8.1.11 dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 @@ -15304,65 +16341,67 @@ snapshots: - react - react-dom - '@storybook/manager@8.0.9': {} + '@storybook/manager@8.1.11': {} - '@storybook/node-logger@8.0.9': {} + '@storybook/node-logger@8.1.11': {} - '@storybook/preview-api@8.0.9': + '@storybook/preview-api@8.1.11': dependencies: - '@storybook/channels': 8.0.9 - '@storybook/client-logger': 8.0.9 - '@storybook/core-events': 8.0.9 - '@storybook/csf': 0.1.6 + '@storybook/channels': 8.1.11 + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 + '@storybook/csf': 0.1.9 '@storybook/global': 5.0.0 - '@storybook/types': 8.0.9 + '@storybook/types': 8.1.11 '@types/qs': 6.9.7 dequal: 2.0.3 lodash: 4.17.21 memoizerific: 1.11.3 qs: 6.11.1 - tiny-invariant: 1.3.1 + tiny-invariant: 1.3.3 ts-dedent: 2.2.0 util-deprecate: 1.0.2 - '@storybook/preview@8.0.9': {} + '@storybook/preview@8.1.11': {} - '@storybook/react-dom-shim@8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@storybook/react-dom-shim@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/react-vite@8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.17.2)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))': + '@storybook/react-vite@8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.18.0)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))': dependencies: - '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.0(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)) - '@rollup/pluginutils': 5.1.0(rollup@4.17.2) - '@storybook/builder-vite': 8.0.9(encoding@0.1.13)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)) - '@storybook/node-logger': 8.0.9 - '@storybook/react': 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.2) + '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.1(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) + '@rollup/pluginutils': 5.1.0(rollup@4.18.0) + '@storybook/builder-vite': 8.1.11(encoding@0.1.13)(prettier@3.3.2)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) + '@storybook/node-logger': 8.1.11 + '@storybook/react': 8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3) + '@storybook/types': 8.1.11 find-up: 5.0.0 - magic-string: 0.30.7 + magic-string: 0.30.10 react: 18.3.1 react-docgen: 7.0.1 react-dom: 18.3.1(react@18.3.1) resolve: 1.22.8 tsconfig-paths: 4.2.0 - vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - '@preact/preset-vite' - encoding + - prettier - rollup - supports-color - typescript - vite-plugin-glimmerx - '@storybook/react@8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.2)': + '@storybook/react@8.1.11(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.3)': dependencies: - '@storybook/client-logger': 8.0.9 - '@storybook/docs-tools': 8.0.9(encoding@0.1.13) + '@storybook/client-logger': 8.1.11 + '@storybook/docs-tools': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/global': 5.0.0 - '@storybook/preview-api': 8.0.9 - '@storybook/react-dom-shim': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/types': 8.0.9 + '@storybook/preview-api': 8.1.11 + '@storybook/react-dom-shim': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 8.1.11 '@types/escodegen': 0.0.6 '@types/estree': 0.0.51 '@types/node': 18.17.15 @@ -15381,30 +16420,31 @@ snapshots: type-fest: 2.19.0 util-deprecate: 1.0.2 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - encoding + - prettier - supports-color - '@storybook/router@8.0.9': + '@storybook/router@8.1.11': dependencies: - '@storybook/client-logger': 8.0.9 + '@storybook/client-logger': 8.1.11 memoizerific: 1.11.3 qs: 6.11.1 - '@storybook/source-loader@8.0.9': + '@storybook/source-loader@8.1.11': dependencies: - '@storybook/csf': 0.1.6 - '@storybook/types': 8.0.9 + '@storybook/csf': 0.1.9 + '@storybook/types': 8.1.11 estraverse: 5.3.0 lodash: 4.17.21 - prettier: 3.2.5 + prettier: 3.3.2 - '@storybook/telemetry@8.0.9(encoding@0.1.13)': + '@storybook/telemetry@8.1.11(encoding@0.1.13)(prettier@3.3.2)': dependencies: - '@storybook/client-logger': 8.0.9 - '@storybook/core-common': 8.0.9(encoding@0.1.13) - '@storybook/csf-tools': 8.0.9 + '@storybook/client-logger': 8.1.11 + '@storybook/core-common': 8.1.11(encoding@0.1.13)(prettier@3.3.2) + '@storybook/csf-tools': 8.1.11 chalk: 4.1.2 detect-package-manager: 2.0.1 fetch-retry: 5.0.4 @@ -15412,18 +16452,19 @@ snapshots: read-pkg-up: 7.0.1 transitivePeerDependencies: - encoding + - prettier - supports-color - '@storybook/test@8.0.9(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3))': + '@storybook/test@8.1.11(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9))(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1))': dependencies: - '@storybook/client-logger': 8.0.9 - '@storybook/core-events': 8.0.9 - '@storybook/instrumenter': 8.0.9 - '@storybook/preview-api': 8.0.9 - '@testing-library/dom': 9.3.4 - '@testing-library/jest-dom': 6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)) - '@testing-library/user-event': 14.5.2(@testing-library/dom@9.3.4) - '@vitest/expect': 1.3.1 + '@storybook/client-logger': 8.1.11 + '@storybook/core-events': 8.1.11 + '@storybook/instrumenter': 8.1.11 + '@storybook/preview-api': 8.1.11 + '@testing-library/dom': 10.1.0 + '@testing-library/jest-dom': 6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9))(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1)) + '@testing-library/user-event': 14.5.2(@testing-library/dom@10.1.0) + '@vitest/expect': 1.6.0 '@vitest/spy': 1.6.0 util: 0.12.5 transitivePeerDependencies: @@ -15433,37 +16474,39 @@ snapshots: - jest - vitest - '@storybook/theming@8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@storybook/theming@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: '@emotion/use-insertion-effect-with-fallbacks': 1.0.1(react@18.3.1) - '@storybook/client-logger': 8.0.9 + '@storybook/client-logger': 8.1.11 '@storybook/global': 5.0.0 memoizerific: 1.11.3 optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@storybook/types@8.0.9': + '@storybook/types@8.1.11': dependencies: - '@storybook/channels': 8.0.9 + '@storybook/channels': 8.1.11 '@types/express': 4.17.17 file-system-cache: 2.3.0 - '@storybook/vue3-vite@8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.5.2))': + '@storybook/vue3-vite@8.1.11(bufferutil@4.0.7)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))(vue@3.4.31(typescript@5.5.3))': dependencies: - '@storybook/builder-vite': 8.0.9(encoding@0.1.13)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)) - '@storybook/core-server': 8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) - '@storybook/vue3': 8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.5.2)) + '@storybook/builder-vite': 8.1.11(encoding@0.1.13)(prettier@3.3.2)(typescript@5.5.3)(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1)) + '@storybook/core-server': 8.1.11(bufferutil@4.0.7)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) + '@storybook/types': 8.1.11 + '@storybook/vue3': 8.1.11(encoding@0.1.13)(prettier@3.3.2)(vue@3.4.31(typescript@5.5.3)) find-package-json: 1.2.0 - magic-string: 0.30.7 - typescript: 5.5.2 - vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) - vue-component-meta: 2.0.16(typescript@5.5.2) - vue-docgen-api: 4.75.1(vue@3.4.26(typescript@5.5.2)) + magic-string: 0.30.10 + typescript: 5.5.3 + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) + vue-component-meta: 2.0.16(typescript@5.5.3) + vue-docgen-api: 4.75.1(vue@3.4.31(typescript@5.5.3)) transitivePeerDependencies: - '@preact/preset-vite' - bufferutil - encoding + - prettier - react - react-dom - supports-color @@ -15471,26 +16514,27 @@ snapshots: - vite-plugin-glimmerx - vue - '@storybook/vue3@8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.5.2))': + '@storybook/vue3@8.1.11(encoding@0.1.13)(prettier@3.3.2)(vue@3.4.31(typescript@5.5.3))': dependencies: - '@storybook/docs-tools': 8.0.9(encoding@0.1.13) + '@storybook/docs-tools': 8.1.11(encoding@0.1.13)(prettier@3.3.2) '@storybook/global': 5.0.0 - '@storybook/preview-api': 8.0.9 - '@storybook/types': 8.0.9 - '@vue/compiler-core': 3.4.21 + '@storybook/preview-api': 8.1.11 + '@storybook/types': 8.1.11 + '@vue/compiler-core': 3.4.29 lodash: 4.17.21 ts-dedent: 2.2.0 type-fest: 2.19.0 - vue: 3.4.26(typescript@5.5.2) - vue-component-type-helpers: 2.0.21 + vue: 3.4.31(typescript@5.5.3) + vue-component-type-helpers: 2.0.24 transitivePeerDependencies: - encoding + - prettier - supports-color - '@swc/cli@0.3.12(@swc/core@1.4.17)(chokidar@3.5.3)': + '@swc/cli@0.3.12(@swc/core@1.6.6)(chokidar@3.5.3)': dependencies: '@mole-inc/bin-wrapper': 8.0.1 - '@swc/core': 1.4.17 + '@swc/core': 1.6.6 '@swc/counter': 0.1.3 commander: 8.3.0 fast-glob: 3.3.2 @@ -15510,13 +16554,13 @@ snapshots: '@swc/core-darwin-arm64@1.3.56': optional: true - '@swc/core-darwin-arm64@1.4.17': + '@swc/core-darwin-arm64@1.6.6': optional: true '@swc/core-darwin-x64@1.3.56': optional: true - '@swc/core-darwin-x64@1.4.17': + '@swc/core-darwin-x64@1.6.6': optional: true '@swc/core-freebsd-x64@1.3.11': @@ -15527,77 +16571,79 @@ snapshots: '@swc/core-linux-arm-gnueabihf@1.3.56': optional: true - '@swc/core-linux-arm-gnueabihf@1.4.17': + '@swc/core-linux-arm-gnueabihf@1.6.6': optional: true '@swc/core-linux-arm64-gnu@1.3.56': optional: true - '@swc/core-linux-arm64-gnu@1.4.17': + '@swc/core-linux-arm64-gnu@1.6.6': optional: true '@swc/core-linux-arm64-musl@1.3.56': optional: true - '@swc/core-linux-arm64-musl@1.4.17': + '@swc/core-linux-arm64-musl@1.6.6': optional: true '@swc/core-linux-x64-gnu@1.3.56': optional: true - '@swc/core-linux-x64-gnu@1.4.17': + '@swc/core-linux-x64-gnu@1.6.6': optional: true '@swc/core-linux-x64-musl@1.3.56': optional: true - '@swc/core-linux-x64-musl@1.4.17': + '@swc/core-linux-x64-musl@1.6.6': optional: true '@swc/core-win32-arm64-msvc@1.3.56': optional: true - '@swc/core-win32-arm64-msvc@1.4.17': + '@swc/core-win32-arm64-msvc@1.6.6': optional: true '@swc/core-win32-ia32-msvc@1.3.56': optional: true - '@swc/core-win32-ia32-msvc@1.4.17': + '@swc/core-win32-ia32-msvc@1.6.6': optional: true '@swc/core-win32-x64-msvc@1.3.56': optional: true - '@swc/core-win32-x64-msvc@1.4.17': + '@swc/core-win32-x64-msvc@1.6.6': optional: true - '@swc/core@1.4.17': + '@swc/core@1.6.6': dependencies: '@swc/counter': 0.1.3 - '@swc/types': 0.1.5 + '@swc/types': 0.1.9 optionalDependencies: - '@swc/core-darwin-arm64': 1.4.17 - '@swc/core-darwin-x64': 1.4.17 - '@swc/core-linux-arm-gnueabihf': 1.4.17 - '@swc/core-linux-arm64-gnu': 1.4.17 - '@swc/core-linux-arm64-musl': 1.4.17 - '@swc/core-linux-x64-gnu': 1.4.17 - '@swc/core-linux-x64-musl': 1.4.17 - '@swc/core-win32-arm64-msvc': 1.4.17 - '@swc/core-win32-ia32-msvc': 1.4.17 - '@swc/core-win32-x64-msvc': 1.4.17 + '@swc/core-darwin-arm64': 1.6.6 + '@swc/core-darwin-x64': 1.6.6 + '@swc/core-linux-arm-gnueabihf': 1.6.6 + '@swc/core-linux-arm64-gnu': 1.6.6 + '@swc/core-linux-arm64-musl': 1.6.6 + '@swc/core-linux-x64-gnu': 1.6.6 + '@swc/core-linux-x64-musl': 1.6.6 + '@swc/core-win32-arm64-msvc': 1.6.6 + '@swc/core-win32-ia32-msvc': 1.6.6 + '@swc/core-win32-x64-msvc': 1.6.6 '@swc/counter@0.1.3': {} - '@swc/jest@0.2.36(@swc/core@1.4.17)': + '@swc/jest@0.2.36(@swc/core@1.6.6)': dependencies: '@jest/create-cache-key-function': 29.7.0 - '@swc/core': 1.4.17 + '@swc/core': 1.6.6 '@swc/counter': 0.1.3 jsonc-parser: 3.2.0 - '@swc/types@0.1.5': {} + '@swc/types@0.1.9': + dependencies: + '@swc/counter': 0.1.3 '@swc/wasm@1.2.130': optional: true @@ -15701,12 +16747,12 @@ snapshots: - encoding - seedrandom - '@testing-library/dom@9.3.3': + '@testing-library/dom@10.1.0': dependencies: - '@babel/code-frame': 7.23.5 + '@babel/code-frame': 7.24.7 '@babel/runtime': 7.23.4 '@types/aria-query': 5.0.1 - aria-query: 5.1.3 + aria-query: 5.3.0 chalk: 4.1.2 dom-accessibility-api: 0.5.16 lz-string: 1.5.0 @@ -15723,7 +16769,7 @@ snapshots: lz-string: 1.5.0 pretty-format: 27.5.1 - '@testing-library/jest-dom@6.4.2(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3))': + '@testing-library/jest-dom@6.4.5(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.14.9))(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1))': dependencies: '@adobe/css-tools': 4.3.3 '@babel/runtime': 7.23.4 @@ -15736,21 +16782,21 @@ snapshots: optionalDependencies: '@jest/globals': 29.7.0 '@types/jest': 29.5.12 - jest: 29.7.0(@types/node@20.12.7) - vitest: 0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3) + jest: 29.7.0(@types/node@20.14.9) + vitest: 1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1) - '@testing-library/user-event@14.5.2(@testing-library/dom@9.3.4)': + '@testing-library/user-event@14.5.2(@testing-library/dom@10.1.0)': dependencies: - '@testing-library/dom': 9.3.4 + '@testing-library/dom': 10.1.0 - '@testing-library/vue@8.0.3(@vue/compiler-sfc@3.4.26)(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2)))(vue@3.4.26(typescript@5.5.2))': + '@testing-library/vue@8.1.0(@vue/compiler-sfc@3.4.31)(@vue/server-renderer@3.4.29(vue@3.4.31(typescript@5.5.3)))(vue@3.4.31(typescript@5.5.3))': dependencies: '@babel/runtime': 7.23.4 - '@testing-library/dom': 9.3.3 - '@vue/test-utils': 2.4.1(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2)))(vue@3.4.26(typescript@5.5.2)) - vue: 3.4.26(typescript@5.5.2) + '@testing-library/dom': 9.3.4 + '@vue/test-utils': 2.4.1(@vue/server-renderer@3.4.29(vue@3.4.31(typescript@5.5.3)))(vue@3.4.31(typescript@5.5.3)) + vue: 3.4.31(typescript@5.5.3) optionalDependencies: - '@vue/compiler-sfc': 3.4.26 + '@vue/compiler-sfc': 3.4.31 transitivePeerDependencies: - '@vue/server-renderer' @@ -15758,7 +16804,7 @@ snapshots: '@trysound/sax@0.2.0': {} - '@tsd/typescript@5.3.3': {} + '@tsd/typescript@5.4.5': {} '@twemoji/parser@15.0.0': {} @@ -15766,7 +16812,7 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/archiver@6.0.2': dependencies: @@ -15778,31 +16824,31 @@ snapshots: '@types/babel__core@7.20.0': dependencies: - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 '@types/babel__generator': 7.6.4 '@types/babel__template': 7.4.1 '@types/babel__traverse': 7.20.0 '@types/babel__generator@7.6.4': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.7 '@types/babel__template@7.4.1': dependencies: - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 '@types/babel__traverse@7.20.0': dependencies: - '@babel/types': 7.24.0 + '@babel/types': 7.24.7 '@types/bcryptjs@2.4.6': {} '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.35 - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/braces@3.0.1': {} @@ -15810,15 +16856,9 @@ snapshots: dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/responselike': 1.0.0 - '@types/chai-subset@1.3.5': - dependencies: - '@types/chai': 4.3.11 - - '@types/chai@4.3.11': {} - '@types/color-convert@2.0.3': dependencies: '@types/color-name': 1.1.1 @@ -15827,11 +16867,11 @@ snapshots: '@types/connect@3.4.35': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/connect@3.4.36': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/content-disposition@0.5.8': {} @@ -15839,14 +16879,14 @@ snapshots: '@types/cookies@0.9.0': dependencies: - '@types/connect': 3.4.35 + '@types/connect': 3.4.36 '@types/express': 4.17.17 '@types/keygrip': 1.0.6 - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/cross-spawn@6.0.2': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/debug@4.1.12': dependencies: @@ -15854,6 +16894,8 @@ snapshots: '@types/detect-port@1.3.2': {} + '@types/diff@5.2.1': {} + '@types/disposable-email-domains@1.0.2': {} '@types/doctrine@0.0.3': {} @@ -15871,7 +16913,7 @@ snapshots: '@types/eslint@7.29.0': dependencies: '@types/estree': 1.0.5 - '@types/json-schema': 7.0.12 + '@types/json-schema': 7.0.15 '@types/estree@0.0.51': {} @@ -15879,7 +16921,7 @@ snapshots: '@types/express-serve-static-core@4.17.33': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 @@ -15894,16 +16936,16 @@ snapshots: '@types/fluent-ffmpeg@2.1.24': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/graceful-fs@4.1.6': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/hast@3.0.4': dependencies: @@ -15917,9 +16959,9 @@ snapshots: '@types/http-errors@2.0.4': {} - '@types/http-link-header@1.0.5': + '@types/http-link-header@1.0.7': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/istanbul-lib-coverage@2.0.4': {} @@ -15938,9 +16980,9 @@ snapshots: '@types/js-yaml@4.0.9': {} - '@types/jsdom@21.1.6': + '@types/jsdom@21.1.7': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/tough-cookie': 4.0.2 parse5: 7.1.2 @@ -15950,7 +16992,7 @@ snapshots: '@types/json5@0.0.29': {} - '@types/jsonld@1.5.13': {} + '@types/jsonld@1.5.14': {} '@types/jsrsasign@10.5.14': {} @@ -15958,7 +17000,7 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/koa-compose@3.2.8': dependencies: @@ -15973,7 +17015,7 @@ snapshots: '@types/http-errors': 2.0.4 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/koa__router@12.0.3': dependencies: @@ -15991,7 +17033,7 @@ snapshots: '@types/mdx@2.0.3': {} - '@types/micromatch@4.0.7': + '@types/micromatch@4.0.9': dependencies: '@types/braces': 3.0.1 @@ -16007,15 +17049,15 @@ snapshots: '@types/mute-stream@0.0.4': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/mysql@2.15.22': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/node-fetch@2.6.4': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 form-data: 3.0.1 '@types/node@18.17.15': {} @@ -16024,7 +17066,7 @@ snapshots: dependencies: undici-types: 5.26.5 - '@types/node@20.12.7': + '@types/node@20.14.9': dependencies: undici-types: 5.26.5 @@ -16034,7 +17076,7 @@ snapshots: '@types/nodemailer@6.4.15': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/normalize-package-data@2.4.1': {} @@ -16045,11 +17087,11 @@ snapshots: '@types/oauth2orize@1.11.5': dependencies: '@types/express': 4.17.17 - '@types/node': 20.12.7 + '@types/node': 20.14.9 - '@types/oauth@0.9.4': + '@types/oauth@0.9.5': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/offscreencanvas@2019.3.0': {} @@ -16057,17 +17099,17 @@ snapshots: '@types/pg-pool@2.0.4': dependencies: - '@types/pg': 8.11.5 + '@types/pg': 8.11.6 - '@types/pg@8.11.5': + '@types/pg@8.11.6': dependencies: - '@types/node': 20.12.7 - pg-protocol: 1.6.0 + '@types/node': 20.14.9 + pg-protocol: 1.6.1 pg-types: 4.0.1 '@types/pg@8.6.1': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 pg-protocol: 1.6.1 pg-types: 2.2.0 @@ -16081,7 +17123,7 @@ snapshots: '@types/qrcode@1.5.5': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/qs@6.9.7': {} @@ -16099,7 +17141,7 @@ snapshots: '@types/readdir-glob@1.1.1': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/rename@1.0.7': {} @@ -16107,7 +17149,7 @@ snapshots: '@types/responselike@1.0.0': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/sanitize-html@2.11.0': dependencies: @@ -16124,7 +17166,7 @@ snapshots: '@types/serve-static@1.15.1': dependencies: '@types/mime': 3.0.1 - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/serviceworker@0.0.67': {} @@ -16156,15 +17198,17 @@ snapshots: '@types/unist@3.0.2': {} + '@types/uuid@10.0.0': {} + '@types/uuid@9.0.8': {} '@types/vary@1.1.3': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/web-push@3.6.3': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/webgl-ext@0.0.30': {} @@ -16172,7 +17216,7 @@ snapshots: '@types/ws@8.5.10': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 '@types/yargs-parser@21.0.0': {} @@ -16182,19 +17226,19 @@ snapshots: '@types/yauzl@2.10.0': dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 optional: true - '@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0)(typescript@5.3.3)': + '@typescript-eslint/eslint-plugin@6.11.0(@typescript-eslint/parser@6.11.0(eslint@9.6.0)(typescript@5.3.3))(eslint@9.6.0)(typescript@5.3.3)': dependencies: '@eslint-community/regexpp': 4.6.2 - '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.11.0(eslint@9.6.0)(typescript@5.3.3) '@typescript-eslint/scope-manager': 6.11.0 - '@typescript-eslint/type-utils': 6.11.0(eslint@8.53.0)(typescript@5.3.3) - '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.3.3) + '@typescript-eslint/type-utils': 6.11.0(eslint@9.6.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.11.0(eslint@9.6.0)(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.11.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 + debug: 4.3.4(supports-color@5.5.0) + eslint: 9.6.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 @@ -16205,16 +17249,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)(typescript@5.3.3)': + '@typescript-eslint/eslint-plugin@7.1.0(@typescript-eslint/parser@7.1.0(eslint@9.6.0)(typescript@5.3.3))(eslint@9.6.0)(typescript@5.3.3)': dependencies: '@eslint-community/regexpp': 4.6.2 - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/parser': 7.1.0(eslint@9.6.0)(typescript@5.3.3) '@typescript-eslint/scope-manager': 7.1.0 - '@typescript-eslint/type-utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) + '@typescript-eslint/type-utils': 7.1.0(eslint@9.6.0)(typescript@5.3.3) + '@typescript-eslint/utils': 7.1.0(eslint@9.6.0)(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + debug: 4.3.4(supports-color@5.5.0) + eslint: 9.6.0 graphemer: 1.4.0 ignore: 5.2.4 natural-compare: 1.4.0 @@ -16225,62 +17269,60 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/eslint-plugin@7.15.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0)(typescript@5.5.3)': dependencies: '@eslint-community/regexpp': 4.10.0 - '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/scope-manager': 7.7.1 - '@typescript-eslint/type-utils': 7.7.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.5.2) - '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + '@typescript-eslint/parser': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/type-utils': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 + eslint: 9.6.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.2) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3)': + '@typescript-eslint/parser@6.11.0(eslint@9.6.0)(typescript@5.3.3)': dependencies: '@typescript-eslint/scope-manager': 6.11.0 '@typescript-eslint/types': 6.11.0 '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.11.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 + debug: 4.3.4(supports-color@5.5.0) + eslint: 9.6.0 optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3)': + '@typescript-eslint/parser@7.1.0(eslint@9.6.0)(typescript@5.3.3)': dependencies: '@typescript-eslint/scope-manager': 7.1.0 '@typescript-eslint/types': 7.1.0 '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + debug: 4.3.4(supports-color@5.5.0) + eslint: 9.6.0 optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/scope-manager': 7.7.1 - '@typescript-eslint/types': 7.7.1 - '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.5.2) - '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.5(supports-color@8.1.1) + eslint: 9.6.0 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -16294,44 +17336,44 @@ snapshots: '@typescript-eslint/types': 7.1.0 '@typescript-eslint/visitor-keys': 7.1.0 - '@typescript-eslint/scope-manager@7.7.1': + '@typescript-eslint/scope-manager@7.15.0': dependencies: - '@typescript-eslint/types': 7.7.1 - '@typescript-eslint/visitor-keys': 7.7.1 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 - '@typescript-eslint/type-utils@6.11.0(eslint@8.53.0)(typescript@5.3.3)': + '@typescript-eslint/type-utils@6.11.0(eslint@9.6.0)(typescript@5.3.3)': dependencies: '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.3.3) - '@typescript-eslint/utils': 6.11.0(eslint@8.53.0)(typescript@5.3.3) - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.53.0 + '@typescript-eslint/utils': 6.11.0(eslint@9.6.0)(typescript@5.3.3) + debug: 4.3.5(supports-color@8.1.1) + eslint: 9.6.0 ts-api-utils: 1.0.1(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@7.1.0(eslint@8.57.0)(typescript@5.3.3)': + '@typescript-eslint/type-utils@7.1.0(eslint@9.6.0)(typescript@5.3.3)': dependencies: '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3) - '@typescript-eslint/utils': 7.1.0(eslint@8.57.0)(typescript@5.3.3) - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + '@typescript-eslint/utils': 7.1.0(eslint@9.6.0)(typescript@5.3.3) + debug: 4.3.4(supports-color@5.5.0) + eslint: 9.6.0 ts-api-utils: 1.0.1(typescript@5.3.3) optionalDependencies: typescript: 5.3.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@7.7.1(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/type-utils@7.15.0(eslint@9.6.0)(typescript@5.5.3)': dependencies: - '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.5.2) - '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.5.2) - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 - ts-api-utils: 1.3.0(typescript@5.5.2) + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + '@typescript-eslint/utils': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + debug: 4.3.5(supports-color@8.1.1) + eslint: 9.6.0 + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color @@ -16339,13 +17381,13 @@ snapshots: '@typescript-eslint/types@7.1.0': {} - '@typescript-eslint/types@7.7.1': {} + '@typescript-eslint/types@7.15.0': {} '@typescript-eslint/typescript-estree@6.11.0(typescript@5.3.3)': dependencies: '@typescript-eslint/types': 6.11.0 '@typescript-eslint/visitor-keys': 6.11.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.5.4 @@ -16359,7 +17401,7 @@ snapshots: dependencies: '@typescript-eslint/types': 7.1.0 '@typescript-eslint/visitor-keys': 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -16370,59 +17412,56 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@7.7.1(typescript@5.5.2)': + '@typescript-eslint/typescript-estree@7.15.0(typescript@5.5.3)': dependencies: - '@typescript-eslint/types': 7.7.1 - '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.4(supports-color@8.1.1) + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/visitor-keys': 7.15.0 + debug: 4.3.5(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 semver: 7.6.0 - ts-api-utils: 1.3.0(typescript@5.5.2) + ts-api-utils: 1.3.0(typescript@5.5.3) optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.11.0(eslint@8.53.0)(typescript@5.3.3)': + '@typescript-eslint/utils@6.11.0(eslint@9.6.0)(typescript@5.3.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 6.11.0 '@typescript-eslint/types': 6.11.0 '@typescript-eslint/typescript-estree': 6.11.0(typescript@5.3.3) - eslint: 8.53.0 + eslint: 9.6.0 semver: 7.5.4 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/utils@7.1.0(eslint@8.57.0)(typescript@5.3.3)': + '@typescript-eslint/utils@7.1.0(eslint@9.6.0)(typescript@5.3.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) '@types/json-schema': 7.0.12 '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 7.1.0 '@typescript-eslint/types': 7.1.0 '@typescript-eslint/typescript-estree': 7.1.0(typescript@5.3.3) - eslint: 8.57.0 + eslint: 9.6.0 semver: 7.6.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/utils@7.7.1(eslint@8.57.0)(typescript@5.5.2)': + '@typescript-eslint/utils@7.15.0(eslint@9.6.0)(typescript@5.5.3)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@types/json-schema': 7.0.15 - '@types/semver': 7.5.8 - '@typescript-eslint/scope-manager': 7.7.1 - '@typescript-eslint/types': 7.7.1 - '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.5.2) - eslint: 8.57.0 - semver: 7.6.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) + '@typescript-eslint/scope-manager': 7.15.0 + '@typescript-eslint/types': 7.15.0 + '@typescript-eslint/typescript-estree': 7.15.0(typescript@5.5.3) + eslint: 9.6.0 transitivePeerDependencies: - supports-color - typescript @@ -16437,84 +17476,59 @@ snapshots: '@typescript-eslint/types': 7.1.0 eslint-visitor-keys: 3.4.3 - '@typescript-eslint/visitor-keys@7.7.1': + '@typescript-eslint/visitor-keys@7.15.0': dependencies: - '@typescript-eslint/types': 7.7.1 + '@typescript-eslint/types': 7.15.0 eslint-visitor-keys: 3.4.3 '@ungap/structured-clone@1.2.0': {} - '@vitejs/plugin-vue@5.0.4(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.5.2))': + '@vitejs/plugin-vue@5.0.5(vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1))(vue@3.4.31(typescript@5.5.3))': dependencies: - vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) - vue: 3.4.26(typescript@5.5.2) + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) + vue: 3.4.31(typescript@5.5.3) - '@vitest/coverage-v8@0.34.6(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3))': + '@vitest/coverage-v8@1.6.0(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1))': dependencies: '@ampproject/remapping': 2.2.1 '@bcoe/v8-coverage': 0.2.3 + debug: 4.3.4(supports-color@5.5.0) istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 + istanbul-lib-source-maps: 5.0.4 istanbul-reports: 3.1.6 - magic-string: 0.30.7 + magic-string: 0.30.10 + magicast: 0.3.4 picocolors: 1.0.0 std-env: 3.7.0 + strip-literal: 2.1.0 test-exclude: 6.0.0 - v8-to-istanbul: 9.2.0 - vitest: 0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3) + vitest: 1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - supports-color - '@vitest/expect@0.34.6': + '@vitest/expect@1.6.0': dependencies: - '@vitest/spy': 0.34.6 - '@vitest/utils': 0.34.6 + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 chai: 4.3.10 - '@vitest/expect@1.3.1': + '@vitest/runner@1.6.0': dependencies: - '@vitest/spy': 1.3.1 - '@vitest/utils': 1.3.1 - chai: 4.3.10 - - '@vitest/runner@0.34.6': - dependencies: - '@vitest/utils': 0.34.6 - p-limit: 4.0.0 + '@vitest/utils': 1.6.0 + p-limit: 5.0.0 pathe: 1.1.2 - '@vitest/snapshot@0.34.6': + '@vitest/snapshot@1.6.0': dependencies: - magic-string: 0.30.7 + magic-string: 0.30.10 pathe: 1.1.2 pretty-format: 29.7.0 - '@vitest/spy@0.34.6': - dependencies: - tinyspy: 2.2.0 - - '@vitest/spy@1.3.1': - dependencies: - tinyspy: 2.2.0 - '@vitest/spy@1.6.0': dependencies: tinyspy: 2.2.0 - '@vitest/utils@0.34.6': - dependencies: - diff-sequences: 29.6.3 - loupe: 2.3.7 - pretty-format: 29.7.0 - - '@vitest/utils@1.3.1': - dependencies: - diff-sequences: 29.6.3 - estree-walker: 3.0.3 - loupe: 2.3.7 - pretty-format: 29.7.0 - '@vitest/utils@1.6.0': dependencies: diff-sequences: 29.6.3 @@ -16526,125 +17540,149 @@ snapshots: dependencies: '@volar/source-map': 2.2.0 + '@volar/language-core@2.4.0-alpha.11': + dependencies: + '@volar/source-map': 2.4.0-alpha.11 + '@volar/source-map@2.2.0': dependencies: muggle-string: 0.4.1 + '@volar/source-map@2.4.0-alpha.11': {} + '@volar/typescript@2.2.0': dependencies: '@volar/language-core': 2.2.0 path-browserify: 1.0.1 - '@vue/compiler-core@3.4.21': + '@volar/typescript@2.4.0-alpha.11': dependencies: - '@babel/parser': 7.24.0 - '@vue/shared': 3.4.21 - entities: 4.5.0 - estree-walker: 2.0.2 - source-map-js: 1.0.2 + '@volar/language-core': 2.4.0-alpha.11 + path-browserify: 1.0.1 + vscode-uri: 3.0.8 - '@vue/compiler-core@3.4.25': + '@vue/compiler-core@3.4.29': dependencies: - '@babel/parser': 7.24.5 - '@vue/shared': 3.4.25 + '@babel/parser': 7.24.7 + '@vue/shared': 3.4.29 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.0 - '@vue/compiler-core@3.4.26': + '@vue/compiler-core@3.4.31': dependencies: - '@babel/parser': 7.24.5 - '@vue/shared': 3.4.26 + '@babel/parser': 7.24.7 + '@vue/shared': 3.4.31 entities: 4.5.0 estree-walker: 2.0.2 source-map-js: 1.2.0 - '@vue/compiler-dom@3.4.21': + '@vue/compiler-dom@3.4.29': dependencies: - '@vue/compiler-core': 3.4.21 - '@vue/shared': 3.4.21 + '@vue/compiler-core': 3.4.29 + '@vue/shared': 3.4.29 - '@vue/compiler-dom@3.4.25': + '@vue/compiler-dom@3.4.31': dependencies: - '@vue/compiler-core': 3.4.25 - '@vue/shared': 3.4.25 + '@vue/compiler-core': 3.4.31 + '@vue/shared': 3.4.31 - '@vue/compiler-dom@3.4.26': + '@vue/compiler-sfc@3.4.31': dependencies: - '@vue/compiler-core': 3.4.26 - '@vue/shared': 3.4.26 - - '@vue/compiler-sfc@3.4.26': - dependencies: - '@babel/parser': 7.24.5 - '@vue/compiler-core': 3.4.26 - '@vue/compiler-dom': 3.4.26 - '@vue/compiler-ssr': 3.4.26 - '@vue/shared': 3.4.26 + '@babel/parser': 7.24.7 + '@vue/compiler-core': 3.4.31 + '@vue/compiler-dom': 3.4.31 + '@vue/compiler-ssr': 3.4.31 + '@vue/shared': 3.4.31 estree-walker: 2.0.2 magic-string: 0.30.10 postcss: 8.4.38 source-map-js: 1.2.0 - '@vue/compiler-ssr@3.4.26': + '@vue/compiler-ssr@3.4.29': dependencies: - '@vue/compiler-dom': 3.4.26 - '@vue/shared': 3.4.26 + '@vue/compiler-dom': 3.4.29 + '@vue/shared': 3.4.29 + optional: true + + '@vue/compiler-ssr@3.4.31': + dependencies: + '@vue/compiler-dom': 3.4.31 + '@vue/shared': 3.4.31 '@vue/devtools-api@6.6.1': {} - '@vue/language-core@2.0.16(typescript@5.5.2)': + '@vue/language-core@2.0.16(typescript@5.5.3)': dependencies: '@volar/language-core': 2.2.0 - '@vue/compiler-dom': 3.4.25 - '@vue/shared': 3.4.25 + '@vue/compiler-dom': 3.4.29 + '@vue/shared': 3.4.29 computeds: 0.0.1 minimatch: 9.0.4 path-browserify: 1.0.1 vue-template-compiler: 2.7.14 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 - '@vue/reactivity@3.4.26': + '@vue/language-core@2.0.24(typescript@5.5.3)': dependencies: - '@vue/shared': 3.4.26 + '@volar/language-core': 2.4.0-alpha.11 + '@vue/compiler-dom': 3.4.29 + '@vue/shared': 3.4.29 + computeds: 0.0.1 + minimatch: 9.0.4 + muggle-string: 0.4.1 + path-browserify: 1.0.1 + vue-template-compiler: 2.7.14 + optionalDependencies: + typescript: 5.5.3 - '@vue/runtime-core@3.4.26': + '@vue/reactivity@3.4.31': dependencies: - '@vue/reactivity': 3.4.26 - '@vue/shared': 3.4.26 + '@vue/shared': 3.4.31 - '@vue/runtime-dom@3.4.26': + '@vue/runtime-core@3.4.31': dependencies: - '@vue/runtime-core': 3.4.26 - '@vue/shared': 3.4.26 + '@vue/reactivity': 3.4.31 + '@vue/shared': 3.4.31 + + '@vue/runtime-dom@3.4.31': + dependencies: + '@vue/reactivity': 3.4.31 + '@vue/runtime-core': 3.4.31 + '@vue/shared': 3.4.31 csstype: 3.1.3 - '@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2))': + '@vue/server-renderer@3.4.29(vue@3.4.31(typescript@5.5.3))': dependencies: - '@vue/compiler-ssr': 3.4.26 - '@vue/shared': 3.4.26 - vue: 3.4.26(typescript@5.5.2) + '@vue/compiler-ssr': 3.4.29 + '@vue/shared': 3.4.29 + vue: 3.4.31(typescript@5.5.3) + optional: true - '@vue/shared@3.4.21': {} + '@vue/server-renderer@3.4.31(vue@3.4.31(typescript@5.5.3))': + dependencies: + '@vue/compiler-ssr': 3.4.31 + '@vue/shared': 3.4.31 + vue: 3.4.31(typescript@5.5.3) - '@vue/shared@3.4.25': {} + '@vue/shared@3.4.29': {} - '@vue/shared@3.4.26': {} + '@vue/shared@3.4.31': {} - '@vue/test-utils@2.4.1(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2)))(vue@3.4.26(typescript@5.5.2))': + '@vue/test-utils@2.4.1(@vue/server-renderer@3.4.29(vue@3.4.31(typescript@5.5.3)))(vue@3.4.31(typescript@5.5.3))': dependencies: js-beautify: 1.14.9 - vue: 3.4.26(typescript@5.5.2) + vue: 3.4.31(typescript@5.5.3) vue-component-type-helpers: 1.8.4 optionalDependencies: - '@vue/server-renderer': 3.4.26(vue@3.4.26(typescript@5.5.2)) + '@vue/server-renderer': 3.4.29(vue@3.4.31(typescript@5.5.3)) '@webgpu/types@0.1.30': {} - '@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.20.2)': + '@yarnpkg/esbuild-plugin-pnp@3.0.0-rc.15(esbuild@0.19.11)': dependencies: - esbuild: 0.20.2 + esbuild: 0.19.11 tslib: 2.6.2 '@yarnpkg/fslib@2.10.3': @@ -16672,22 +17710,22 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 - acorn-import-assertions@1.9.0(acorn@8.11.3): + acorn-import-assertions@1.9.0(acorn@8.12.0): dependencies: - acorn: 8.11.3 + acorn: 8.12.0 optional: true - acorn-import-attributes@1.9.5(acorn@8.11.3): + acorn-import-attributes@1.9.5(acorn@8.12.0): dependencies: - acorn: 8.11.3 + acorn: 8.12.0 acorn-jsx@5.3.2(acorn@7.4.1): dependencies: acorn: 7.4.1 - acorn-jsx@5.3.2(acorn@8.11.3): + acorn-jsx@5.3.2(acorn@8.12.0): dependencies: - acorn: 8.11.3 + acorn: 8.12.0 acorn-walk@7.2.0: {} @@ -16695,7 +17733,7 @@ snapshots: acorn@7.4.1: {} - acorn@8.11.3: {} + acorn@8.12.0: {} address@1.2.2: {} @@ -16709,13 +17747,13 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color agent-base@7.1.0: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -16738,7 +17776,15 @@ snapshots: optionalDependencies: ajv: 8.13.0 - ajv-formats@2.1.1(ajv@8.13.0): + ajv-draft-04@1.0.0(ajv@8.16.0): + optionalDependencies: + ajv: 8.16.0 + + ajv-formats@2.1.1(ajv@8.16.0): + optionalDependencies: + ajv: 8.16.0 + + ajv-formats@3.0.1(ajv@8.13.0): optionalDependencies: ajv: 8.13.0 @@ -16749,6 +17795,13 @@ snapshots: json-schema-traverse: 0.4.1 uri-js: 4.4.1 + ajv@8.12.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + ajv@8.13.0: dependencies: fast-deep-equal: 3.1.3 @@ -16756,6 +17809,13 @@ snapshots: require-from-string: 2.0.2 uri-js: 4.4.1 + ajv@8.16.0: + dependencies: + fast-deep-equal: 3.1.3 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + uri-js: 4.4.1 + ansi-colors@4.1.3: {} ansi-escapes@4.3.2: @@ -16798,7 +17858,7 @@ snapshots: archiver-utils@5.0.2: dependencies: - glob: 10.3.12 + glob: 10.4.2 graceful-fs: 4.2.11 is-stream: 2.0.1 lazystream: 1.0.1 @@ -16832,10 +17892,18 @@ snapshots: argparse@2.0.1: {} + aria-hidden@1.2.4: + dependencies: + tslib: 2.6.2 + aria-query@5.1.3: dependencies: deep-equal: 2.2.0 + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + array-buffer-byte-length@1.0.0: dependencies: call-bind: 1.0.2 @@ -16931,6 +17999,8 @@ snapshots: dependencies: tslib: 2.6.2 + async@0.2.10: {} + async@3.2.4: {} asynckit@0.4.0: {} @@ -16945,12 +18015,12 @@ snapshots: dependencies: '@fastify/error': 3.4.0 archy: 1.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) fastq: 1.17.1 transitivePeerDependencies: - supports-color - aws-sdk-client-mock@3.0.1: + aws-sdk-client-mock@4.0.1: dependencies: '@types/sinon': 10.0.13 sinon: 16.1.3 @@ -16962,13 +18032,13 @@ snapshots: axios@0.24.0: dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.2(debug@4.3.5) transitivePeerDependencies: - debug - axios@1.6.2(debug@4.3.4): + axios@1.6.2(debug@4.3.5): dependencies: - follow-redirects: 1.15.2(debug@4.3.4) + follow-redirects: 1.15.2(debug@4.3.5) form-data: 4.0.0 proxy-from-env: 1.1.0 transitivePeerDependencies: @@ -16976,9 +18046,9 @@ snapshots: b4a@1.6.4: {} - babel-core@7.0.0-bridge.0(@babel/core@7.24.0): + babel-core@7.0.0-bridge.0(@babel/core@7.24.7): dependencies: - '@babel/core': 7.24.0 + '@babel/core': 7.24.7 babel-jest@29.7.0(@babel/core@7.23.5): dependencies: @@ -17006,31 +18076,31 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: '@babel/template': 7.24.0 - '@babel/types': 7.24.0 + '@babel/types': 7.24.7 '@types/babel__core': 7.20.0 '@types/babel__traverse': 7.20.0 - babel-plugin-polyfill-corejs2@0.4.6(@babel/core@7.24.0): + babel-plugin-polyfill-corejs2@0.4.11(@babel/core@7.24.7): dependencies: - '@babel/compat-data': 7.23.5 - '@babel/core': 7.24.0 - '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.24.0) + '@babel/compat-data': 7.24.7 + '@babel/core': 7.24.7 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.7) semver: 6.3.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-corejs3@0.8.6(@babel/core@7.24.0): + babel-plugin-polyfill-corejs3@0.10.4(@babel/core@7.24.7): dependencies: - '@babel/core': 7.24.0 - '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.24.0) - core-js-compat: 3.33.3 + '@babel/core': 7.24.7 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.7) + core-js-compat: 3.37.1 transitivePeerDependencies: - supports-color - babel-plugin-polyfill-regenerator@0.5.3(@babel/core@7.24.0): + babel-plugin-polyfill-regenerator@0.6.2(@babel/core@7.24.7): dependencies: - '@babel/core': 7.24.0 - '@babel/helper-define-polyfill-provider': 0.4.3(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/helper-define-polyfill-provider': 0.6.2(@babel/core@7.24.7) transitivePeerDependencies: - supports-color @@ -17058,7 +18128,7 @@ snapshots: babel-walk@3.0.0-canary-5: dependencies: - '@babel/types': 7.23.5 + '@babel/types': 7.24.0 bail@2.0.2: {} @@ -17110,23 +18180,6 @@ snapshots: bn.js@4.12.0: {} - body-parser@1.20.1: - dependencies: - bytes: 3.1.2 - content-type: 1.0.5 - debug: 2.6.9 - depd: 2.0.0 - destroy: 1.2.0 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - on-finished: 2.4.1 - qs: 6.11.0 - raw-body: 2.5.1 - type-is: 1.6.18 - unpipe: 1.0.0 - transitivePeerDependencies: - - supports-color - body-parser@1.20.2: dependencies: bytes: 3.1.2 @@ -17165,6 +18218,10 @@ snapshots: dependencies: fill-range: 7.0.1 + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + broadcast-channel@7.0.0: dependencies: '@babel/runtime': 7.23.4 @@ -17224,7 +18281,7 @@ snapshots: node-gyp-build: 4.6.0 optional: true - bullmq@5.7.8: + bullmq@5.8.3: dependencies: cron-parser: 4.8.1 ioredis: 5.4.1 @@ -17252,7 +18309,7 @@ snapshots: dependencies: '@npmcli/fs': 3.1.0 fs-minipass: 3.0.2 - glob: 10.3.12 + glob: 10.4.2 lru-cache: 10.2.2 minipass: 7.0.4 minipass-collect: 1.0.2 @@ -17277,6 +18334,16 @@ snapshots: normalize-url: 8.0.0 responselike: 3.0.0 + cacheable-request@12.0.1: + dependencies: + '@types/http-cache-semantics': 4.0.4 + get-stream: 9.0.1 + http-cache-semantics: 4.1.1 + keyv: 4.5.4 + mimic-response: 4.0.0 + normalize-url: 8.0.1 + responselike: 3.0.0 + cacheable-request@7.0.2: dependencies: clone-response: 1.0.3 @@ -17371,26 +18438,26 @@ snapshots: dependencies: is-regex: 1.1.4 - chart.js@4.4.2: + chart.js@4.4.3: dependencies: '@kurkle/color': 0.3.2 - chartjs-adapter-date-fns@3.0.0(chart.js@4.4.2)(date-fns@2.30.0): + chartjs-adapter-date-fns@3.0.0(chart.js@4.4.3)(date-fns@2.30.0): dependencies: - chart.js: 4.4.2 + chart.js: 4.4.3 date-fns: 2.30.0 - chartjs-chart-matrix@2.0.1(chart.js@4.4.2): + chartjs-chart-matrix@2.0.1(chart.js@4.4.3): dependencies: - chart.js: 4.4.2 + chart.js: 4.4.3 - chartjs-plugin-gradient@0.6.1(chart.js@4.4.2): + chartjs-plugin-gradient@0.6.1(chart.js@4.4.3): dependencies: - chart.js: 4.4.2 + chart.js: 4.4.3 - chartjs-plugin-zoom@2.0.1(chart.js@4.4.2): + chartjs-plugin-zoom@2.0.1(chart.js@4.4.3): dependencies: - chart.js: 4.4.2 + chart.js: 4.4.3 hammerjs: 2.0.8 check-error@1.0.3: @@ -17434,7 +18501,7 @@ snapshots: chownr@2.0.0: {} - chromatic@11.3.0: {} + chromatic@11.5.4: {} ci-info@3.7.1: {} @@ -17459,8 +18526,6 @@ snapshots: parse5-htmlparser2-tree-adapter: 6.0.1 yargs: 16.2.0 - cli-spinners@2.7.0: {} - cli-spinners@2.9.2: {} cli-table3@0.6.3: @@ -17612,8 +18677,8 @@ snapshots: constantinople@4.0.1: dependencies: - '@babel/parser': 7.23.9 - '@babel/types': 7.23.5 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.0 content-disposition@0.5.4: dependencies: @@ -17631,7 +18696,7 @@ snapshots: cookie@0.6.0: {} - core-js-compat@3.33.3: + core-js-compat@3.37.1: dependencies: browserslist: 4.23.0 @@ -17653,13 +18718,13 @@ snapshots: crc-32: 1.2.2 readable-stream: 4.3.0 - create-jest@29.7.0(@types/node@20.12.7): + create-jest@29.7.0(@types/node@20.14.9): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.12.7) + jest-config: 29.7.0(@types/node@20.14.9) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -17705,7 +18770,9 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - crypto-random-string@2.0.0: {} + crypto-random-string@4.0.0: + dependencies: + type-fest: 1.4.0 css-declaration-sorter@7.2.0(postcss@8.4.38): dependencies: @@ -17793,7 +18860,7 @@ snapshots: dependencies: uniq: 1.0.1 - cypress@13.7.3: + cypress@13.13.0: dependencies: '@cypress/request': 3.0.0 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) @@ -17811,52 +18878,7 @@ snapshots: commander: 6.2.1 common-tags: 1.8.2 dayjs: 1.11.10 - debug: 4.3.4(supports-color@8.1.1) - enquirer: 2.3.6 - eventemitter2: 6.4.7 - execa: 4.1.0 - executable: 4.1.1 - extract-zip: 2.0.1(supports-color@8.1.1) - figures: 3.2.0 - fs-extra: 9.1.0 - getos: 3.2.1 - is-ci: 3.0.1 - is-installed-globally: 0.4.0 - lazy-ass: 1.6.0 - listr2: 3.14.0(enquirer@2.3.6) - lodash: 4.17.21 - log-symbols: 4.1.0 - minimist: 1.2.8 - ospath: 1.2.2 - pretty-bytes: 5.6.0 - process: 0.11.10 - proxy-from-env: 1.0.0 - request-progress: 3.0.0 - semver: 7.6.0 - supports-color: 8.1.1 - tmp: 0.2.3 - untildify: 4.0.0 - yauzl: 2.10.0 - - cypress@13.8.1: - dependencies: - '@cypress/request': 3.0.0 - '@cypress/xvfb': 1.2.4(supports-color@8.1.1) - '@types/sinonjs__fake-timers': 8.1.1 - '@types/sizzle': 2.3.3 - arch: 2.2.0 - blob-util: 2.0.2 - bluebird: 3.7.2 - buffer: 5.7.1 - cachedir: 2.3.0 - chalk: 4.1.2 - check-more-types: 2.24.0 - cli-cursor: 3.1.0 - cli-table3: 0.6.3 - commander: 6.2.1 - common-tags: 1.8.2 - dayjs: 1.11.10 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) enquirer: 2.3.6 eventemitter2: 6.4.7 execa: 4.1.0 @@ -17920,7 +18942,7 @@ snapshots: optionalDependencies: supports-color: 5.5.0 - debug@4.3.4(supports-color@8.1.1): + debug@4.3.5(supports-color@8.1.1): dependencies: ms: 2.1.2 optionalDependencies: @@ -18013,17 +19035,6 @@ snapshots: defu@6.1.4: {} - del@6.1.1: - dependencies: - globby: 11.1.0 - graceful-fs: 4.2.11 - is-glob: 4.0.3 - is-path-cwd: 2.2.0 - is-path-inside: 3.0.3 - p-map: 4.0.0 - rimraf: 3.0.2 - slash: 3.0.0 - delayed-stream@1.0.0: {} delegates@1.0.0: @@ -18046,6 +19057,8 @@ snapshots: detect-newline@3.1.0: {} + detect-node-es@1.1.0: {} + detect-package-manager@2.0.1: dependencies: execa: 5.1.1 @@ -18053,7 +19066,7 @@ snapshots: detect-port@1.5.1: dependencies: address: 1.2.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -18067,6 +19080,8 @@ snapshots: diff@5.1.0: {} + diff@5.2.0: {} + dijkstrajs@1.0.2: {} dir-glob@3.0.1: @@ -18140,7 +19155,7 @@ snapshots: ee-first@1.1.1: {} - ejs@3.1.9: + ejs@3.1.10: dependencies: jake: 10.8.5 @@ -18239,7 +19254,7 @@ snapshots: isarray: 2.0.5 stop-iteration-iterator: 1.0.0 - es-module-lexer@0.9.3: {} + es-module-lexer@1.5.4: {} es-set-tostringtag@2.0.1: dependencies: @@ -18267,10 +19282,10 @@ snapshots: esbuild-plugin-alias@0.2.1: {} - esbuild-register@3.5.0(esbuild@0.20.2): + esbuild-register@3.5.0(esbuild@0.19.11): dependencies: - debug: 4.3.4(supports-color@8.1.1) - esbuild: 0.20.2 + debug: 4.3.5(supports-color@8.1.1) + esbuild: 0.19.11 transitivePeerDependencies: - supports-color @@ -18325,31 +19340,58 @@ snapshots: '@esbuild/win32-ia32': 0.19.11 '@esbuild/win32-x64': 0.19.11 - esbuild@0.20.2: + esbuild@0.21.5: optionalDependencies: - '@esbuild/aix-ppc64': 0.20.2 - '@esbuild/android-arm': 0.20.2 - '@esbuild/android-arm64': 0.20.2 - '@esbuild/android-x64': 0.20.2 - '@esbuild/darwin-arm64': 0.20.2 - '@esbuild/darwin-x64': 0.20.2 - '@esbuild/freebsd-arm64': 0.20.2 - '@esbuild/freebsd-x64': 0.20.2 - '@esbuild/linux-arm': 0.20.2 - '@esbuild/linux-arm64': 0.20.2 - '@esbuild/linux-ia32': 0.20.2 - '@esbuild/linux-loong64': 0.20.2 - '@esbuild/linux-mips64el': 0.20.2 - '@esbuild/linux-ppc64': 0.20.2 - '@esbuild/linux-riscv64': 0.20.2 - '@esbuild/linux-s390x': 0.20.2 - '@esbuild/linux-x64': 0.20.2 - '@esbuild/netbsd-x64': 0.20.2 - '@esbuild/openbsd-x64': 0.20.2 - '@esbuild/sunos-x64': 0.20.2 - '@esbuild/win32-arm64': 0.20.2 - '@esbuild/win32-ia32': 0.20.2 - '@esbuild/win32-x64': 0.20.2 + '@esbuild/aix-ppc64': 0.21.5 + '@esbuild/android-arm': 0.21.5 + '@esbuild/android-arm64': 0.21.5 + '@esbuild/android-x64': 0.21.5 + '@esbuild/darwin-arm64': 0.21.5 + '@esbuild/darwin-x64': 0.21.5 + '@esbuild/freebsd-arm64': 0.21.5 + '@esbuild/freebsd-x64': 0.21.5 + '@esbuild/linux-arm': 0.21.5 + '@esbuild/linux-arm64': 0.21.5 + '@esbuild/linux-ia32': 0.21.5 + '@esbuild/linux-loong64': 0.21.5 + '@esbuild/linux-mips64el': 0.21.5 + '@esbuild/linux-ppc64': 0.21.5 + '@esbuild/linux-riscv64': 0.21.5 + '@esbuild/linux-s390x': 0.21.5 + '@esbuild/linux-x64': 0.21.5 + '@esbuild/netbsd-x64': 0.21.5 + '@esbuild/openbsd-x64': 0.21.5 + '@esbuild/sunos-x64': 0.21.5 + '@esbuild/win32-arm64': 0.21.5 + '@esbuild/win32-ia32': 0.21.5 + '@esbuild/win32-x64': 0.21.5 + + esbuild@0.22.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.22.0 + '@esbuild/android-arm': 0.22.0 + '@esbuild/android-arm64': 0.22.0 + '@esbuild/android-x64': 0.22.0 + '@esbuild/darwin-arm64': 0.22.0 + '@esbuild/darwin-x64': 0.22.0 + '@esbuild/freebsd-arm64': 0.22.0 + '@esbuild/freebsd-x64': 0.22.0 + '@esbuild/linux-arm': 0.22.0 + '@esbuild/linux-arm64': 0.22.0 + '@esbuild/linux-ia32': 0.22.0 + '@esbuild/linux-loong64': 0.22.0 + '@esbuild/linux-mips64el': 0.22.0 + '@esbuild/linux-ppc64': 0.22.0 + '@esbuild/linux-riscv64': 0.22.0 + '@esbuild/linux-s390x': 0.22.0 + '@esbuild/linux-x64': 0.22.0 + '@esbuild/netbsd-x64': 0.22.0 + '@esbuild/openbsd-arm64': 0.22.0 + '@esbuild/openbsd-x64': 0.22.0 + '@esbuild/sunos-x64': 0.22.0 + '@esbuild/win32-arm64': 0.22.0 + '@esbuild/win32-ia32': 0.22.0 + '@esbuild/win32-x64': 0.22.0 escalade@3.1.1: {} @@ -18392,37 +19434,17 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.53.0): + eslint-module-utils@2.8.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@9.6.0): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: - '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.3.3) - eslint: 8.53.0 + '@typescript-eslint/parser': 7.15.0(eslint@9.6.0)(typescript@5.5.3) + eslint: 9.6.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - dependencies: - debug: 3.2.7(supports-color@8.1.1) - optionalDependencies: - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.3.3) - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - - eslint-module-utils@2.8.0(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): - dependencies: - debug: 3.2.7(supports-color@8.1.1) - optionalDependencies: - '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.2) - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - transitivePeerDependencies: - - supports-color - - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint@8.53.0): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint@9.6.0): dependencies: array-includes: 3.1.7 array.prototype.findlastindex: 1.2.3 @@ -18430,9 +19452,9 @@ snapshots: array.prototype.flatmap: 1.3.2 debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 - eslint: 8.53.0 + eslint: 9.6.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.11.0(eslint@8.53.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.53.0) + eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.15.0(eslint@9.6.0)(typescript@5.5.3))(eslint-import-resolver-node@0.3.9)(eslint@9.6.0) hasown: 2.0.0 is-core-module: 2.13.1 is-glob: 4.0.3 @@ -18443,76 +19465,22 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.11.0(eslint@8.53.0)(typescript@5.3.3) + '@typescript-eslint/parser': 7.15.0(eslint@9.6.0)(typescript@5.5.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0): + eslint-plugin-vue@9.26.0(eslint@9.6.0): dependencies: - array-includes: 3.1.7 - array.prototype.findlastindex: 1.2.3 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7(supports-color@8.1.1) - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.0 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.7 - object.groupby: 1.0.1 - object.values: 1.1.7 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 7.1.0(eslint@8.57.0)(typescript@5.3.3) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0): - dependencies: - array-includes: 3.1.7 - array.prototype.findlastindex: 1.2.3 - array.prototype.flat: 1.3.2 - array.prototype.flatmap: 1.3.2 - debug: 3.2.7(supports-color@8.1.1) - doctrine: 2.1.0 - eslint: 8.57.0 - eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) - hasown: 2.0.0 - is-core-module: 2.13.1 - is-glob: 4.0.3 - minimatch: 3.1.2 - object.fromentries: 2.0.7 - object.groupby: 1.0.1 - object.values: 1.1.7 - semver: 6.3.1 - tsconfig-paths: 3.15.0 - optionalDependencies: - '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.2) - transitivePeerDependencies: - - eslint-import-resolver-typescript - - eslint-import-resolver-webpack - - supports-color - - eslint-plugin-vue@9.25.0(eslint@8.57.0): - dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - eslint: 8.57.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) + eslint: 9.6.0 globals: 13.24.0 natural-compare: 1.4.0 nth-check: 2.1.1 - postcss-selector-parser: 6.0.15 + postcss-selector-parser: 6.0.16 semver: 7.6.0 - vue-eslint-parser: 9.4.2(eslint@8.57.0) + vue-eslint-parser: 9.4.3(eslint@9.6.0) xml-name-validator: 4.0.0 transitivePeerDependencies: - supports-color @@ -18524,40 +19492,43 @@ snapshots: esrecurse: 4.3.0 estraverse: 5.3.0 + eslint-scope@8.0.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + eslint-visitor-keys@3.4.3: {} - eslint@8.53.0: + eslint-visitor-keys@4.0.0: {} + + eslint@9.6.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.53.0) - '@eslint-community/regexpp': 4.6.2 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.53.0 - '@humanwhocodes/config-array': 0.11.13 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.6.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/config-array': 0.17.0 + '@eslint/eslintrc': 3.1.0 + '@eslint/js': 9.6.0 '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) - doctrine: 3.0.0 + debug: 4.3.5(supports-color@8.1.1) escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.4.2 + eslint-scope: 8.0.1 + eslint-visitor-keys: 4.0.0 + espree: 10.1.0 + esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 + file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - globals: 13.19.0 - graphemer: 1.4.0 - ignore: 5.2.4 + ignore: 5.3.1 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 - js-yaml: 4.1.0 json-stable-stringify-without-jsonify: 1.0.1 levn: 0.4.1 lodash.merge: 4.6.2 @@ -18569,53 +19540,16 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@8.57.0: + espree@10.1.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@eslint-community/regexpp': 4.6.2 - '@eslint/eslintrc': 2.1.4 - '@eslint/js': 8.57.0 - '@humanwhocodes/config-array': 0.11.14 - '@humanwhocodes/module-importer': 1.0.1 - '@nodelib/fs.walk': 1.2.8 - '@ungap/structured-clone': 1.2.0 - ajv: 6.12.6 - chalk: 4.1.2 - cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) - doctrine: 3.0.0 - escape-string-regexp: 4.0.0 - eslint-scope: 7.2.2 - eslint-visitor-keys: 3.4.3 - espree: 9.6.1 - esquery: 1.4.2 - esutils: 2.0.3 - fast-deep-equal: 3.1.3 - file-entry-cache: 6.0.1 - find-up: 5.0.0 - glob-parent: 6.0.2 - globals: 13.19.0 - graphemer: 1.4.0 - ignore: 5.2.4 - imurmurhash: 0.1.4 - is-glob: 4.0.3 - is-path-inside: 3.0.3 - js-yaml: 4.1.0 - json-stable-stringify-without-jsonify: 1.0.1 - levn: 0.4.1 - lodash.merge: 4.6.2 - minimatch: 3.1.2 - natural-compare: 1.4.0 - optionator: 0.9.3 - strip-ansi: 6.0.1 - text-table: 0.2.0 - transitivePeerDependencies: - - supports-color + acorn: 8.12.0 + acorn-jsx: 5.3.2(acorn@8.12.0) + eslint-visitor-keys: 4.0.0 espree@9.6.1: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.12.0 + acorn-jsx: 5.3.2(acorn@8.12.0) eslint-visitor-keys: 3.4.3 esprima@4.0.1: {} @@ -18624,6 +19558,10 @@ snapshots: dependencies: estraverse: 5.3.0 + esquery@1.5.0: + dependencies: + estraverse: 5.3.0 + esrecurse@4.3.0: dependencies: estraverse: 5.3.0 @@ -18718,6 +19656,21 @@ snapshots: signal-exit: 4.1.0 strip-final-newline: 3.0.0 + execa@9.2.0: + dependencies: + '@sindresorhus/merge-streams': 4.0.0 + cross-spawn: 7.0.3 + figures: 6.1.0 + get-stream: 9.0.1 + human-signals: 7.0.0 + is-plain-obj: 4.1.0 + is-stream: 4.0.1 + npm-run-path: 5.3.0 + pretty-ms: 9.0.0 + signal-exit: 4.1.0 + strip-final-newline: 4.0.0 + yoctocolors: 2.0.2 + executable@4.1.1: dependencies: pify: 2.3.0 @@ -18734,42 +19687,6 @@ snapshots: exponential-backoff@3.1.1: {} - express@4.18.2: - dependencies: - accepts: 1.3.8 - array-flatten: 1.1.1 - body-parser: 1.20.1 - content-disposition: 0.5.4 - content-type: 1.0.5 - cookie: 0.5.0 - cookie-signature: 1.0.6 - debug: 2.6.9 - depd: 2.0.0 - encodeurl: 1.0.2 - escape-html: 1.0.3 - etag: 1.8.1 - finalhandler: 1.2.0 - fresh: 0.5.2 - http-errors: 2.0.0 - merge-descriptors: 1.0.1 - methods: 1.1.2 - on-finished: 2.4.1 - parseurl: 1.3.3 - path-to-regexp: 0.1.7 - proxy-addr: 2.0.7 - qs: 6.11.0 - range-parser: 1.2.1 - safe-buffer: 5.2.1 - send: 0.18.0 - serve-static: 1.15.0 - setprototypeof: 1.2.0 - statuses: 2.0.1 - type-is: 1.6.18 - utils-merge: 1.0.1 - vary: 1.1.2 - transitivePeerDependencies: - - supports-color - express@4.19.2: dependencies: accepts: 1.3.8 @@ -18819,7 +19736,7 @@ snapshots: extract-zip@2.0.1(supports-color@8.1.1): dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) get-stream: 5.2.0 yauzl: 2.10.0 optionalDependencies: @@ -18843,15 +19760,15 @@ snapshots: '@nodelib/fs.walk': 1.2.8 glob-parent: 5.1.2 merge2: 1.4.1 - micromatch: 4.0.5 + micromatch: 4.0.7 fast-json-stable-stringify@2.1.0: {} fast-json-stringify@5.8.0: dependencies: '@fastify/deepmerge': 1.3.0 - ajv: 8.13.0 - ajv-formats: 2.1.1(ajv@8.13.0) + ajv: 8.16.0 + ajv-formats: 2.1.1(ajv@8.16.0) fast-deep-equal: 3.1.3 fast-uri: 2.2.0 rfdc: 1.3.0 @@ -18880,7 +19797,7 @@ snapshots: raw-body: 2.5.2 secure-json-parse: 2.7.0 - fastify@4.26.2: + fastify@4.28.1: dependencies: '@fastify/ajv-compiler': 3.5.0 '@fastify/error': 3.4.0 @@ -18891,20 +19808,16 @@ snapshots: fast-json-stringify: 5.8.0 find-my-way: 8.2.0 light-my-request: 5.11.0 - pino: 8.17.0 + pino: 9.2.0 process-warning: 3.0.0 proxy-addr: 2.0.7 rfdc: 1.3.0 secure-json-parse: 2.7.0 semver: 7.6.0 - toad-cache: 3.3.0 + toad-cache: 3.7.0 transitivePeerDependencies: - supports-color - fastq@1.15.0: - dependencies: - reusify: 1.0.4 - fastq@1.17.1: dependencies: reusify: 1.0.4 @@ -18932,9 +19845,13 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 - file-entry-cache@6.0.1: + figures@6.1.0: dependencies: - flat-cache: 3.0.4 + is-unicode-supported: 2.0.0 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 file-system-cache@2.3.0: dependencies: @@ -18969,6 +19886,10 @@ snapshots: dependencies: to-regex-range: 5.0.1 + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + finalhandler@1.2.0: dependencies: debug: 2.6.9 @@ -19028,23 +19949,23 @@ snapshots: ps-list: 8.1.1 taskkill: 5.0.0 - flat-cache@3.0.4: + flat-cache@4.0.1: dependencies: - flatted: 3.2.7 - rimraf: 3.0.2 + flatted: 3.3.1 + keyv: 4.5.4 - flatted@3.2.7: {} + flatted@3.3.1: {} flow-parser@0.202.0: {} - fluent-ffmpeg@2.1.2: + fluent-ffmpeg@2.1.3: dependencies: - async: 3.2.4 + async: 0.2.10 which: 1.3.1 - follow-redirects@1.15.2(debug@4.3.4): + follow-redirects@1.15.2(debug@4.3.5): optionalDependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) for-each@0.3.3: dependencies: @@ -19171,6 +20092,8 @@ snapshots: has-proto: 1.0.1 has-symbols: 1.0.3 + get-nonce@1.0.1: {} + get-npm-tarball-url@2.0.3: {} get-package-type@0.1.0: {} @@ -19199,6 +20122,11 @@ snapshots: get-stream@8.0.1: {} + get-stream@9.0.1: + dependencies: + '@sec-ant/readable-stream': 0.4.1 + is-stream: 4.0.1 + get-symbol-description@1.0.0: dependencies: call-bind: 1.0.2 @@ -19265,6 +20193,15 @@ snapshots: minipass: 7.0.4 path-scurry: 1.10.2 + glob@10.4.2: + dependencies: + foreground-child: 3.1.1 + jackspeak: 3.4.0 + minimatch: 9.0.4 + minipass: 7.1.2 + package-json-from-dist: 1.0.0 + path-scurry: 1.11.1 + glob@7.2.3: dependencies: fs.realpath: 1.0.0 @@ -19288,14 +20225,14 @@ snapshots: globals@11.12.0: {} - globals@13.19.0: - dependencies: - type-fest: 0.20.2 - globals@13.24.0: dependencies: type-fest: 0.20.2 + globals@14.0.0: {} + + globals@15.7.0: {} + globalthis@1.0.3: dependencies: define-properties: 1.2.0 @@ -19309,6 +20246,15 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 + globby@14.0.1: + dependencies: + '@sindresorhus/merge-streams': 2.3.0 + fast-glob: 3.3.2 + ignore: 5.3.1 + path-type: 5.0.0 + slash: 5.1.0 + unicorn-magic: 0.1.0 + google-protobuf@3.21.2: optional: true @@ -19344,12 +20290,12 @@ snapshots: p-cancelable: 3.0.0 responselike: 3.0.0 - got@14.2.1: + got@14.4.1: dependencies: - '@sindresorhus/is': 6.1.0 + '@sindresorhus/is': 6.3.1 '@szmarczak/http-timer': 5.0.1 cacheable-lookup: 7.0.0 - cacheable-request: 10.2.14 + cacheable-request: 12.0.1 decompress-response: 6.0.0 form-data-encoder: 4.0.2 get-stream: 8.0.1 @@ -19357,6 +20303,7 @@ snapshots: lowercase-keys: 3.0.0 p-cancelable: 4.0.1 responselike: 3.0.0 + type-fest: 4.20.1 graceful-fs@4.2.11: {} @@ -19499,7 +20446,14 @@ snapshots: http-proxy-agent@7.0.0: dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + http-proxy-agent@7.0.2: + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -19538,14 +20492,21 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) transitivePeerDependencies: - supports-color https-proxy-agent@7.0.2: dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) + transitivePeerDependencies: + - supports-color + + https-proxy-agent@7.0.4: + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -19557,6 +20518,8 @@ snapshots: human-signals@5.0.0: {} + human-signals@7.0.0: {} + iconv-lite@0.4.24: dependencies: safer-buffer: 2.1.2 @@ -19588,16 +20551,16 @@ snapshots: import-in-the-middle@1.4.2: dependencies: - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) + acorn: 8.12.0 + acorn-import-assertions: 1.9.0(acorn@8.12.0) cjs-module-lexer: 1.2.2 module-details-from-path: 1.0.3 optional: true - import-in-the-middle@1.7.4: + import-in-the-middle@1.8.1: dependencies: - acorn: 8.11.3 - acorn-import-attributes: 1.9.5(acorn@8.11.3) + acorn: 8.12.0 + acorn-import-attributes: 1.9.5(acorn@8.12.0) cjs-module-lexer: 1.2.2 module-details-from-path: 1.0.3 @@ -19637,11 +20600,15 @@ snapshots: intersection-observer@0.12.2: {} + invariant@2.2.4: + dependencies: + loose-envify: 1.4.0 + ioredis@5.4.1: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -19653,15 +20620,14 @@ snapshots: iota-array@1.0.0: {} - ip-address@7.1.0: + ip-address@9.0.5: dependencies: jsbn: 1.1.0 - sprintf-js: 1.1.2 + sprintf-js: 1.1.3 - ip-cidr@3.1.0: + ip-cidr@4.0.1: dependencies: - ip-address: 7.1.0 - jsbn: 1.1.0 + ip-address: 9.0.5 ip-regex@4.3.0: {} @@ -19776,8 +20742,6 @@ snapshots: is-number@7.0.0: {} - is-path-cwd@2.2.0: {} - is-path-inside@3.0.3: {} is-plain-obj@1.1.0: {} @@ -19811,11 +20775,13 @@ snapshots: is-stream@3.0.0: {} + is-stream@4.0.1: {} + is-string@1.0.7: dependencies: has-tostringtag: 1.0.0 - is-svg@5.0.0: + is-svg@5.0.1: dependencies: fast-xml-parser: 4.2.5 @@ -19835,6 +20801,8 @@ snapshots: is-unicode-supported@0.1.0: {} + is-unicode-supported@2.0.0: {} + is-weakmap@2.0.1: {} is-weakref@1.0.2: @@ -19868,8 +20836,8 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: - '@babel/core': 7.24.0 - '@babel/parser': 7.24.0 + '@babel/core': 7.24.7 + '@babel/parser': 7.24.7 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -19878,8 +20846,8 @@ snapshots: istanbul-lib-instrument@6.0.0: dependencies: - '@babel/core': 7.24.0 - '@babel/parser': 7.24.0 + '@babel/core': 7.24.7 + '@babel/parser': 7.24.7 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 semver: 7.6.0 @@ -19894,12 +20862,20 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: - supports-color + istanbul-lib-source-maps@5.0.4: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + debug: 4.3.5(supports-color@8.1.1) + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + istanbul-reports@3.1.6: dependencies: html-escaper: 2.0.2 @@ -19913,6 +20889,12 @@ snapshots: optionalDependencies: '@pkgjs/parseargs': 0.11.0 + jackspeak@3.4.0: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + jake@10.8.5: dependencies: async: 3.2.4 @@ -19932,7 +20914,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 chalk: 4.1.2 co: 4.6.0 dedent: 1.3.0 @@ -19952,16 +20934,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.12.7): + jest-cli@29.7.0(@types/node@20.14.9): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.12.7) + create-jest: 29.7.0(@types/node@20.14.9) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.12.7) + jest-config: 29.7.0(@types/node@20.14.9) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -19971,7 +20953,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.12.7): + jest-config@29.7.0(@types/node@20.14.9): dependencies: '@babel/core': 7.23.5 '@jest/test-sequencer': 29.7.0 @@ -19990,13 +20972,13 @@ snapshots: jest-runner: 29.7.0 jest-util: 29.7.0 jest-validate: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.7 parse-json: 5.2.0 pretty-format: 29.7.0 slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -20025,7 +21007,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -20042,14 +21024,14 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.6 - '@types/node': 20.12.7 + '@types/node': 20.14.9 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 jest-regex-util: 29.6.3 jest-util: 29.7.0 jest-worker: 29.7.0 - micromatch: 4.0.5 + micromatch: 4.0.7 walker: 1.0.8 optionalDependencies: fsevents: 2.3.3 @@ -20073,7 +21055,7 @@ snapshots: '@types/stack-utils': 2.0.1 chalk: 4.1.2 graceful-fs: 4.2.11 - micromatch: 4.0.5 + micromatch: 4.0.7 pretty-format: 29.7.0 slash: 3.0.0 stack-utils: 2.0.6 @@ -20081,7 +21063,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -20116,7 +21098,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -20144,7 +21126,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 chalk: 4.1.2 cjs-module-lexer: 1.2.2 collect-v8-coverage: 1.0.1 @@ -20190,7 +21172,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 chalk: 4.1.2 ci-info: 3.7.1 graceful-fs: 4.2.11 @@ -20209,7 +21191,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.12.7 + '@types/node': 20.14.9 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -20223,17 +21205,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.12.7): + jest@29.7.0(@types/node@20.14.9): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.12.7) + jest-cli: 29.7.0(@types/node@20.14.9) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -20263,6 +21245,8 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.0: {} + js-yaml@3.14.1: dependencies: argparse: 1.0.10 @@ -20278,55 +21262,55 @@ snapshots: jschardet@3.0.0: {} - jscodeshift@0.15.1(@babel/preset-env@7.23.5(@babel/core@7.24.0)): + jscodeshift@0.15.1(@babel/preset-env@7.24.7(@babel/core@7.24.7)): dependencies: - '@babel/core': 7.24.0 - '@babel/parser': 7.24.0 - '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.24.0) - '@babel/plugin-transform-nullish-coalescing-operator': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.24.0) - '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.24.0) - '@babel/preset-flow': 7.23.3(@babel/core@7.24.0) - '@babel/preset-typescript': 7.23.3(@babel/core@7.24.0) - '@babel/register': 7.22.15(@babel/core@7.24.0) - babel-core: 7.0.0-bridge.0(@babel/core@7.24.0) + '@babel/core': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/plugin-transform-class-properties': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-modules-commonjs': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-nullish-coalescing-operator': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-optional-chaining': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-private-methods': 7.24.7(@babel/core@7.24.7) + '@babel/preset-flow': 7.23.3(@babel/core@7.24.7) + '@babel/preset-typescript': 7.23.3(@babel/core@7.24.7) + '@babel/register': 7.22.15(@babel/core@7.24.7) + babel-core: 7.0.0-bridge.0(@babel/core@7.24.7) chalk: 4.1.2 flow-parser: 0.202.0 graceful-fs: 4.2.11 - micromatch: 4.0.5 + micromatch: 4.0.7 neo-async: 2.6.2 node-dir: 0.1.17 - recast: 0.23.4 + recast: 0.23.6 temp: 0.8.4 write-file-atomic: 2.4.3 optionalDependencies: - '@babel/preset-env': 7.23.5(@babel/core@7.24.0) + '@babel/preset-env': 7.24.7(@babel/core@7.24.7) transitivePeerDependencies: - supports-color - jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3): + jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3): dependencies: cssstyle: 4.0.1 data-urls: 5.0.0 decimal.js: 10.4.3 form-data: 4.0.0 html-encoding-sniffer: 4.0.0 - http-proxy-agent: 7.0.0 - https-proxy-agent: 7.0.2 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 is-potential-custom-element-name: 1.0.1 - nwsapi: 2.2.9 + nwsapi: 2.2.10 parse5: 7.1.2 - rrweb-cssom: 0.6.0 + rrweb-cssom: 0.7.1 saxes: 6.0.0 symbol-tree: 3.2.4 - tough-cookie: 4.1.3 + tough-cookie: 4.1.4 w3c-xmlserializer: 5.0.0 webidl-conversions: 7.0.0 whatwg-encoding: 3.1.1 whatwg-mimetype: 4.0.0 whatwg-url: 14.0.0 - ws: 8.17.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) + ws: 8.17.1(bufferutil@4.0.7)(utf-8-validate@6.0.3) xml-name-validator: 5.0.0 transitivePeerDependencies: - bufferutil @@ -20407,8 +21391,6 @@ snapshots: jsrsasign@11.1.0: {} - jssha@3.3.1: {} - jstransformer@1.0.0: dependencies: is-promise: 2.2.2 @@ -20487,7 +21469,10 @@ snapshots: optionalDependencies: enquirer: 2.3.6 - local-pkg@0.4.3: {} + local-pkg@0.5.0: + dependencies: + mlly: 1.5.0 + pkg-types: 1.0.3 locate-path@3.0.0: dependencies: @@ -20510,8 +21495,6 @@ snapshots: lodash.isarguments@3.1.0: {} - lodash.isequal@4.5.0: {} - lodash.memoize@4.1.2: {} lodash.merge@4.6.2: {} @@ -20583,9 +21566,11 @@ snapshots: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 - magic-string@0.30.7: + magicast@0.3.4: dependencies: - '@jridgewell/sourcemap-codec': 1.4.15 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.0 + source-map-js: 1.2.0 mailcheck@1.1.1: {} @@ -20745,7 +21730,7 @@ snapshots: media-typer@0.3.0: {} - meilisearch@0.38.0(encoding@0.1.13): + meilisearch@0.41.0(encoding@0.1.13): dependencies: cross-fetch: 3.1.6(encoding@0.1.13) transitivePeerDependencies: @@ -20958,7 +21943,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.0 @@ -20977,9 +21962,9 @@ snapshots: transitivePeerDependencies: - supports-color - micromatch@4.0.5: + micromatch@4.0.7: dependencies: - braces: 3.0.2 + braces: 3.0.3 picomatch: 2.3.1 mime-db@1.52.0: {} @@ -21076,6 +22061,8 @@ snapshots: minipass@7.0.4: {} + minipass@7.1.2: {} + minizlib@1.3.3: dependencies: minipass: 2.9.0 @@ -21098,7 +22085,7 @@ snapshots: mlly@1.5.0: dependencies: - acorn: 8.11.3 + acorn: 8.12.0 pathe: 1.1.2 pkg-types: 1.0.3 ufo: 1.3.2 @@ -21137,18 +22124,18 @@ snapshots: optionalDependencies: msgpackr-extract: 3.0.2 - msw-storybook-addon@2.0.1(msw@2.2.14(typescript@5.5.2)): + msw-storybook-addon@2.0.2(msw@2.3.1(typescript@5.5.3)): dependencies: is-node-process: 1.2.0 - msw: 2.2.14(typescript@5.5.2) + msw: 2.3.1(typescript@5.5.3) - msw@2.2.14(typescript@5.5.2): + msw@2.3.1(typescript@5.5.3): dependencies: '@bundled-es-modules/cookie': 2.0.0 '@bundled-es-modules/statuses': 1.0.1 '@inquirer/confirm': 3.1.6 '@mswjs/cookies': 1.1.0 - '@mswjs/interceptors': 0.26.15 + '@mswjs/interceptors': 0.29.1 '@open-draft/until': 2.1.0 '@types/cookie': 0.6.0 '@types/statuses': 2.0.4 @@ -21162,7 +22149,7 @@ snapshots: type-fest: 4.9.0 yargs: 17.7.2 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 muggle-string@0.4.1: {} @@ -21294,7 +22281,7 @@ snapshots: dependencies: env-paths: 2.2.1 exponential-backoff: 3.1.1 - glob: 10.3.12 + glob: 10.4.2 graceful-fs: 4.2.11 make-fetch-happen: 13.0.0 nopt: 7.2.0 @@ -21309,7 +22296,7 @@ snapshots: node-releases@2.0.14: {} - nodemailer@6.9.13: {} + nodemailer@6.9.14: {} nodemon@3.0.2: dependencies: @@ -21324,14 +22311,14 @@ snapshots: touch: 3.1.0 undefsafe: 2.0.5 - nodemon@3.1.0: + nodemon@3.1.4: dependencies: chokidar: 3.5.3 debug: 4.3.4(supports-color@5.5.0) ignore-by-default: 1.0.1 minimatch: 3.1.2 pstree.remy: 1.1.8 - semver: 7.5.4 + semver: 7.6.0 simple-update-notifier: 2.0.0 supports-color: 5.5.0 touch: 3.1.0 @@ -21376,6 +22363,8 @@ snapshots: normalize-url@8.0.0: {} + normalize-url@8.0.1: {} + npm-run-path@2.0.2: dependencies: path-key: 2.0.1 @@ -21388,6 +22377,10 @@ snapshots: dependencies: path-key: 4.0.0 + npm-run-path@5.3.0: + dependencies: + path-key: 4.0.0 + npmlog@5.0.1: dependencies: are-we-there-yet: 2.0.0 @@ -21405,7 +22398,7 @@ snapshots: dependencies: boolbase: 1.0.0 - nwsapi@2.2.9: {} + nwsapi@2.2.10: {} oauth-sign@0.9.0: {} @@ -21505,9 +22498,9 @@ snapshots: opentelemetry-instrumentation-fetch-node@1.2.0: dependencies: - '@opentelemetry/api': 1.8.0 - '@opentelemetry/instrumentation': 0.43.0(@opentelemetry/api@1.8.0) - '@opentelemetry/semantic-conventions': 1.24.1 + '@opentelemetry/api': 1.9.0 + '@opentelemetry/instrumentation': 0.43.0(@opentelemetry/api@1.9.0) + '@opentelemetry/semantic-conventions': 1.25.1 transitivePeerDependencies: - supports-color optional: true @@ -21526,7 +22519,7 @@ snapshots: bl: 4.1.0 chalk: 4.1.2 cli-cursor: 3.1.0 - cli-spinners: 2.7.0 + cli-spinners: 2.9.2 is-interactive: 1.0.0 is-unicode-supported: 0.1.0 log-symbols: 4.1.0 @@ -21541,9 +22534,9 @@ snapshots: ospath@1.2.2: {} - otpauth@9.2.3: + otpauth@9.3.1: dependencies: - jssha: 3.3.1 + '@noble/hashes': 1.4.0 outvariant@1.4.2: {} @@ -21563,7 +22556,7 @@ snapshots: dependencies: yocto-queue: 0.1.0 - p-limit@4.0.0: + p-limit@5.0.0: dependencies: yocto-queue: 1.0.0 @@ -21594,6 +22587,8 @@ snapshots: p-try@2.2.0: {} + package-json-from-dist@1.0.0: {} + pako@0.2.9: {} parent-module@1.0.1: @@ -21611,6 +22606,8 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse-ms@4.0.0: {} + parse-srcset@1.0.2: {} parse5-htmlparser2-tree-adapter@6.0.1: @@ -21658,6 +22655,11 @@ snapshots: lru-cache: 10.2.2 minipass: 7.0.4 + path-scurry@1.11.1: + dependencies: + lru-cache: 10.2.2 + minipass: 7.1.2 + path-to-regexp@0.1.7: {} path-to-regexp@1.8.0: @@ -21670,6 +22672,8 @@ snapshots: path-type@4.0.0: {} + path-type@5.0.0: {} + pathe@1.1.2: {} pathval@1.1.1: {} @@ -21699,11 +22703,9 @@ snapshots: pg-numeric@1.0.2: {} - pg-pool@3.6.2(pg@8.11.5): + pg-pool@3.6.2(pg@8.12.0): dependencies: - pg: 8.11.5 - - pg-protocol@1.6.0: {} + pg: 8.12.0 pg-protocol@1.6.1: {} @@ -21725,10 +22727,10 @@ snapshots: postgres-interval: 3.0.0 postgres-range: 1.1.3 - pg@8.11.5: + pg@8.12.0: dependencies: pg-connection-string: 2.6.4 - pg-pool: 3.6.2(pg@8.11.5) + pg-pool: 3.6.2(pg@8.12.0) pg-protocol: 1.6.1 pg-types: 2.2.0 pgpass: 1.0.5 @@ -21739,7 +22741,7 @@ snapshots: dependencies: split2: 4.1.0 - photoswipe@5.4.3: {} + photoswipe@5.4.4: {} picocolors@1.0.0: {} @@ -21753,26 +22755,26 @@ snapshots: pify@4.0.1: {} - pino-abstract-transport@1.1.0: + pino-abstract-transport@1.2.0: dependencies: readable-stream: 4.3.0 split2: 4.1.0 - pino-std-serializers@6.1.0: {} + pino-std-serializers@7.0.0: {} - pino@8.17.0: + pino@9.2.0: dependencies: atomic-sleep: 1.0.0 fast-redact: 3.1.2 on-exit-leak-free: 2.1.0 - pino-abstract-transport: 1.1.0 - pino-std-serializers: 6.1.0 - process-warning: 2.2.0 + pino-abstract-transport: 1.2.0 + pino-std-serializers: 7.0.0 + process-warning: 3.0.0 quick-format-unescaped: 4.0.4 real-require: 0.2.0 safe-stable-stringify: 2.4.2 - sonic-boom: 3.7.0 - thread-stream: 2.3.0 + sonic-boom: 4.0.1 + thread-stream: 3.1.0 pirates@4.0.5: {} @@ -22007,7 +23009,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier@3.2.5: {} + prettier@3.3.2: {} pretty-bytes@5.6.0: {} @@ -22025,6 +23027,10 @@ snapshots: pretty-hrtime@1.0.3: {} + pretty-ms@9.0.0: + dependencies: + parse-ms: 4.0.0 + private-ip@2.3.3: dependencies: ip-regex: 4.3.0 @@ -22110,19 +23116,21 @@ snapshots: js-stringify: 1.0.2 pug-runtime: 3.0.1 - pug-code-gen@3.0.2: + pug-code-gen@3.0.3: dependencies: constantinople: 4.0.1 doctypes: 1.1.0 js-stringify: 1.0.2 pug-attrs: 3.0.0 - pug-error: 2.0.0 + pug-error: 2.1.0 pug-runtime: 3.0.1 void-elements: 3.1.0 with: 7.0.2 pug-error@2.0.0: {} + pug-error@2.1.0: {} + pug-filters@4.0.0: dependencies: constantinople: 4.0.1 @@ -22160,9 +23168,9 @@ snapshots: pug-walk@2.0.0: {} - pug@3.0.2: + pug@3.0.3: dependencies: - pug-code-gen: 3.0.2 + pug-code-gen: 3.0.3 pug-filters: 4.0.0 pug-lexer: 5.0.1 pug-linker: 4.0.0 @@ -22242,13 +23250,6 @@ snapshots: ratelimiter@3.4.1: {} - raw-body@2.5.1: - dependencies: - bytes: 3.1.2 - http-errors: 2.0.0 - iconv-lite: 0.4.24 - unpipe: 1.0.0 - raw-body@2.5.2: dependencies: bytes: 3.1.2 @@ -22260,7 +23261,7 @@ snapshots: dependencies: setimmediate: 1.0.5 - re2@1.21.2: + re2@1.21.3: dependencies: install-artifact-from-github: 1.3.5 nan: 2.20.0 @@ -22273,15 +23274,15 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - react-docgen-typescript@2.2.2(typescript@5.5.2): + react-docgen-typescript@2.2.2(typescript@5.5.3): dependencies: - typescript: 5.5.2 + typescript: 5.5.3 react-docgen@7.0.1: dependencies: - '@babel/core': 7.24.0 - '@babel/traverse': 7.24.0 - '@babel/types': 7.24.0 + '@babel/core': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 '@types/babel__core': 7.20.0 '@types/babel__traverse': 7.20.0 '@types/doctrine': 0.0.9 @@ -22314,6 +23315,34 @@ snapshots: react-is@18.2.0: {} + react-remove-scroll-bar@2.3.6(@types/react@18.0.28)(react@18.3.1): + dependencies: + react: 18.3.1 + react-style-singleton: 2.2.1(@types/react@18.0.28)(react@18.3.1) + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.0.28 + + react-remove-scroll@2.5.7(@types/react@18.0.28)(react@18.3.1): + dependencies: + react: 18.3.1 + react-remove-scroll-bar: 2.3.6(@types/react@18.0.28)(react@18.3.1) + react-style-singleton: 2.2.1(@types/react@18.0.28)(react@18.3.1) + tslib: 2.6.2 + use-callback-ref: 1.3.2(@types/react@18.0.28)(react@18.3.1) + use-sidecar: 1.1.2(@types/react@18.0.28)(react@18.3.1) + optionalDependencies: + '@types/react': 18.0.28 + + react-style-singleton@2.2.1(@types/react@18.0.28)(react@18.3.1): + dependencies: + get-nonce: 1.0.1 + invariant: 2.2.4 + react: 18.3.1 + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.0.28 + react@18.3.1: dependencies: loose-envify: 1.4.0 @@ -22375,14 +23404,6 @@ snapshots: real-require@0.2.0: {} - recast@0.23.4: - dependencies: - assert: 2.1.0 - ast-types: 0.16.1 - esprima: 4.0.1 - source-map: 0.6.1 - tslib: 2.6.2 - recast@0.23.6: dependencies: ast-types: 0.16.1 @@ -22527,7 +23548,7 @@ snapshots: require-in-the-middle@7.3.0: dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: @@ -22551,11 +23572,6 @@ snapshots: resolve.exports@2.0.0: {} - resolve@1.19.0: - dependencies: - is-core-module: 2.13.1 - path-parse: 1.0.7 - resolve@1.22.8: dependencies: is-core-module: 2.13.1 @@ -22595,31 +23611,34 @@ snapshots: rimraf@3.0.2: dependencies: glob: 7.2.3 + optional: true - rollup@4.17.2: + rollup@4.18.0: dependencies: '@types/estree': 1.0.5 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 + '@rollup/rollup-android-arm-eabi': 4.18.0 + '@rollup/rollup-android-arm64': 4.18.0 + '@rollup/rollup-darwin-arm64': 4.18.0 + '@rollup/rollup-darwin-x64': 4.18.0 + '@rollup/rollup-linux-arm-gnueabihf': 4.18.0 + '@rollup/rollup-linux-arm-musleabihf': 4.18.0 + '@rollup/rollup-linux-arm64-gnu': 4.18.0 + '@rollup/rollup-linux-arm64-musl': 4.18.0 + '@rollup/rollup-linux-powerpc64le-gnu': 4.18.0 + '@rollup/rollup-linux-riscv64-gnu': 4.18.0 + '@rollup/rollup-linux-s390x-gnu': 4.18.0 + '@rollup/rollup-linux-x64-gnu': 4.18.0 + '@rollup/rollup-linux-x64-musl': 4.18.0 + '@rollup/rollup-win32-arm64-msvc': 4.18.0 + '@rollup/rollup-win32-ia32-msvc': 4.18.0 + '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 rrweb-cssom@0.6.0: {} + rrweb-cssom@0.7.1: {} + rss-parser@3.13.0: dependencies: entities: 2.2.0 @@ -22667,7 +23686,7 @@ snapshots: parse-srcset: 1.0.2 postcss: 8.4.38 - sass@1.76.0: + sass@1.77.6: dependencies: chokidar: 3.5.3 immutable: 4.2.2 @@ -22749,14 +23768,14 @@ snapshots: dependencies: kind-of: 6.0.3 - sharp@0.33.3: + sharp@0.33.4: dependencies: color: 4.2.3 detect-libc: 2.0.3 semver: 7.6.0 optionalDependencies: - '@img/sharp-darwin-arm64': 0.33.3 - '@img/sharp-darwin-x64': 0.33.3 + '@img/sharp-darwin-arm64': 0.33.4 + '@img/sharp-darwin-x64': 0.33.4 '@img/sharp-libvips-darwin-arm64': 1.0.2 '@img/sharp-libvips-darwin-x64': 1.0.2 '@img/sharp-libvips-linux-arm': 1.0.2 @@ -22765,15 +23784,15 @@ snapshots: '@img/sharp-libvips-linux-x64': 1.0.2 '@img/sharp-libvips-linuxmusl-arm64': 1.0.2 '@img/sharp-libvips-linuxmusl-x64': 1.0.2 - '@img/sharp-linux-arm': 0.33.3 - '@img/sharp-linux-arm64': 0.33.3 - '@img/sharp-linux-s390x': 0.33.3 - '@img/sharp-linux-x64': 0.33.3 - '@img/sharp-linuxmusl-arm64': 0.33.3 - '@img/sharp-linuxmusl-x64': 0.33.3 - '@img/sharp-wasm32': 0.33.3 - '@img/sharp-win32-ia32': 0.33.3 - '@img/sharp-win32-x64': 0.33.3 + '@img/sharp-linux-arm': 0.33.4 + '@img/sharp-linux-arm64': 0.33.4 + '@img/sharp-linux-s390x': 0.33.4 + '@img/sharp-linux-x64': 0.33.4 + '@img/sharp-linuxmusl-arm64': 0.33.4 + '@img/sharp-linuxmusl-x64': 0.33.4 + '@img/sharp-wasm32': 0.33.4 + '@img/sharp-win32-ia32': 0.33.4 + '@img/sharp-win32-x64': 0.33.4 shebang-command@1.2.0: dependencies: @@ -22787,9 +23806,9 @@ snapshots: shebang-regex@3.0.0: {} - shiki@1.4.0: + shiki@1.10.0: dependencies: - '@shikijs/core': 1.4.0 + '@shikijs/core': 1.10.0 shimmer@1.2.1: {} @@ -22805,11 +23824,11 @@ snapshots: signal-exit@4.1.0: {} - simple-oauth2@5.0.0: + simple-oauth2@5.0.1: dependencies: - '@hapi/hoek': 10.0.1 + '@hapi/hoek': 11.0.4 '@hapi/wreck': 18.0.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) joi: 17.11.0 transitivePeerDependencies: - supports-color @@ -22890,6 +23909,8 @@ snapshots: slash@3.0.0: {} + slash@5.1.0: {} + slice-ansi@3.0.0: dependencies: ansi-styles: 4.3.0 @@ -22907,7 +23928,7 @@ snapshots: socks-proxy-agent@8.0.2: dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) socks: 2.7.1 transitivePeerDependencies: - supports-color @@ -22917,7 +23938,7 @@ snapshots: ip: 2.0.1 smart-buffer: 4.2.0 - sonic-boom@3.7.0: + sonic-boom@4.0.1: dependencies: atomic-sleep: 1.0.0 @@ -22973,7 +23994,7 @@ snapshots: sprintf-js@1.0.3: {} - sprintf-js@1.1.2: {} + sprintf-js@1.1.3: {} sshpk@1.17.0: dependencies: @@ -22999,16 +24020,16 @@ snapshots: standard-as-callback@2.1.0: {} - start-server-and-test@2.0.3: + start-server-and-test@2.0.4: dependencies: arg: 5.0.2 bluebird: 3.7.2 check-more-types: 2.24.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.5(supports-color@8.1.1) execa: 5.1.1 lazy-ass: 1.6.0 ps-tree: 1.2.0 - wait-on: 7.2.0(debug@4.3.4) + wait-on: 7.2.0(debug@4.3.5) transitivePeerDependencies: - supports-color @@ -23022,22 +24043,22 @@ snapshots: store2@2.14.2: {} - storybook-addon-misskey-theme@https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/components@8.0.9(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/core-events@8.0.9)(@storybook/manager-api@8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/preview-api@8.0.9)(@storybook/theming@8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/types@8.0.9)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + storybook-addon-misskey-theme@https://codeload.github.com/misskey-dev/storybook-addon-misskey-theme/tar.gz/cf583db098365b2ccc81a82f63ca9c93bc32b640(@storybook/blocks@8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/components@8.1.11(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/core-events@8.1.11)(@storybook/manager-api@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/preview-api@8.1.11)(@storybook/theming@8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(@storybook/types@8.1.11)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: - '@storybook/blocks': 8.0.9(@types/react@18.0.28)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/components': 8.0.9(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/core-events': 8.0.9 - '@storybook/manager-api': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/preview-api': 8.0.9 - '@storybook/theming': 8.0.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@storybook/types': 8.0.9 + '@storybook/blocks': 8.1.11(@types/react@18.0.28)(encoding@0.1.13)(prettier@3.3.2)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/components': 8.1.11(@types/react@18.0.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/core-events': 8.1.11 + '@storybook/manager-api': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/preview-api': 8.1.11 + '@storybook/theming': 8.1.11(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@storybook/types': 8.1.11 optionalDependencies: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - storybook@8.0.9(@babel/preset-env@7.23.5(@babel/core@7.24.0))(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3): + storybook@8.1.11(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3): dependencies: - '@storybook/cli': 8.0.9(@babel/preset-env@7.23.5(@babel/core@7.24.0))(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) + '@storybook/cli': 8.1.11(@babel/preset-env@7.24.7(@babel/core@7.24.7))(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) transitivePeerDependencies: - '@babel/preset-env' - bufferutil @@ -23146,6 +24167,8 @@ snapshots: strip-final-newline@3.0.0: {} + strip-final-newline@4.0.0: {} + strip-indent@3.0.0: dependencies: min-indent: 1.0.1 @@ -23156,9 +24179,9 @@ snapshots: strip-json-comments@3.1.1: {} - strip-literal@1.3.0: + strip-literal@2.1.0: dependencies: - acorn: 8.11.3 + js-tokens: 9.0.0 strip-outer@2.0.0: {} @@ -23208,7 +24231,7 @@ snapshots: symbol-tree@3.2.4: {} - systeminformation@5.22.7: {} + systeminformation@5.22.11: {} tar-fs@2.1.1: dependencies: @@ -23259,24 +24282,23 @@ snapshots: dependencies: memoizerific: 1.11.3 - temp-dir@2.0.0: {} + temp-dir@3.0.0: {} temp@0.8.4: dependencies: rimraf: 2.6.3 - tempy@1.0.1: + tempy@3.1.0: dependencies: - del: 6.1.1 - is-stream: 2.0.1 - temp-dir: 2.0.0 - type-fest: 0.16.0 - unique-string: 2.0.0 + is-stream: 3.0.0 + temp-dir: 3.0.0 + type-fest: 2.19.0 + unique-string: 3.0.0 - terser@5.30.3: + terser@5.31.1: dependencies: '@jridgewell/source-map': 0.3.5 - acorn: 8.11.3 + acorn: 8.12.0 commander: 2.20.3 source-map-support: 0.5.21 @@ -23298,13 +24320,13 @@ snapshots: dependencies: any-promise: 1.3.0 - thread-stream@2.3.0: + thread-stream@3.1.0: dependencies: real-require: 0.2.0 - three@0.164.1: {} + three@0.165.0: {} - throttle-debounce@5.0.0: {} + throttle-debounce@5.0.2: {} throttleit@1.0.0: {} @@ -23317,8 +24339,6 @@ snapshots: through@2.3.8: {} - tiny-invariant@1.3.1: {} - tiny-invariant@1.3.3: {} tiny-lru@10.0.1: {} @@ -23327,7 +24347,7 @@ snapshots: tinycolor2@1.6.0: {} - tinypool@0.7.0: {} + tinypool@0.8.4: {} tinyspy@2.2.0: {} @@ -23343,8 +24363,6 @@ snapshots: dependencies: is-number: 7.0.0 - toad-cache@3.3.0: {} - toad-cache@3.7.0: {} tocbot@4.21.1: {} @@ -23367,7 +24385,7 @@ snapshots: psl: 1.9.0 punycode: 2.3.1 - tough-cookie@4.1.3: + tough-cookie@4.1.4: dependencies: psl: 1.9.0 punycode: 2.3.1 @@ -23394,9 +24412,9 @@ snapshots: dependencies: typescript: 5.3.3 - ts-api-utils@1.3.0(typescript@5.5.2): + ts-api-utils@1.3.0(typescript@5.5.3): dependencies: - typescript: 5.5.2 + typescript: 5.5.3 ts-case-convert@2.0.2: {} @@ -23404,7 +24422,7 @@ snapshots: ts-map@1.0.3: {} - tsc-alias@1.8.8: + tsc-alias@1.8.10: dependencies: chokidar: 3.5.3 commander: 9.5.0 @@ -23426,9 +24444,9 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 - tsd@0.30.7: + tsd@0.31.1: dependencies: - '@tsd/typescript': 5.3.3 + '@tsd/typescript': 5.4.5 eslint-formatter-pretty: 4.1.0 globby: 11.1.0 jest-diff: 29.7.0 @@ -23440,6 +24458,8 @@ snapshots: tslib@2.6.2: {} + tslib@2.6.3: {} + tsx@4.4.0: dependencies: esbuild: 0.18.20 @@ -23459,8 +24479,6 @@ snapshots: type-detect@4.0.8: {} - type-fest@0.16.0: {} - type-fest@0.18.1: {} type-fest@0.20.2: {} @@ -23471,8 +24489,12 @@ snapshots: type-fest@0.8.1: {} + type-fest@1.4.0: {} + type-fest@2.19.0: {} + type-fest@4.20.1: {} + type-fest@4.9.0: {} type-is@1.6.18: @@ -23509,7 +24531,7 @@ snapshots: typedarray@0.0.6: {} - typeorm@0.3.20(ioredis@5.4.1)(pg@8.11.5): + typeorm@0.3.20(ioredis@5.4.1)(pg@8.12.0): dependencies: '@sqltools/formatter': 1.2.5 app-root-path: 3.1.0 @@ -23517,7 +24539,7 @@ snapshots: chalk: 4.1.2 cli-highlight: 2.1.11 dayjs: 1.11.10 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) dotenv: 16.0.3 glob: 10.3.10 mkdirp: 2.1.6 @@ -23528,7 +24550,7 @@ snapshots: yargs: 17.7.2 optionalDependencies: ioredis: 5.4.1 - pg: 8.11.5 + pg: 8.12.0 transitivePeerDependencies: - supports-color @@ -23536,7 +24558,7 @@ snapshots: typescript@5.4.2: {} - typescript@5.5.2: {} + typescript@5.5.3: {} ufo@1.3.2: {} @@ -23577,6 +24599,8 @@ snapshots: unicode-property-aliases-ecmascript@2.1.0: {} + unicorn-magic@0.1.0: {} + unified@11.0.4: dependencies: '@types/unist': 3.0.2 @@ -23597,9 +24621,9 @@ snapshots: dependencies: imurmurhash: 0.1.4 - unique-string@2.0.0: + unique-string@3.0.0: dependencies: - crypto-random-string: 2.0.0 + crypto-random-string: 4.0.0 unist-util-is@6.0.0: dependencies: @@ -23632,7 +24656,7 @@ snapshots: unplugin@1.4.0: dependencies: - acorn: 8.11.3 + acorn: 8.12.0 chokidar: 3.5.3 webpack-sources: 3.2.3 webpack-virtual-modules: 0.5.0 @@ -23660,6 +24684,21 @@ snapshots: querystringify: 2.2.0 requires-port: 1.0.0 + use-callback-ref@1.3.2(@types/react@18.0.28)(react@18.3.1): + dependencies: + react: 18.3.1 + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.0.28 + + use-sidecar@1.1.2(@types/react@18.0.28)(react@18.3.1): + dependencies: + detect-node-es: 1.1.0 + react: 18.3.1 + tslib: 2.6.2 + optionalDependencies: + '@types/react': 18.0.28 + utf-8-validate@6.0.3: dependencies: node-gyp-build: 4.6.0 @@ -23677,20 +24716,22 @@ snapshots: utils-merge@1.0.1: {} + uuid@10.0.0: {} + uuid@3.4.0: {} uuid@8.3.2: {} uuid@9.0.1: {} - v-code-diff@1.11.0(vue@3.4.26(typescript@5.5.2)): + v-code-diff@1.12.0(vue@3.4.31(typescript@5.5.3)): dependencies: diff: 5.1.0 diff-match-patch: 1.0.5 highlight.js: 11.9.0 - vue: 3.4.26(typescript@5.5.2) - vue-demi: 0.14.7(vue@3.4.26(typescript@5.5.2)) - vue-i18n: 9.13.1(vue@3.4.26(typescript@5.5.2)) + vue: 3.4.31(typescript@5.5.3) + vue-demi: 0.14.7(vue@3.4.31(typescript@5.5.3)) + vue-i18n: 9.13.1(vue@3.4.31(typescript@5.5.3)) v8-to-istanbul@9.2.0: dependencies: @@ -23703,8 +24744,6 @@ snapshots: spdx-correct: 3.1.1 spdx-expression-parse: 3.0.1 - validator@13.9.0: {} - vary@1.1.2: {} verror@1.10.0: @@ -23724,14 +24763,13 @@ snapshots: unist-util-stringify-position: 4.0.0 vfile-message: 4.0.2 - vite-node@0.34.6(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3): + vite-node@1.6.0(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1): dependencies: cac: 6.7.14 - debug: 4.3.4(supports-color@8.1.1) - mlly: 1.5.0 + debug: 4.3.5(supports-color@8.1.1) pathe: 1.1.2 picocolors: 1.0.0 - vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - '@types/node' - less @@ -23744,53 +24782,50 @@ snapshots: vite-plugin-turbosnap@1.0.3: {} - vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3): + vite@5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1): dependencies: - esbuild: 0.20.2 + esbuild: 0.21.5 postcss: 8.4.38 - rollup: 4.17.2 + rollup: 4.18.0 optionalDependencies: - '@types/node': 20.12.7 + '@types/node': 20.14.9 fsevents: 2.3.3 - sass: 1.76.0 - terser: 5.30.3 + sass: 1.77.6 + terser: 5.31.1 - vitest-fetch-mock@0.2.2(encoding@0.1.13)(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)): + vitest-fetch-mock@0.2.2(encoding@0.1.13)(vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1)): dependencies: cross-fetch: 3.1.6(encoding@0.1.13) - vitest: 0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3) + vitest: 1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1) transitivePeerDependencies: - encoding - vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3): + vitest@1.6.0(@types/node@20.14.9)(happy-dom@10.0.3)(jsdom@24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.77.6)(terser@5.31.1): dependencies: - '@types/chai': 4.3.11 - '@types/chai-subset': 1.3.5 - '@types/node': 20.12.7 - '@vitest/expect': 0.34.6 - '@vitest/runner': 0.34.6 - '@vitest/snapshot': 0.34.6 - '@vitest/spy': 0.34.6 - '@vitest/utils': 0.34.6 - acorn: 8.11.3 + '@vitest/expect': 1.6.0 + '@vitest/runner': 1.6.0 + '@vitest/snapshot': 1.6.0 + '@vitest/spy': 1.6.0 + '@vitest/utils': 1.6.0 acorn-walk: 8.3.2 - cac: 6.7.14 chai: 4.3.10 - debug: 4.3.4(supports-color@8.1.1) - local-pkg: 0.4.3 - magic-string: 0.30.7 + debug: 4.3.4(supports-color@5.5.0) + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.10 pathe: 1.1.2 picocolors: 1.0.0 std-env: 3.7.0 - strip-literal: 1.3.0 + strip-literal: 2.1.0 tinybench: 2.6.0 - tinypool: 0.7.0 - vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) - vite-node: 0.34.6(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) + tinypool: 0.8.4 + vite: 5.3.2(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) + vite-node: 1.6.0(@types/node@20.14.9)(sass@1.77.6)(terser@5.31.1) why-is-node-running: 2.2.2 optionalDependencies: + '@types/node': 20.14.9 happy-dom: 10.0.3 - jsdom: 24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) + jsdom: 24.1.0(bufferutil@4.0.7)(utf-8-validate@6.0.3) transitivePeerDependencies: - less - lightningcss @@ -23823,98 +24858,100 @@ snapshots: dependencies: vscode-languageserver-protocol: 3.17.5 - vue-component-meta@2.0.16(typescript@5.5.2): + vscode-uri@3.0.8: {} + + vue-component-meta@2.0.16(typescript@5.5.3): dependencies: '@volar/typescript': 2.2.0 - '@vue/language-core': 2.0.16(typescript@5.5.2) + '@vue/language-core': 2.0.16(typescript@5.5.3) path-browserify: 1.0.1 vue-component-type-helpers: 2.0.16 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 vue-component-type-helpers@1.8.4: {} vue-component-type-helpers@2.0.16: {} - vue-component-type-helpers@2.0.21: {} + vue-component-type-helpers@2.0.24: {} - vue-demi@0.14.7(vue@3.4.26(typescript@5.5.2)): + vue-demi@0.14.7(vue@3.4.31(typescript@5.5.3)): dependencies: - vue: 3.4.26(typescript@5.5.2) + vue: 3.4.31(typescript@5.5.3) - vue-docgen-api@4.75.1(vue@3.4.26(typescript@5.5.2)): + vue-docgen-api@4.75.1(vue@3.4.31(typescript@5.5.3)): dependencies: - '@babel/parser': 7.24.0 - '@babel/types': 7.24.0 - '@vue/compiler-dom': 3.4.21 - '@vue/compiler-sfc': 3.4.26 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + '@vue/compiler-dom': 3.4.29 + '@vue/compiler-sfc': 3.4.31 ast-types: 0.16.1 hash-sum: 2.0.0 lru-cache: 8.0.4 - pug: 3.0.2 - recast: 0.23.4 + pug: 3.0.3 + recast: 0.23.6 ts-map: 1.0.3 - vue: 3.4.26(typescript@5.5.2) - vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.4.26(typescript@5.5.2)) + vue: 3.4.31(typescript@5.5.3) + vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.4.31(typescript@5.5.3)) - vue-eslint-parser@9.4.2(eslint@8.57.0): + vue-eslint-parser@9.4.3(eslint@9.6.0): dependencies: - debug: 4.3.4(supports-color@8.1.1) - eslint: 8.57.0 + debug: 4.3.4(supports-color@5.5.0) + eslint: 9.6.0 eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 esquery: 1.4.2 lodash: 4.17.21 - semver: 7.5.4 + semver: 7.6.0 transitivePeerDependencies: - supports-color - vue-i18n@9.13.1(vue@3.4.26(typescript@5.5.2)): + vue-i18n@9.13.1(vue@3.4.31(typescript@5.5.3)): dependencies: '@intlify/core-base': 9.13.1 '@intlify/shared': 9.13.1 '@vue/devtools-api': 6.6.1 - vue: 3.4.26(typescript@5.5.2) + vue: 3.4.31(typescript@5.5.3) - vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.4.26(typescript@5.5.2)): + vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.4.31(typescript@5.5.3)): dependencies: - vue: 3.4.26(typescript@5.5.2) + vue: 3.4.31(typescript@5.5.3) vue-template-compiler@2.7.14: dependencies: de-indent: 1.0.2 he: 1.2.0 - vue-tsc@2.0.16(typescript@5.5.2): + vue-tsc@2.0.24(typescript@5.5.3): dependencies: - '@volar/typescript': 2.2.0 - '@vue/language-core': 2.0.16(typescript@5.5.2) + '@volar/typescript': 2.4.0-alpha.11 + '@vue/language-core': 2.0.24(typescript@5.5.3) semver: 7.6.0 - typescript: 5.5.2 + typescript: 5.5.3 - vue@3.4.26(typescript@5.5.2): + vue@3.4.31(typescript@5.5.3): dependencies: - '@vue/compiler-dom': 3.4.26 - '@vue/compiler-sfc': 3.4.26 - '@vue/runtime-dom': 3.4.26 - '@vue/server-renderer': 3.4.26(vue@3.4.26(typescript@5.5.2)) - '@vue/shared': 3.4.26 + '@vue/compiler-dom': 3.4.31 + '@vue/compiler-sfc': 3.4.31 + '@vue/runtime-dom': 3.4.31 + '@vue/server-renderer': 3.4.31(vue@3.4.31(typescript@5.5.3)) + '@vue/shared': 3.4.31 optionalDependencies: - typescript: 5.5.2 + typescript: 5.5.3 - vuedraggable@4.1.0(vue@3.4.26(typescript@5.5.2)): + vuedraggable@4.1.0(vue@3.4.31(typescript@5.5.3)): dependencies: sortablejs: 1.14.0 - vue: 3.4.26(typescript@5.5.2) + vue: 3.4.31(typescript@5.5.3) w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 - wait-on@7.2.0(debug@4.3.4): + wait-on@7.2.0(debug@4.3.5): dependencies: - axios: 1.6.2(debug@4.3.4) + axios: 1.6.2(debug@4.3.5) joi: 17.11.0 lodash: 4.17.21 minimist: 1.2.8 @@ -24026,8 +25063,8 @@ snapshots: with@7.0.2: dependencies: - '@babel/parser': 7.23.9 - '@babel/types': 7.23.5 + '@babel/parser': 7.24.5 + '@babel/types': 7.24.0 assert-never: 1.2.1 babel-walk: 3.0.0-canary-5 @@ -24064,7 +25101,7 @@ snapshots: imurmurhash: 0.1.4 signal-exit: 3.0.7 - ws@8.17.0(bufferutil@4.0.7)(utf-8-validate@6.0.3): + ws@8.17.1(bufferutil@4.0.7)(utf-8-validate@6.0.3): optionalDependencies: bufferutil: 4.0.7 utf-8-validate: 6.0.3 @@ -24152,13 +25189,7 @@ snapshots: yocto-queue@1.0.0: {} - z-schema@5.0.5: - dependencies: - lodash.get: 4.4.2 - lodash.isequal: 4.5.0 - validator: 13.9.0 - optionalDependencies: - commander: 9.5.0 + yoctocolors@2.0.2: {} zip-stream@6.0.1: dependencies: diff --git a/scripts/changelog-checker/.eslintrc.cjs b/scripts/changelog-checker/.eslintrc.cjs deleted file mode 100644 index 6acf8b3e6e..0000000000 --- a/scripts/changelog-checker/.eslintrc.cjs +++ /dev/null @@ -1,9 +0,0 @@ -module.exports = { - parserOptions: { - tsconfigRootDir: __dirname, - project: ['./tsconfig.json'], - }, - extends: [ - '../../packages/shared/.eslintrc.js', - ], -}; diff --git a/scripts/changelog-checker/eslint.config.js b/scripts/changelog-checker/eslint.config.js new file mode 100644 index 0000000000..813e96981a --- /dev/null +++ b/scripts/changelog-checker/eslint.config.js @@ -0,0 +1,17 @@ +import tsParser from '@typescript-eslint/parser'; +import sharedConfig from '../../packages/shared/eslint.config.js'; + +export default [ + ...sharedConfig, + { + files: ['src/**/*.ts', 'src/**/*.tsx'], + languageOptions: { + parserOptions: { + parser: tsParser, + project: ['./tsconfig.json'], + sourceType: 'module', + tsconfigRootDir: import.meta.dirname, + }, + }, + }, +]; From eafae79869204e6de4a3fd4835eda3eb23b53974 Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:29:44 +0900 Subject: [PATCH 070/246] test(backend): goodbye, Lenna (#14111) --- .../src/models/json-schema/drive-file.ts | 2 +- .../api/endpoints/admin/drive/show-file.ts | 2 +- packages/backend/test/e2e/drive.ts | 6 +++--- packages/backend/test/e2e/endpoints.ts | 2 +- packages/backend/test/e2e/note.ts | 4 ++-- packages/backend/test/e2e/user-notes.ts | 4 ++-- packages/backend/test/resources/192.jpg | Bin 0 -> 5131 bytes packages/backend/test/resources/192.png | Bin 0 -> 26568 bytes packages/backend/test/resources/Lenna.jpg | Bin 25360 -> 0 bytes packages/backend/test/resources/Lenna.png | Bin 473831 -> 0 bytes packages/backend/test/unit/FileInfoService.ts | 10 +++++----- packages/backend/test/utils.ts | 2 +- packages/misskey-js/src/autogen/types.ts | 4 ++-- 13 files changed, 18 insertions(+), 18 deletions(-) create mode 100644 packages/backend/test/resources/192.jpg create mode 100644 packages/backend/test/resources/192.png delete mode 100644 packages/backend/test/resources/Lenna.jpg delete mode 100644 packages/backend/test/resources/Lenna.png diff --git a/packages/backend/src/models/json-schema/drive-file.ts b/packages/backend/src/models/json-schema/drive-file.ts index ca88cc0e39..5ee1561c50 100644 --- a/packages/backend/src/models/json-schema/drive-file.ts +++ b/packages/backend/src/models/json-schema/drive-file.ts @@ -20,7 +20,7 @@ export const packedDriveFileSchema = { name: { type: 'string', optional: false, nullable: false, - example: 'lenna.jpg', + example: '192.jpg', }, type: { type: 'string', diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts index 459d8880fa..a7136d8c8c 100644 --- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts +++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts @@ -61,7 +61,7 @@ export const meta = { name: { type: 'string', optional: false, nullable: false, - example: 'lenna.jpg', + example: '192.jpg', }, type: { type: 'string', diff --git a/packages/backend/test/e2e/drive.ts b/packages/backend/test/e2e/drive.ts index 828c5200ef..43a73163eb 100644 --- a/packages/backend/test/e2e/drive.ts +++ b/packages/backend/test/e2e/drive.ts @@ -23,7 +23,7 @@ describe('Drive', () => { const marker = Math.random().toString(); - const url = 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'; + const url = 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg'; const catcher = makeStreamCatcher( alice, @@ -41,14 +41,14 @@ describe('Drive', () => { const file = await catcher; assert.strictEqual(res.status, 204); - assert.strictEqual(file.name, 'Lenna.jpg'); + assert.strictEqual(file.name, '192.jpg'); assert.strictEqual(file.type, 'image/jpeg'); }); test('ローカルからアップロードできる', async () => { // APIレスポンスを直接使用するので utils.js uploadFile が通過することで成功とする - const res = await uploadFile(alice, { path: 'Lenna.jpg', name: 'テスト画像' }); + const res = await uploadFile(alice, { path: '192.jpg', name: 'テスト画像' }); assert.strictEqual(res.body?.name, 'テスト画像.jpg'); assert.strictEqual(res.body.type, 'image/jpeg'); diff --git a/packages/backend/test/e2e/endpoints.ts b/packages/backend/test/e2e/endpoints.ts index de5e8ba95e..d5583ea8bb 100644 --- a/packages/backend/test/e2e/endpoints.ts +++ b/packages/backend/test/e2e/endpoints.ts @@ -584,7 +584,7 @@ describe('Endpoints', () => { assert.strictEqual(res.status, 200); assert.strictEqual(typeof res.body === 'object' && !Array.isArray(res.body), true); - assert.strictEqual(res.body!.name, 'Lenna.jpg'); + assert.strictEqual(res.body!.name, '192.jpg'); }); test('ファイルに名前を付けられる', async () => { diff --git a/packages/backend/test/e2e/note.ts b/packages/backend/test/e2e/note.ts index bda31d9640..7ce9f47bc3 100644 --- a/packages/backend/test/e2e/note.ts +++ b/packages/backend/test/e2e/note.ts @@ -41,7 +41,7 @@ describe('Note', () => { }); test('ファイルを添付できる', async () => { - const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'); + const file = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg'); const res = await api('notes/create', { fileIds: [file.id], @@ -53,7 +53,7 @@ describe('Note', () => { }, 1000 * 10); test('他人のファイルで怒られる', async () => { - const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'); + const file = await uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg'); const res = await api('notes/create', { text: 'test', diff --git a/packages/backend/test/e2e/user-notes.ts b/packages/backend/test/e2e/user-notes.ts index 331e053935..cc07c5ae71 100644 --- a/packages/backend/test/e2e/user-notes.ts +++ b/packages/backend/test/e2e/user-notes.ts @@ -17,8 +17,8 @@ describe('users/notes', () => { beforeAll(async () => { alice = await signup({ username: 'alice' }); - const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.jpg'); - const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/Lenna.png'); + const jpg = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.jpg'); + const png = await uploadUrl(alice, 'https://raw.githubusercontent.com/misskey-dev/misskey/develop/packages/backend/test/resources/192.png'); jpgNote = await post(alice, { fileIds: [jpg.id], }); diff --git a/packages/backend/test/resources/192.jpg b/packages/backend/test/resources/192.jpg new file mode 100644 index 0000000000000000000000000000000000000000..76374628e0acf2e3b85152d55c11c9a763027810 GIT binary patch literal 5131 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 literal 0 HcmV?d00001 diff --git a/packages/backend/test/resources/192.png b/packages/backend/test/resources/192.png new file mode 100644 index 0000000000000000000000000000000000000000..15fd1e3731210ad53f3948c1551a5be1f5ab1396 GIT binary patch literal 26568 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

WU5-N=dey=F`@4DEshA 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 E0Hgq>F#rGn literal 0 HcmV?d00001 diff --git a/packages/backend/test/resources/Lenna.jpg b/packages/backend/test/resources/Lenna.jpg deleted file mode 100644 index 6b5b32281c1ffd5893d23392169cc368d72e0823..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25360 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 O>~nN4ZJfRS|4jhJY`72r diff --git a/packages/backend/test/resources/Lenna.png b/packages/backend/test/resources/Lenna.png deleted file mode 100644 index 59ef68aabd033341028ccd2b1f6c5871c02b9d7b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 473831 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

NKMno`K4L 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�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

Xn*pCyUKBCz@Y#ZMoE`>cP57} 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%0ADm`};Qj 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 { describe('IMAGE', () => { test('Generic JPEG', async () => { - const path = `${resources}/Lenna.jpg`; + const path = `${resources}/192.jpg`; const info = await fileInfoService.getFileInfo(path, { skipSensitiveDetection: true }) as any; delete info.warnings; delete info.blurhash; delete info.sensitive; delete info.porn; assert.deepStrictEqual(info, { - size: 25360, - md5: '091b3f259662aa31e2ffef4519951168', + size: 5131, + md5: '8c9ed0677dd2b8f9f7472c3af247e5e3', type: { mime: 'image/jpeg', ext: 'jpg', }, - width: 512, - height: 512, + width: 192, + height: 192, orientation: undefined, }); }); diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index aad4ab37c9..bf14d05eca 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -297,7 +297,7 @@ export const uploadFile = async (user?: UserToken, { path, name, blob }: UploadO body: misskey.entities.DriveFile | null }> => { const absPath = path == null - ? new URL('resources/Lenna.jpg', import.meta.url) + ? new URL('resources/192.jpg', import.meta.url) : isAbsolute(path.toString()) ? new URL(path) : new URL(path, new URL('resources/', import.meta.url)); diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 72aca4dee2..b59f8dcbe3 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -4299,7 +4299,7 @@ export type components = { id: string; /** Format: date-time */ createdAt: string; - /** @example lenna.jpg */ + /** @example 192.jpg */ name: string; /** @example image/jpeg */ type: string; @@ -6799,7 +6799,7 @@ export type operations = { * @example 15eca7fba0480996e2245f5185bf39f2 */ md5: string; - /** @example lenna.jpg */ + /** @example 192.jpg */ name: string; /** @example image/jpeg */ type: string; From de1fe7cc5a22fed6c677a6b35365c667eece8ab8 Mon Sep 17 00:00:00 2001 From: woxtu Date: Tue, 2 Jul 2024 14:47:07 +0900 Subject: [PATCH 071/246] Use built-in API (#14095) --- packages/backend/test/e2e/move.ts | 7 +- packages/backend/test/e2e/renote-mute.ts | 9 +- packages/backend/test/e2e/timelines.ts | 93 ++++++++++--------- packages/backend/test/unit/RoleService.ts | 8 +- .../backend/test/unit/SystemWebhookService.ts | 17 ++-- packages/backend/test/utils.ts | 8 -- 6 files changed, 69 insertions(+), 73 deletions(-) diff --git a/packages/backend/test/e2e/move.ts b/packages/backend/test/e2e/move.ts index 74cf61a785..35240cd3c8 100644 --- a/packages/backend/test/e2e/move.ts +++ b/packages/backend/test/e2e/move.ts @@ -7,12 +7,13 @@ import { INestApplicationContext } from '@nestjs/common'; process.env.NODE_ENV = 'test'; +import { setTimeout } from 'node:timers/promises'; import * as assert from 'assert'; import { loadConfig } from '@/config.js'; import { MiRepository, MiUser, UsersRepository, miRepository } from '@/models/_.js'; import { secureRndstr } from '@/misc/secure-rndstr.js'; import { jobQueue } from '@/boot/common.js'; -import { api, initTestDb, signup, sleep, successfulApiCall, uploadFile } from '../utils.js'; +import { api, initTestDb, signup, successfulApiCall, uploadFile } from '../utils.js'; import type * as misskey from 'misskey-js'; describe('Account Move', () => { @@ -271,7 +272,7 @@ describe('Account Move', () => { assert.strictEqual(move.status, 200); - await sleep(1000 * 3); // wait for jobs to finish + await setTimeout(1000 * 3); // wait for jobs to finish // Unfollow delayed? const aliceFollowings = await api('users/following', { @@ -330,7 +331,7 @@ describe('Account Move', () => { }); test('Unfollowed after 10 sec (24 hours in production).', async () => { - await sleep(1000 * 8); + await setTimeout(1000 * 8); const following = await api('users/following', { userId: alice.id, diff --git a/packages/backend/test/e2e/renote-mute.ts b/packages/backend/test/e2e/renote-mute.ts index 1abbb4f044..f6895c43d8 100644 --- a/packages/backend/test/e2e/renote-mute.ts +++ b/packages/backend/test/e2e/renote-mute.ts @@ -6,7 +6,8 @@ process.env.NODE_ENV = 'test'; import * as assert from 'assert'; -import { api, post, signup, sleep, waitFire } from '../utils.js'; +import { setTimeout } from 'node:timers/promises'; +import { api, post, signup, waitFire } from '../utils.js'; import type * as misskey from 'misskey-js'; describe('Renote Mute', () => { @@ -35,7 +36,7 @@ describe('Renote Mute', () => { const carolNote = await post(carol, { text: 'hi' }); // redisに追加されるのを待つ - await sleep(100); + await setTimeout(100); const res = await api('notes/local-timeline', {}, alice); @@ -52,7 +53,7 @@ describe('Renote Mute', () => { const carolNote = await post(carol, { text: 'hi' }); // redisに追加されるのを待つ - await sleep(100); + await setTimeout(100); const res = await api('notes/local-timeline', {}, alice); @@ -69,7 +70,7 @@ describe('Renote Mute', () => { const bobRenote = await post(bob, { renoteId: carolNote.id }); // redisに追加されるのを待つ - await sleep(100); + await setTimeout(100); const res = await api('notes/local-timeline', {}, alice); diff --git a/packages/backend/test/e2e/timelines.ts b/packages/backend/test/e2e/timelines.ts index f6cc2bac28..fccc052d99 100644 --- a/packages/backend/test/e2e/timelines.ts +++ b/packages/backend/test/e2e/timelines.ts @@ -7,16 +7,17 @@ // pnpm jest -- e2e/timelines.ts import * as assert from 'assert'; +import { setTimeout } from 'node:timers/promises'; import { Redis } from 'ioredis'; import { loadConfig } from '@/config.js'; -import { api, post, randomString, sendEnvUpdateRequest, signup, sleep, uploadUrl } from '../utils.js'; +import { api, post, randomString, sendEnvUpdateRequest, signup, uploadUrl } from '../utils.js'; function genHost() { return randomString() + '.example.com'; } function waitForPushToTl() { - return sleep(500); + return setTimeout(500); } let redisForTimelines: Redis; @@ -44,7 +45,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi' }); const carolNote = await post(carol, { text: 'hi' }); @@ -60,7 +61,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); const carolNote = await post(carol, { text: 'hi' }); @@ -77,7 +78,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -94,7 +95,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -111,7 +112,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] }); @@ -128,7 +129,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'followers' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -147,7 +148,7 @@ describe('Timelines', () => { await api('following/create', { userId: carol.id }, alice); await api('following/create', { userId: carol.id }, bob); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'followers' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -166,7 +167,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/create', { userId: carol.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id, visibility: 'specified', visibleUserIds: [carolNote.id] }); @@ -182,7 +183,7 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); @@ -198,7 +199,7 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); @@ -228,7 +229,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { renoteId: carolNote.id }); @@ -244,7 +245,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { renoteId: carolNote.id }); @@ -262,7 +263,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); @@ -280,7 +281,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] }); await waitForPushToTl(); @@ -295,7 +296,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); @@ -313,7 +314,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -359,7 +360,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const [bobFile, carolFile] = await Promise.all([ uploadUrl(bob, 'https://raw.githubusercontent.com/misskey-dev/assets/main/public/icon.png'), uploadUrl(carol, 'https://raw.githubusercontent.com/misskey-dev/assets/main/public/icon.png'), @@ -384,7 +385,7 @@ describe('Timelines', () => { const channel = await api('channels/create', { name: 'channel' }, bob).then(x => x.body); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', channelId: channel.id }); await waitForPushToTl(); @@ -411,7 +412,7 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [alice.id] }); await waitForPushToTl(); @@ -438,7 +439,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] }); await waitForPushToTl(); @@ -566,7 +567,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('following/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi', visibility: 'home' }); const bobNote = await post(bob, { text: 'hi' }); @@ -582,7 +583,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi' }); @@ -599,7 +600,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); @@ -617,7 +618,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); await api('following/update', { userId: bob.id, withReplies: true }, alice); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -633,7 +634,7 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); @@ -703,7 +704,7 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); await waitForPushToTl(); @@ -717,7 +718,7 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); @@ -820,7 +821,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi' }); await waitForPushToTl(); @@ -835,7 +836,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); await waitForPushToTl(); @@ -850,7 +851,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); await waitForPushToTl(); @@ -865,7 +866,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -881,7 +882,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); @@ -899,7 +900,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: false }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); @@ -916,7 +917,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: false }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -933,7 +934,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('users/lists/update-membership', { listId: list.id, userId: bob.id, withReplies: true }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', replyId: carolNote.id }); @@ -950,7 +951,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'home' }); await waitForPushToTl(); @@ -966,7 +967,7 @@ describe('Timelines', () => { await api('following/create', { userId: bob.id }, alice); const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); await waitForPushToTl(); @@ -982,7 +983,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: alice.id }, alice); - await sleep(1000); + await setTimeout(1000); const aliceNote = await post(alice, { text: 'hi', visibility: 'followers' }); await waitForPushToTl(); @@ -999,7 +1000,7 @@ describe('Timelines', () => { const channel = await api('channels/create', { name: 'channel' }, bob).then(x => x.body); const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', channelId: channel.id }); await waitForPushToTl(); @@ -1031,7 +1032,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [alice.id] }); await waitForPushToTl(); @@ -1048,7 +1049,7 @@ describe('Timelines', () => { const list = await api('users/lists/create', { name: 'list' }, alice).then(res => res.body); await api('users/lists/push', { listId: list.id, userId: bob.id }, alice); await api('users/lists/push', { listId: list.id, userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'specified', visibleUserIds: [carol.id] }); await waitForPushToTl(); @@ -1088,7 +1089,7 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('following/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote = await post(bob, { text: 'hi', visibility: 'followers' }); await waitForPushToTl(); @@ -1228,7 +1229,7 @@ describe('Timelines', () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); await api('mute/create', { userId: carol.id }, alice); - await sleep(1000); + await setTimeout(1000); const carolNote = await post(carol, { text: 'hi' }); const bobNote = await post(bob, { text: 'hi', renoteId: carolNote.id }); @@ -1243,7 +1244,7 @@ describe('Timelines', () => { const [alice, bob] = await Promise.all([signup(), signup()]); await api('mute/create', { userId: bob.id }, alice); - await sleep(1000); + await setTimeout(1000); const bobNote1 = await post(bob, { text: 'hi' }); const bobNote2 = await post(bob, { text: 'hi', replyId: bobNote1.id }); const bobNote3 = await post(bob, { text: 'hi', renoteId: bobNote1.id }); diff --git a/packages/backend/test/unit/RoleService.ts b/packages/backend/test/unit/RoleService.ts index 69fa4162fb..b6cbe4c520 100644 --- a/packages/backend/test/unit/RoleService.ts +++ b/packages/backend/test/unit/RoleService.ts @@ -5,6 +5,7 @@ process.env.NODE_ENV = 'test'; +import { setTimeout } from 'node:timers/promises'; import { jest } from '@jest/globals'; import { ModuleMocker } from 'jest-mock'; import { Test } from '@nestjs/testing'; @@ -29,7 +30,6 @@ import { secureRndstr } from '@/misc/secure-rndstr.js'; import { NotificationService } from '@/core/NotificationService.js'; import { RoleCondFormulaValue } from '@/models/Role.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; -import { sleep } from '../utils.js'; import type { TestingModule } from '@nestjs/testing'; import type { MockFunctionMetadata } from 'jest-mock'; @@ -278,7 +278,7 @@ describe('RoleService', () => { // ストリーミング経由で反映されるまでちょっと待つ clock.uninstall(); - await sleep(100); + await setTimeout(100); const resultAfter25hAgain = await roleService.getUserPolicies(user.id); expect(resultAfter25hAgain.canManageCustomEmojis).toBe(true); @@ -807,7 +807,7 @@ describe('RoleService', () => { await roleService.assign(user.id, role.id); clock.uninstall(); - await sleep(100); + await setTimeout(100); const assignments = await roleAssignmentsRepository.find({ where: { @@ -835,7 +835,7 @@ describe('RoleService', () => { await roleService.assign(user.id, role.id); clock.uninstall(); - await sleep(100); + await setTimeout(100); const assignments = await roleAssignmentsRepository.find({ where: { diff --git a/packages/backend/test/unit/SystemWebhookService.ts b/packages/backend/test/unit/SystemWebhookService.ts index 41b7f977ca..790cd1490e 100644 --- a/packages/backend/test/unit/SystemWebhookService.ts +++ b/packages/backend/test/unit/SystemWebhookService.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import { setTimeout } from 'node:timers/promises'; import { afterEach, beforeEach, describe, expect, jest } from '@jest/globals'; import { Test, TestingModule } from '@nestjs/testing'; import { MiUser } from '@/models/User.js'; @@ -16,7 +17,7 @@ import { DI } from '@/di-symbols.js'; import { QueueService } from '@/core/QueueService.js'; import { LoggerService } from '@/core/LoggerService.js'; import { SystemWebhookService } from '@/core/SystemWebhookService.js'; -import { randomString, sleep } from '../utils.js'; +import { randomString } from '../utils.js'; describe('SystemWebhookService', () => { let app: TestingModule; @@ -358,7 +359,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks).toEqual([webhook]); @@ -377,7 +378,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks).toEqual([]); @@ -407,7 +408,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks).toEqual([webhook2]); @@ -434,7 +435,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks.length).toEqual(0); @@ -457,7 +458,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks).toEqual([webhook2]); @@ -481,7 +482,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks.length).toEqual(0); @@ -504,7 +505,7 @@ describe('SystemWebhookService', () => { ); // redisでの配信経由で更新されるのでちょっと待つ - await sleep(500); + await setTimeout(500); const fetchedWebhooks = await service.fetchActiveSystemWebhooks(); expect(fetchedWebhooks.length).toEqual(0); diff --git a/packages/backend/test/utils.ts b/packages/backend/test/utils.ts index bf14d05eca..06c3f82601 100644 --- a/packages/backend/test/utils.ts +++ b/packages/backend/test/utils.ts @@ -605,14 +605,6 @@ export async function initTestDb(justBorrow = false, initEntities?: any[]) { return db; } -export function sleep(msec: number) { - return new Promise(res => { - setTimeout(() => { - res(); - }, msec); - }); -} - export async function sendEnvUpdateRequest(params: { key: string, value?: string }) { const res = await fetch( `http://localhost:${port + 1000}/env`, From 5d03efa1bb230bf1f22cf4a86a20157cd8aca7c4 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 3 Jul 2024 06:40:31 +0900 Subject: [PATCH 072/246] dev: fix pnpm dev is broken (#14123) * dev: pnpm dev is broken * dev: fix crash pnpm dev because of unhandled promise --- packages/backend/scripts/dev.mjs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/scripts/dev.mjs b/packages/backend/scripts/dev.mjs index 2d0de0f916..a3e0558abd 100644 --- a/packages/backend/scripts/dev.mjs +++ b/packages/backend/scripts/dev.mjs @@ -30,6 +30,7 @@ function execStart() { async function killProc() { if (backendProcess) { + backendProcess.catch(() => {}); // backendProcess.kill()によって発生する例外を無視するためにcatch()を呼び出す backendProcess.kill(); await new Promise(resolve => backendProcess.on('exit', resolve)); backendProcess = undefined; @@ -46,6 +47,7 @@ async function killProc() { ], { stdio: [process.stdin, process.stdout, process.stderr, 'ipc'], + serialization: "json", }) .on('message', async (message) => { if (message.type === 'exit') { From fab7d5e484d86dc8c24850dd98ebc1ee3688910e Mon Sep 17 00:00:00 2001 From: zyoshoka <107108195+zyoshoka@users.noreply.github.com> Date: Thu, 4 Jul 2024 12:33:43 +0900 Subject: [PATCH 073/246] fix(storybook): build skipping even after updating impl story files (#14124) --- packages/frontend/.storybook/changes.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/frontend/.storybook/changes.ts b/packages/frontend/.storybook/changes.ts index 7c70972e1e..bc7601441c 100644 --- a/packages/frontend/.storybook/changes.ts +++ b/packages/frontend/.storybook/changes.ts @@ -47,7 +47,6 @@ await fs.readFile( ) ) .map((path) => path.replace(/(?:(?<=\.stories)\.(?:impl|meta)|\.msw)(?=\.ts$)/g, '')) - .map((path) => (path.startsWith('.') ? path : `./${path}`)) ); if ( micromatch(Array.from(modules), [ From 6dd2e9fc0b1eeea6b5f04ccac93ccfab658f976d Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Thu, 4 Jul 2024 13:14:49 +0900 Subject: [PATCH 074/246] refactor(frontend): refactor popup api and make sure call dispose callback Close #14122 --- packages/frontend/src/account.ts | 16 ++- packages/frontend/src/boot/main-boot.ts | 30 +++-- .../frontend/src/components/MkClickerGame.vue | 4 +- .../src/components/MkDrive.folder.vue | 5 +- .../frontend/src/components/MkEmojiPicker.vue | 4 +- packages/frontend/src/components/MkLink.vue | 6 +- packages/frontend/src/components/MkNote.vue | 16 ++- .../src/components/MkNoteDetailed.vue | 16 ++- .../frontend/src/components/MkPostForm.vue | 13 +- .../src/components/MkPostFormAttaches.vue | 5 +- packages/frontend/src/components/MkRange.vue | 10 +- .../src/components/MkReactionIcon.vue | 6 +- .../components/MkReactionsViewer.reaction.vue | 14 +- packages/frontend/src/components/MkSignin.vue | 5 +- .../components/MkSystemWebhookEditor.impl.ts | 6 +- .../frontend/src/components/MkUrlPreview.vue | 8 +- .../src/components/MkUserSetupDialog.vue | 6 +- .../src/components/MkVisitorDashboard.vue | 12 +- .../src/components/global/MkCustomEmoji.vue | 4 +- .../frontend/src/components/global/MkUrl.vue | 6 +- packages/frontend/src/directives/ripple.ts | 4 +- packages/frontend/src/directives/tooltip.ts | 6 +- .../frontend/src/directives/user-preview.ts | 5 +- packages/frontend/src/os.ts | 125 ++++++++++-------- packages/frontend/src/pages/admin-user.vue | 12 +- .../abuse-report/notification-recipient.vue | 6 +- .../src/pages/custom-emojis-manager.vue | 10 +- .../frontend/src/pages/drive.file.info.vue | 5 +- .../src/pages/drop-and-fusion.game.vue | 14 +- packages/frontend/src/pages/emojis.emoji.vue | 8 +- .../frontend/src/pages/reset-password.vue | 4 +- packages/frontend/src/pages/settings/2fa.vue | 6 +- .../frontend/src/pages/settings/accounts.vue | 10 +- packages/frontend/src/pages/settings/api.vue | 5 +- .../src/pages/settings/avatar-decoration.vue | 5 +- .../src/scripts/get-drive-file-menu.ts | 5 +- .../frontend/src/scripts/get-note-menu.ts | 18 ++- .../frontend/src/scripts/get-user-menu.ts | 6 +- .../frontend/src/scripts/install-plugin.ts | 5 +- packages/frontend/src/scripts/please-login.ts | 5 +- .../frontend/src/scripts/use-chart-tooltip.ts | 10 +- packages/frontend/src/ui/_common_/common.ts | 4 +- .../src/ui/_common_/navbar-for-mobile.vue | 5 +- packages/frontend/src/ui/_common_/navbar.vue | 5 +- packages/frontend/src/ui/classic.header.vue | 5 +- packages/frontend/src/ui/classic.sidebar.vue | 6 +- .../src/ui/deck/notifications-column.vue | 5 +- packages/frontend/src/ui/visitor.vue | 12 +- .../src/widgets/WidgetNotifications.vue | 5 +- 49 files changed, 317 insertions(+), 196 deletions(-) diff --git a/packages/frontend/src/account.ts b/packages/frontend/src/account.ts index f99b550a83..4172016f89 100644 --- a/packages/frontend/src/account.ts +++ b/packages/frontend/src/account.ts @@ -184,10 +184,12 @@ export async function refreshAccount() { export async function login(token: Account['token'], redirect?: string) { const showing = ref(true); - popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkWaitingDialog.vue')), { success: false, showing: showing, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); if (_DEV_) console.log('logging as token ', token); const me = await fetchAccount(token, undefined, true) .catch(reason => { @@ -223,21 +225,23 @@ export async function openAccountMenu(opts: { if (!$i) return; function showSigninDialog() { - popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSigninDialog.vue')), {}, { done: res => { addAccount(res.id, res.i); success(); }, - }, 'closed'); + closed: () => dispose(), + }); } function createAccount() { - popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSignupDialog.vue')), {}, { done: res => { addAccount(res.id, res.i); switchAccountWithToken(res.i); }, - }, 'closed'); + closed: () => dispose(), + }); } async function switchAccount(account: Misskey.entities.UserDetailed) { diff --git a/packages/frontend/src/boot/main-boot.ts b/packages/frontend/src/boot/main-boot.ts index 5cb19f388a..faf230a1a2 100644 --- a/packages/frontend/src/boot/main-boot.ts +++ b/packages/frontend/src/boot/main-boot.ts @@ -35,7 +35,9 @@ export async function mainBoot() { emojiPicker.init(); if (isClientUpdated && $i) { - popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUpdated.vue')), {}, { + closed: () => dispose(), + }); } const stream = useStream(); @@ -96,7 +98,7 @@ export async function mainBoot() { }).render(); } } - } + } } catch (error) { // console.error(error); console.error('Failed to initialise the seasonal screen effect canvas context:', error); @@ -108,22 +110,28 @@ export async function mainBoot() { defaultStore.loaded.then(() => { if (defaultStore.state.accountSetupWizard !== -1) { - popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkUserSetupDialog.vue')), {}, { + closed: () => dispose(), + }); } }); for (const announcement of ($i.unreadAnnouncements ?? []).filter(x => x.display === 'dialog')) { - popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { announcement, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); } stream.on('announcementCreated', (ev) => { const announcement = ev.announcement; if (announcement.display === 'dialog') { - popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkAnnouncementDialog.vue')), { announcement, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); } }); @@ -247,13 +255,17 @@ export async function mainBoot() { const neverShowDonationInfo = miLocalStorage.getItem('neverShowDonationInfo'); if (neverShowDonationInfo !== 'true' && (createdAt.getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 3))) && !location.pathname.startsWith('/miauth')) { if (latestDonationInfoShownAt == null || (new Date(latestDonationInfoShownAt).getTime() < (Date.now() - (1000 * 60 * 60 * 24 * 30)))) { - popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkDonation.vue')), {}, { + closed: () => dispose(), + }); } } const modifiedVersionMustProminentlyOfferInAgplV3Section13Read = miLocalStorage.getItem('modifiedVersionMustProminentlyOfferInAgplV3Section13Read'); if (modifiedVersionMustProminentlyOfferInAgplV3Section13Read !== 'true' && instance.repositoryUrl !== 'https://github.com/misskey-dev/misskey') { - popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, {}, 'closed'); + const { dispose } = popup(defineAsyncComponent(() => import('@/components/MkSourceCodeAvailablePopup.vue')), {}, { + closed: () => dispose(), + }); } if ('Notification' in window) { diff --git a/packages/frontend/src/components/MkClickerGame.vue b/packages/frontend/src/components/MkClickerGame.vue index b592609e18..00506fb735 100644 --- a/packages/frontend/src/components/MkClickerGame.vue +++ b/packages/frontend/src/components/MkClickerGame.vue @@ -35,7 +35,9 @@ const prevCookies = ref(0); function onClick(ev: MouseEvent) { const x = ev.clientX; const y = ev.clientY; - os.popup(MkPlusOneEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkPlusOneEffect, { x, y }, { + end: () => dispose(), + }); saveData.value!.cookies++; saveData.value!.totalCookies++; diff --git a/packages/frontend/src/components/MkDrive.folder.vue b/packages/frontend/src/components/MkDrive.folder.vue index 8da0d78f35..1cc8b15b73 100644 --- a/packages/frontend/src/components/MkDrive.folder.vue +++ b/packages/frontend/src/components/MkDrive.folder.vue @@ -257,10 +257,11 @@ function onContextmenu(ev: MouseEvent) { text: i18n.ts.openInWindow, icon: 'ti ti-app-window', action: () => { - os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkDriveWindow.vue')), { initialFolder: props.folder, }, { - }, 'closed'); + closed: () => dispose(), + }); }, }, { type: 'divider' }, { text: i18n.ts.rename, diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 8a6bef54d8..4bd4bee1e5 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -402,7 +402,9 @@ function chosen(emoji: any, ev?: MouseEvent) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } const key = getKey(emoji); diff --git a/packages/frontend/src/components/MkLink.vue b/packages/frontend/src/components/MkLink.vue index 5d54a58e97..e842ec2d6e 100644 --- a/packages/frontend/src/components/MkLink.vue +++ b/packages/frontend/src/components/MkLink.vue @@ -37,11 +37,13 @@ const el = ref(); if (isEnabledUrlPreview.value) { useTooltip(el, (showing) => { - os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkUrlPreviewPopup.vue')), { showing, url: props.url, source: el.value instanceof HTMLElement ? el.value : el.value?.$el, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 22b1691a86..1313e4c58e 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -335,12 +335,14 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: renoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); if (appearNote.value.reactionAcceptance === 'likeOnly') { @@ -355,13 +357,15 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkReactionsViewerDetails, { + const { dispose } = os.popup(MkReactionsViewerDetails, { showing, reaction: '❤️', users, count: appearNote.value.reactionCount, targetElement: reactButton.value!, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } } @@ -409,7 +413,9 @@ function react(viaKeyboard = false): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index ed1c0a9e96..bc1f416373 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -346,12 +346,14 @@ useTooltip(renoteButton, async (showing) => { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: renoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); if (appearNote.value.reactionAcceptance === 'likeOnly') { @@ -366,13 +368,15 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') { if (users.length < 1) return; - os.popup(MkReactionsViewerDetails, { + const { dispose } = os.popup(MkReactionsViewerDetails, { showing, reaction: '❤️', users, count: appearNote.value.reactionCount, targetElement: reactButton.value!, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } @@ -413,7 +417,9 @@ function react(viaKeyboard = false): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index 1df9007681..0dc1aa0891 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -463,7 +463,7 @@ function setVisibility() { return; } - os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkVisibilityPicker.vue')), { currentVisibility: visibility.value, isSilenced: $i.isSilenced, localOnly: localOnly.value, @@ -476,7 +476,8 @@ function setVisibility() { defaultStore.set('visibility', visibility.value); } }, - }, 'closed'); + closed: () => dispose(), + }); } async function toggleLocalOnly() { @@ -624,8 +625,8 @@ async function onPaste(ev: ClipboardEvent) { return; } - const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, "0"); - const file = new File([paste], `${fileName}.txt`, { type: "text/plain" }); + const fileName = formatTimeString(new Date(), defaultStore.state.pastedFileName).replace(/{{number}}/g, '0'); + const file = new File([paste], `${fileName}.txt`, { type: 'text/plain' }); upload(file, `${fileName}.txt`); }); } @@ -731,7 +732,9 @@ async function post(ev?: MouseEvent) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } diff --git a/packages/frontend/src/components/MkPostFormAttaches.vue b/packages/frontend/src/components/MkPostFormAttaches.vue index 95eb367318..8854babb6b 100644 --- a/packages/frontend/src/components/MkPostFormAttaches.vue +++ b/packages/frontend/src/components/MkPostFormAttaches.vue @@ -108,7 +108,7 @@ async function rename(file) { async function describe(file) { if (mock) return; - os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkFileCaptionEditWindow.vue')), { default: file.comment !== null ? file.comment : '', file: file, }, { @@ -121,7 +121,8 @@ async function describe(file) { file.comment = comment; }); }, - }, 'closed'); + closed: () => dispose(), + }); } async function crop(file: Misskey.entities.DriveFile): Promise { diff --git a/packages/frontend/src/components/MkRange.vue b/packages/frontend/src/components/MkRange.vue index 15f8128e98..1eae642937 100644 --- a/packages/frontend/src/components/MkRange.vue +++ b/packages/frontend/src/components/MkRange.vue @@ -101,17 +101,19 @@ const steps = computed(() => { } }); -const onMousedown = (ev: MouseEvent | TouchEvent) => { +function onMousedown(ev: MouseEvent | TouchEvent) { ev.preventDefault(); const tooltipShowing = ref(true); - os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/MkTooltip.vue')), { showing: tooltipShowing, text: computed(() => { return props.textConverter(finalValue.value); }), targetElement: thumbEl, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); const style = document.createElement('style'); style.appendChild(document.createTextNode('* { cursor: grabbing !important; } body * { pointer-events: none !important; }')); @@ -152,7 +154,7 @@ const onMousedown = (ev: MouseEvent | TouchEvent) => { window.addEventListener('touchmove', onDrag); window.addEventListener('mouseup', onMouseup, { once: true }); window.addEventListener('touchend', onMouseup, { once: true }); -}; +} + + + + + + diff --git a/packages/backend/assets/redoc.html b/packages/backend/assets/redoc.html deleted file mode 100644 index 2557b4532e..0000000000 --- a/packages/backend/assets/redoc.html +++ /dev/null @@ -1,24 +0,0 @@ - - - - Misskey API - - - - - - - - - - - - - diff --git a/packages/backend/src/server/api/openapi/OpenApiServerService.ts b/packages/backend/src/server/api/openapi/OpenApiServerService.ts index 5210e4d2bc..f124aa9f39 100644 --- a/packages/backend/src/server/api/openapi/OpenApiServerService.ts +++ b/packages/backend/src/server/api/openapi/OpenApiServerService.ts @@ -25,7 +25,7 @@ export class OpenApiServerService { public createServer(fastify: FastifyInstance, _options: FastifyPluginOptions, done: (err?: Error) => void) { fastify.get('/api-doc', async (_request, reply) => { reply.header('Cache-Control', 'public, max-age=86400'); - return await reply.sendFile('/redoc.html', staticAssets); + return await reply.sendFile('/api-doc.html', staticAssets); }); fastify.get('/api.json', (_request, reply) => { reply.header('Cache-Control', 'public, max-age=600'); diff --git a/packages/backend/src/server/api/openapi/gen-spec.ts b/packages/backend/src/server/api/openapi/gen-spec.ts index 2a14270a24..efa47a6986 100644 --- a/packages/backend/src/server/api/openapi/gen-spec.ts +++ b/packages/backend/src/server/api/openapi/gen-spec.ts @@ -15,7 +15,6 @@ export function genOpenapiSpec(config: Config, includeSelfRef = false) { info: { version: config.version, title: 'Misskey API', - 'x-logo': { url: '/static-assets/api-doc.png' }, }, externalDocs: { From 02e0a86b12473265c2fc0f219349d2c662f89f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Wed, 10 Jul 2024 01:00:40 +0900 Subject: [PATCH 086/246] fix(frontend): remove unused statement fix #14162 --- packages/frontend/src/components/MkNote.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 5f1820a379..fc72813285 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -318,7 +318,7 @@ const keymap = { }, 'o': () => { if (renoteCollapsed.value) return; - galleryEl.value?.openGallery(); + showMenu(); }, 'v|enter': () => { if (renoteCollapsed.value) { From 52d8a54fc72b886fecb30a736b3ccf5057ea2a0c Mon Sep 17 00:00:00 2001 From: Kisaragi <48310258+KisaragiEffective@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:40:04 +0900 Subject: [PATCH 087/246] =?UTF-8?q?feat(misskey-js):=20`POST=20admin/roles?= =?UTF-8?q?/create`=E3=81=AE=E5=9E=8B=E3=82=92=E5=85=B7=E8=B1=A1=E5=8C=96?= =?UTF-8?q?=20(#14167)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(misskey-js): `POST admin/roles/create`の型を具象化 * fix * docs: CHANGELOG.md * test(misskey-js): admin/roles/createの型が合うことを表明 * test(misskey-js): single quote * test(misskey-js): 無を読もうとして爆発するのを修正 * test(misskey-js): fix comment --- CHANGELOG.md | 1 + packages/misskey-js/etc/misskey-js.api.md | 18 ++++++++++- packages/misskey-js/src/api.types.ts | 7 ++++- packages/misskey-js/src/entities.ts | 15 ++++++++- packages/misskey-js/test/api.ts | 38 +++++++++++++++++++++++ 5 files changed, 76 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b99a2cbc53..aec4e1868c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ ### Misskey.js - Feat: `/drive/files/create` のリクエストに対応(`multipart/form-data`に対応) +- Feat: `/admin/role/create` のロールポリシーの型を修正 ## 2024.5.0 diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index be2f510ac2..d11d2a4f06 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -1160,6 +1160,12 @@ export type Endpoints = Overwrite; + res: AdminRolesCreateResponse; + }; }>; // @public (undocumented) @@ -1185,6 +1191,7 @@ declare namespace entities { SignupPendingResponse, SigninRequest, SigninResponse, + PartialRolePolicyOverride, EmptyRequest, EmptyResponse, AdminMetaResponse, @@ -2725,6 +2732,15 @@ type PagesUpdateRequest = operations['pages___update']['requestBody']['content'] // @public (undocumented) function parse(acct: string): Acct; +// Warning: (ae-forgotten-export) The symbol "Values" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +type PartialRolePolicyOverride = Partial<{ + [k in keyof RolePolicies]: Omit, 'value'> & { + value: RolePolicies[k]; + }; +}>; + // @public (undocumented) export const permissions: readonly ["read:account", "write:account", "read:blocks", "write:blocks", "read:drive", "write:drive", "read:favorites", "write:favorites", "read:following", "write:following", "read:messaging", "write:messaging", "read:mutes", "write:mutes", "write:notes", "read:notifications", "write:notifications", "read:reactions", "write:reactions", "write:votes", "read:pages", "write:pages", "write:page-likes", "read:page-likes", "read:user-groups", "write:user-groups", "read:channels", "write:channels", "read:gallery", "write:gallery", "read:gallery-likes", "write:gallery-likes", "read:flash", "write:flash", "read:flash-likes", "write:flash-likes", "read:admin:abuse-user-reports", "write:admin:delete-account", "write:admin:delete-all-files-of-a-user", "read:admin:index-stats", "read:admin:table-stats", "read:admin:user-ips", "read:admin:meta", "write:admin:reset-password", "write:admin:resolve-abuse-user-report", "write:admin:send-email", "read:admin:server-info", "read:admin:show-moderation-log", "read:admin:show-user", "write:admin:suspend-user", "write:admin:unset-user-avatar", "write:admin:unset-user-banner", "write:admin:unsuspend-user", "write:admin:meta", "write:admin:user-note", "write:admin:roles", "read:admin:roles", "write:admin:relays", "read:admin:relays", "write:admin:invite-codes", "read:admin:invite-codes", "write:admin:announcements", "read:admin:announcements", "write:admin:avatar-decorations", "read:admin:avatar-decorations", "write:admin:federation", "write:admin:account", "read:admin:account", "write:admin:emoji", "read:admin:emoji", "write:admin:queue", "read:admin:queue", "write:admin:promo", "write:admin:drive", "read:admin:drive", "write:admin:ad", "read:admin:ad", "write:invite-codes", "read:invite-codes", "write:clip-favorite", "read:clip-favorite", "read:federation", "write:report-abuse"]; @@ -3213,7 +3229,7 @@ type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody'][' // Warnings were encountered during analysis: // -// src/entities.ts:25:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts +// src/entities.ts:34:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/packages/misskey-js/src/api.types.ts b/packages/misskey-js/src/api.types.ts index af0bade5b3..8c403639b7 100644 --- a/packages/misskey-js/src/api.types.ts +++ b/packages/misskey-js/src/api.types.ts @@ -1,7 +1,8 @@ import { Endpoints as Gen } from './autogen/endpoint.js'; import { UserDetailed } from './autogen/models.js'; -import { UsersShowRequest } from './autogen/entities.js'; +import { AdminRolesCreateRequest, AdminRolesCreateResponse, UsersShowRequest } from './autogen/entities.js'; import { + PartialRolePolicyOverride, SigninRequest, SigninResponse, SignupPendingRequest, @@ -79,5 +80,9 @@ export type Endpoints = Overwrite< req: SigninRequest; res: SigninResponse; }, + 'admin/roles/create': { + req: Overwrite; + res: AdminRolesCreateResponse; + } } > diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts index 7a84cb6a1a..7331a55a1c 100644 --- a/packages/misskey-js/src/entities.ts +++ b/packages/misskey-js/src/entities.ts @@ -1,5 +1,14 @@ import { ModerationLogPayloads } from './consts.js'; -import { Announcement, EmojiDetailed, MeDetailed, Page, User, UserDetailedNotMe } from './autogen/models.js'; +import { + Announcement, + EmojiDetailed, + MeDetailed, + Page, + Role, + RolePolicies, + User, + UserDetailedNotMe +} from './autogen/models.js'; export * from './autogen/entities.js'; export * from './autogen/models.js'; @@ -236,3 +245,7 @@ export type SigninResponse = { id: User['id'], i: string, }; + +type Values> = T[keyof T]; + +export type PartialRolePolicyOverride = Partial<{[k in keyof RolePolicies]: Omit, 'value'> & { value: RolePolicies[k] }}>; diff --git a/packages/misskey-js/test/api.ts b/packages/misskey-js/test/api.ts index 95f1946fa2..1a7574de25 100644 --- a/packages/misskey-js/test/api.ts +++ b/packages/misskey-js/test/api.ts @@ -259,4 +259,42 @@ describe('API', () => { expect(isAPIError(e)).toEqual(false); } }); + + test('admin/roles/create の型が合う', async() => { + fetchMock.resetMocks(); + fetchMock.mockResponse(async () => { + return { + // 本来返すべき値は`Role`型だが、テストなのでお茶を濁す + status: 200, + body: '{}' + }; + }); + + const cli = new APIClient({ + origin: 'https://misskey.test', + credential: 'TOKEN', + }); + await cli.request('admin/roles/create', { + name: 'aaa', + asBadge: false, + canEditMembersByModerator: false, + color: '#123456', + condFormula: {}, + description: '', + displayOrder: 0, + iconUrl: '', + isAdministrator: false, + isExplorable: false, + isModerator: false, + isPublic: false, + policies: { + ltlAvailable: { + value: true, + priority: 0, + useDefault: false, + }, + }, + target: 'manual', + }); + }) }); From 679318541afb789842db5f2cbf918b8acf284f1d Mon Sep 17 00:00:00 2001 From: woxtu Date: Thu, 11 Jul 2024 16:29:18 +0900 Subject: [PATCH 088/246] Improve background color specification (#14176) --- packages/frontend/src/pages/settings/drive-cleaner.vue | 6 +++--- packages/frontend/src/pages/settings/drive.vue | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/frontend/src/pages/settings/drive-cleaner.vue b/packages/frontend/src/pages/settings/drive-cleaner.vue index b20774c4ec..8d2946db63 100644 --- a/packages/frontend/src/pages/settings/drive-cleaner.vue +++ b/packages/frontend/src/pages/settings/drive-cleaner.vue @@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only + + diff --git a/packages/frontend/src/pages/welcome.timeline.vue b/packages/frontend/src/pages/welcome.timeline.vue index 139b2e0a07..db326f9e6c 100644 --- a/packages/frontend/src/pages/welcome.timeline.vue +++ b/packages/frontend/src/pages/welcome.timeline.vue @@ -4,24 +4,17 @@ SPDX-License-Identifier: AGPL-3.0-only --> @@ -29,43 +22,54 @@ SPDX-License-Identifier: AGPL-3.0-only From 121af778a0925d5850e9d88261e9a8e8c6fd968b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Thu, 11 Jul 2024 18:44:18 +0900 Subject: [PATCH 091/246] =?UTF-8?q?enhance(frontend):=20=E6=9C=AA=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E3=81=AE=E3=82=B5=E3=82=A6=E3=83=B3=E3=83=89=E8=A8=AD?= =?UTF-8?q?=E5=AE=9A=E3=82=92=E5=89=8A=E9=99=A4=20(#14116)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * enhance(frontend): 未使用のサウンド設定を削除 * Update Changelog * Update CHANGELOG.md --- CHANGELOG.md | 3 +++ locales/index.d.ts | 8 -------- locales/ja-JP.yml | 2 -- .../frontend/src/pages/settings/preferences-backups.vue | 2 -- packages/frontend/src/pages/settings/sounds.vue | 2 -- packages/frontend/src/scripts/sound.ts | 2 -- packages/frontend/src/store.ts | 8 -------- 7 files changed, 3 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 259420a6c6..cd123c938e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Unreleased +### Note +- デッキUIの新着ノートをサウンドで通知する機能の追加(v2024.5.0)に伴い、以前から動作しなくなっていたクライアント設定内の「アンテナ受信」「チャンネル通知」サウンドを削除しました。 + ### General - Feat: 通報を受けた際、または解決した際に、予め登録した宛先に通知を飛ばせるように(mail or webhook) #13705 - Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正 diff --git a/locales/index.d.ts b/locales/index.d.ts index ebd980ed85..5089f7802e 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -7515,14 +7515,6 @@ export interface Locale extends ILocale { * 通知 */ "notification": string; - /** - * アンテナ受信 - */ - "antenna": string; - /** - * チャンネル通知 - */ - "channel": string; /** * リアクション選択時 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 0d89d33abe..a03d792140 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1971,8 +1971,6 @@ _sfx: note: "ノート" noteMy: "ノート(自分)" notification: "通知" - antenna: "アンテナ受信" - channel: "チャンネル通知" reaction: "リアクション選択時" _soundSettings: diff --git a/packages/frontend/src/pages/settings/preferences-backups.vue b/packages/frontend/src/pages/settings/preferences-backups.vue index b6f1043154..dace2cd847 100644 --- a/packages/frontend/src/pages/settings/preferences-backups.vue +++ b/packages/frontend/src/pages/settings/preferences-backups.vue @@ -113,8 +113,6 @@ const defaultStoreSaveKeys: (keyof typeof defaultStore['state'])[] = [ 'sound_note', 'sound_noteMy', 'sound_notification', - 'sound_antenna', - 'sound_channel', ]; const coldDeviceStorageSaveKeys: (keyof typeof ColdDeviceStorage.default)[] = [ 'lightTheme', diff --git a/packages/frontend/src/pages/settings/sounds.vue b/packages/frontend/src/pages/settings/sounds.vue index 090f0cf14c..0f1b725fae 100644 --- a/packages/frontend/src/pages/settings/sounds.vue +++ b/packages/frontend/src/pages/settings/sounds.vue @@ -54,8 +54,6 @@ const sounds = ref>>({ note: defaultStore.reactiveState.sound_note, noteMy: defaultStore.reactiveState.sound_noteMy, notification: defaultStore.reactiveState.sound_notification, - antenna: defaultStore.reactiveState.sound_antenna, - channel: defaultStore.reactiveState.sound_channel, reaction: defaultStore.reactiveState.sound_reaction, }); diff --git a/packages/frontend/src/scripts/sound.ts b/packages/frontend/src/scripts/sound.ts index fcd59510df..bba855cd64 100644 --- a/packages/frontend/src/scripts/sound.ts +++ b/packages/frontend/src/scripts/sound.ts @@ -74,8 +74,6 @@ export const soundsTypes = [ export const operationTypes = [ 'noteMy', 'note', - 'antenna', - 'channel', 'notification', 'reaction', ] as const; diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts index e8eb5a1ed7..9cb2742069 100644 --- a/packages/frontend/src/store.ts +++ b/packages/frontend/src/store.ts @@ -479,14 +479,6 @@ export const defaultStore = markRaw(new Storage('base', { where: 'device', default: { type: 'syuilo/n-ea', volume: 1 } as SoundStore, }, - sound_antenna: { - where: 'device', - default: { type: 'syuilo/triple', volume: 1 } as SoundStore, - }, - sound_channel: { - where: 'device', - default: { type: 'syuilo/square-pico', volume: 1 } as SoundStore, - }, sound_reaction: { where: 'device', default: { type: 'syuilo/bubble2', volume: 1 } as SoundStore, From 385969e9f56a39a1e5547b94901d155e1e811263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Fri, 12 Jul 2024 16:25:44 +0900 Subject: [PATCH 092/246] =?UTF-8?q?fix(frontend):=20=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=BC=E3=82=AB=E3=82=B9=E3=81=AE=E6=8C=99=E5=8B=95=E3=82=92?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20(#14158)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(frontend): 直前のパターンを記録するように * fix(frontend): フォーカス/タブ移動に関する挙動を調整 (#226) Cherry-pick commit e8c030673326871edf3623cf2b8675d68f9e1b13 Co-authored-by: taiyme <53635909+taiyme@users.noreply.github.com> * focusのデザイン修正 * move scripts * Modalにfocus trapを追加 * 記録するホットキーはレートリミット式にする * escキーのハンドリングをMkModalに統一 * fix * enterで子メニューを開けるように * lint * fix focus trap * improve switch accessibility * 一部のmodalのフォーカストラップが外れない問題を修正 * fix * fix * Revert "記録するホットキーはレートリミット式にする" This reverts commit 40a7509286a87911ad4cc06d9482e8a2e5d0e7e8. * Revert "fix(frontend): 直前のパターンを記録するように" This reverts commit 5372b2594023952cff34aa62253ed4efef15b5dd. * Revert "Revert "fix(frontend): 直前のパターンを記録するように"" This reverts commit a9bb52e799e110927ad92cd8f26af980819334e1. * Revert "Revert "記録するホットキーはレートリミット式にする"" This reverts commit bdac34273e0bc5f13604c7e2f9fa6b1321a0df3d. * 試験的にCypressでのFocustrapを無効化 * fix * fix focus-trap * Update Changelog * :v: * fix focustrap invocation logic * スクロールがsticky headerを考慮するように * :art: * スタイルの微調整 * :art: * remove deprecated key aliases * focusElementが足りなかったので修正 * preview系にfocus時スタイルが足りなかったので修正 * `returnFocusElement` -> `returnFocusTo` * lint * Update packages/frontend/src/components/MkModalWindow.vue * Apply suggestions from code review Co-authored-by: taiy <53635909+taiyme@users.noreply.github.com> * keydownイベントをまとめる * use correct pesudo-element selector * fix * rename --------- Co-authored-by: taiyme <53635909+taiyme@users.noreply.github.com> Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com> --- CHANGELOG.md | 2 + .../src/components/MkAchievements.vue | 4 +- packages/frontend/src/components/MkButton.vue | 1 - .../src/components/MkChannelFollowButton.vue | 12 +- .../src/components/MkChannelPreview.vue | 19 +- .../frontend/src/components/MkClipPreview.vue | 8 + .../frontend/src/components/MkContextMenu.vue | 2 +- .../frontend/src/components/MkCwButton.vue | 4 +- packages/frontend/src/components/MkDialog.vue | 16 +- .../frontend/src/components/MkDrive.file.vue | 32 +- .../src/components/MkDrive.folder.vue | 2 +- .../frontend/src/components/MkEmojiPicker.vue | 33 +- .../src/components/MkEmojiPickerDialog.vue | 2 + .../src/components/MkFlashPreview.vue | 6 +- packages/frontend/src/components/MkFolder.vue | 16 +- .../src/components/MkFollowButton.vue | 12 +- .../src/components/MkGalleryPostPreview.vue | 4 +- .../src/components/MkImgWithBlurhash.vue | 4 +- .../frontend/src/components/MkLaunchPad.vue | 2 +- .../frontend/src/components/MkMediaAudio.vue | 26 +- .../frontend/src/components/MkMediaList.vue | 54 ++- .../frontend/src/components/MkMediaVideo.vue | 10 +- .../frontend/src/components/MkMenu.child.vue | 5 +- packages/frontend/src/components/MkMenu.vue | 367 +++++++++++------- packages/frontend/src/components/MkModal.vue | 28 +- .../frontend/src/components/MkModalWindow.vue | 13 +- packages/frontend/src/components/MkNote.vue | 48 +-- .../src/components/MkNoteDetailed.vue | 62 +-- .../frontend/src/components/MkNotePreview.vue | 2 +- .../src/components/MkNotification.vue | 2 +- .../frontend/src/components/MkPagePreview.vue | 19 +- .../frontend/src/components/MkPopupMenu.vue | 6 +- .../frontend/src/components/MkPostForm.vue | 10 + .../src/components/MkPostFormDialog.vue | 2 +- packages/frontend/src/components/MkRadio.vue | 10 +- packages/frontend/src/components/MkSelect.vue | 27 +- .../frontend/src/components/MkSuperMenu.vue | 10 +- packages/frontend/src/components/MkSwitch.vue | 10 +- .../components/MkTutorialDialog.PostNote.vue | 2 +- .../components/MkTutorialDialog.Sensitive.vue | 2 +- .../components/MkTutorialDialog.Timeline.vue | 2 +- .../src/components/MkVisibilityPicker.vue | 2 +- .../components/global/MkStickyContainer.vue | 6 +- packages/frontend/src/directives/hotkey.ts | 4 +- packages/frontend/src/os.ts | 27 +- .../frontend/src/pages/drive.file.info.vue | 1 + packages/frontend/src/pages/games.vue | 11 +- packages/frontend/src/pages/page.vue | 1 + .../frontend/src/pages/settings/profile.vue | 1 + .../frontend/src/pages/settings/theme.vue | 6 + packages/frontend/src/scripts/focus-trap.ts | 65 ++++ packages/frontend/src/scripts/focus.ts | 98 +++-- .../src/scripts/get-dom-node-or-null.ts | 19 + packages/frontend/src/scripts/hotkey.ts | 51 ++- packages/frontend/src/scripts/scroll.ts | 8 + packages/frontend/src/style.scss | 25 +- packages/frontend/src/ui/_common_/common.vue | 2 +- .../src/ui/_common_/navbar-for-mobile.vue | 6 +- packages/frontend/src/ui/_common_/navbar.vue | 86 +++- packages/frontend/src/ui/deck/column.vue | 4 +- .../frontend/src/widgets/WidgetCalendar.vue | 2 +- 61 files changed, 932 insertions(+), 391 deletions(-) create mode 100644 packages/frontend/src/scripts/focus-trap.ts create mode 100644 packages/frontend/src/scripts/get-dom-node-or-null.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index cd123c938e..c6f48684b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,8 @@ ### Client - Enhance: 内蔵APIドキュメントのデザイン・パフォーマンスを改善 - Enhance: 非ログイン時のハイライトTLのデザインを改善 +- Enhance: フロントエンドのアクセシビリティ改善 + (Based on https://github.com/taiyme/misskey/pull/226) - Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正 - Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968) - Fix: リバーシの対局を正しく共有できないことがある問題を修正 diff --git a/packages/frontend/src/components/MkAchievements.vue b/packages/frontend/src/components/MkAchievements.vue index 5d103fa789..c8134416b5 100644 --- a/packages/frontend/src/components/MkAchievements.vue +++ b/packages/frontend/src/components/MkAchievements.vue @@ -153,7 +153,7 @@ onMounted(() => { background: linear-gradient(0deg, #ffee20, #eb7018); } - &:before { + &::before { content: ""; display: block; position: absolute; @@ -173,7 +173,7 @@ onMounted(() => { background: linear-gradient(0deg, #e1e1e1, #7c7c7c); } - &:before { + &::before { content: ""; display: block; position: absolute; diff --git a/packages/frontend/src/components/MkButton.vue b/packages/frontend/src/components/MkButton.vue index 25b003ba5a..9560efb7d9 100644 --- a/packages/frontend/src/components/MkButton.vue +++ b/packages/frontend/src/components/MkButton.vue @@ -250,7 +250,6 @@ function onMousedown(evt: MouseEvent): void { } &:focus-visible { - outline: solid 2px var(--focus); outline-offset: 2px; } diff --git a/packages/frontend/src/components/MkChannelFollowButton.vue b/packages/frontend/src/components/MkChannelFollowButton.vue index 841d37a568..35dc3ad4bf 100644 --- a/packages/frontend/src/components/MkChannelFollowButton.vue +++ b/packages/frontend/src/components/MkChannelFollowButton.vue @@ -87,17 +87,7 @@ async function onClick() { } &:focus-visible { - &:after { - content: ""; - pointer-events: none; - position: absolute; - top: -5px; - right: -5px; - bottom: -5px; - left: -5px; - border: 2px solid var(--focus); - border-radius: 32px; - } + outline-offset: 2px; } &:hover { diff --git a/packages/frontend/src/components/MkChannelPreview.vue b/packages/frontend/src/components/MkChannelPreview.vue index 4ff64dc4ba..c30cb66c07 100644 --- a/packages/frontend/src/components/MkChannelPreview.vue +++ b/packages/frontend/src/components/MkChannelPreview.vue @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/components/MkDialog.vue b/packages/frontend/src/components/MkDialog.vue index 5c3c6aa51d..16cf5b1b75 100644 --- a/packages/frontend/src/components/MkDialog.vue +++ b/packages/frontend/src/components/MkDialog.vue @@ -36,7 +36,12 @@ SPDX-License-Identifier: AGPL-3.0-only

@@ -67,11 +72,16 @@ type Input = { maxLength?: number; }; +type SelectItem = { + value: any; + text: string; +}; + type Select = { - items: { - value: any; - text: string; - }[]; + items: (SelectItem | { + sectionTitle: string; + items: SelectItem[]; + })[]; default: string | null; }; diff --git a/packages/frontend/src/os.ts b/packages/frontend/src/os.ts index 3085f33e21..a8dd99c854 100644 --- a/packages/frontend/src/os.ts +++ b/packages/frontend/src/os.ts @@ -447,15 +447,20 @@ export function authenticateDialog(): Promise<{ }); } +type SelectItem = { + value: C; + text: string; +}; + // default が指定されていたら result は null になり得ないことを保証する overload function export function select(props: { title?: string; text?: string; default: string; - items: { - value: C; - text: string; - }[]; + items: (SelectItem | { + sectionTitle: string; + items: SelectItem[]; + } | undefined)[]; }): Promise<{ canceled: true; result: undefined; } | { @@ -465,10 +470,10 @@ export function select(props: { title?: string; text?: string; default?: string | null; - items: { - value: C; - text: string; - }[]; + items: (SelectItem | { + sectionTitle: string; + items: SelectItem[]; + } | undefined)[]; }): Promise<{ canceled: true; result: undefined; } | { @@ -478,10 +483,10 @@ export function select(props: { title?: string; text?: string; default?: string | null; - items: { - value: C; - text: string; - }[]; + items: (SelectItem | { + sectionTitle: string; + items: SelectItem[]; + } | undefined)[]; }): Promise<{ canceled: true; result: undefined; } | { @@ -492,7 +497,7 @@ export function select(props: { title: props.title, text: props.text, select: { - items: props.items, + items: props.items.filter(x => x !== undefined), default: props.default ?? null, }, }, { diff --git a/packages/frontend/src/pages/my-antennas/create.vue b/packages/frontend/src/pages/my-antennas/create.vue index 2d026d2fa9..2b8518747f 100644 --- a/packages/frontend/src/pages/my-antennas/create.vue +++ b/packages/frontend/src/pages/my-antennas/create.vue @@ -4,43 +4,33 @@ SPDX-License-Identifier: AGPL-3.0-only --> diff --git a/packages/frontend/src/pages/my-antennas/edit.vue b/packages/frontend/src/pages/my-antennas/edit.vue index 9471be8575..9f927cd1a0 100644 --- a/packages/frontend/src/pages/my-antennas/edit.vue +++ b/packages/frontend/src/pages/my-antennas/edit.vue @@ -4,15 +4,17 @@ SPDX-License-Identifier: AGPL-3.0-only --> diff --git a/packages/frontend/src/scripts/merge.ts b/packages/frontend/src/scripts/merge.ts index 4e39a0fa06..9794a300da 100644 --- a/packages/frontend/src/scripts/merge.ts +++ b/packages/frontend/src/scripts/merge.ts @@ -6,7 +6,7 @@ import { deepClone } from './clone.js'; import type { Cloneable } from './clone.js'; -type DeepPartial = { +export type DeepPartial = { [P in keyof T]?: T[P] extends Record ? DeepPartial : T[P]; }; diff --git a/packages/frontend/src/ui/deck.vue b/packages/frontend/src/ui/deck.vue index bdb62dca15..af46b0641d 100644 --- a/packages/frontend/src/ui/deck.vue +++ b/packages/frontend/src/ui/deck.vue @@ -24,7 +24,7 @@ SPDX-License-Identifier: AGPL-3.0-only :ref="id" :key="id" :class="$style.column" - :column="columns.find(c => c.id === id)" + :column="columns.find(c => c.id === id)!" :isStacked="ids.length > 1" @headerWheel="onWheel" /> @@ -95,7 +95,8 @@ SPDX-License-Identifier: AGPL-3.0-only import { computed, defineAsyncComponent, ref, watch, shallowRef } from 'vue'; import { v4 as uuid } from 'uuid'; import XCommon from './_common_/common.vue'; -import { deckStore, addColumn as addColumnToStore, loadDeck, getProfiles, deleteProfile as deleteProfile_ } from './deck/deck-store.js'; +import { deckStore, columnTypes, addColumn as addColumnToStore, loadDeck, getProfiles, deleteProfile as deleteProfile_ } from './deck/deck-store.js'; +import type { ColumnType } from './deck/deck-store.js'; import XSidebar from '@/ui/_common_/navbar.vue'; import XDrawerMenu from '@/ui/_common_/navbar-for-mobile.vue'; import MkButton from '@/components/MkButton.vue'; @@ -152,10 +153,12 @@ window.addEventListener('resize', () => { const snapScroll = deviceKind === 'smartphone' || deviceKind === 'tablet'; const drawerMenuShowing = ref(false); +/* const route = 'TODO'; watch(route, () => { drawerMenuShowing.value = false; }); +*/ const columns = deckStore.reactiveState.columns; const layout = deckStore.reactiveState.layout; @@ -174,32 +177,20 @@ function showSettings() { const columnsEl = shallowRef(); const addColumn = async (ev) => { - const columns = [ - 'main', - 'widgets', - 'notifications', - 'tl', - 'antenna', - 'list', - 'channel', - 'mentions', - 'direct', - 'roleTimeline', - ]; - const { canceled, result: column } = await os.select({ title: i18n.ts._deck.addColumn, - items: columns.map(column => ({ + items: columnTypes.map(column => ({ value: column, text: i18n.ts._deck._columns[column], })), }); - if (canceled) return; + if (canceled || column == null) return; addColumnToStore({ type: column, id: uuid(), name: i18n.ts._deck._columns[column], width: 330, + soundSetting: { type: null, volume: 1 }, }); }; @@ -211,7 +202,7 @@ const onContextmenu = (ev) => { }; function onWheel(ev: WheelEvent) { - if (ev.deltaX === 0) { + if (ev.deltaX === 0 && columnsEl.value != null) { columnsEl.value.scrollLeft += ev.deltaY; } } @@ -242,7 +233,7 @@ function changeProfile(ev: MouseEvent) { title: i18n.ts._deck.profile, minLength: 1, }); - if (canceled) return; + if (canceled || name == null) return; deckStore.set('profile', name); unisonReload(); diff --git a/packages/frontend/src/ui/deck/antenna-column.vue b/packages/frontend/src/ui/deck/antenna-column.vue index c3dc1e4fce..987bd4db55 100644 --- a/packages/frontend/src/ui/deck/antenna-column.vue +++ b/packages/frontend/src/ui/deck/antenna-column.vue @@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only --> + diff --git a/packages/frontend/src/pages/search.stories.impl.ts b/packages/frontend/src/pages/search.stories.impl.ts new file mode 100644 index 0000000000..0110a7ab8e --- /dev/null +++ b/packages/frontend/src/pages/search.stories.impl.ts @@ -0,0 +1,88 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { StoryObj } from '@storybook/vue3'; +import { HttpResponse, http } from 'msw'; +import search_ from './search.vue'; +import { userDetailed } from '@/../.storybook/fakes.js'; +import { commonHandlers } from '@/../.storybook/mocks.js'; + +const localUser = userDetailed('someuserid', 'miskist', null, 'Local Misskey User'); + +export const Default = { + render(args) { + return { + components: { + search_, + }, + setup() { + return { + args, + }; + }, + computed: { + props() { + return { + ...this.args, + }; + }, + }, + template: '', + }; + }, + args: { + ignoreNotesSearchAvailable: true, + }, + parameters: { + layout: 'fullscreen', + msw: { + handlers: [ + ...commonHandlers, + http.post('/api/users/show', () => { + return HttpResponse.json(userDetailed()); + }), + http.post('/api/users/search', () => { + return HttpResponse.json([userDetailed(), localUser]); + }), + ], + }, + }, +} satisfies StoryObj; + +export const NoteSearchDisabled = { + ...Default, + args: {}, +} satisfies StoryObj; + +export const WithUsernameLocal = { + ...Default, + + args: { + ...Default.args, + username: localUser.username, + host: localUser.host, + }, + parameters: { + layout: 'fullscreen', + msw: { + handlers: [ + ...commonHandlers, + http.post('/api/users/show', () => { + return HttpResponse.json(localUser); + }), + http.post('/api/users/search', () => { + return HttpResponse.json([userDetailed(), localUser]); + }), + ], + }, + }, +} satisfies StoryObj; + +export const WithUserType = { + ...Default, + args: { + type: 'user', + }, +} satisfies StoryObj; diff --git a/packages/frontend/src/pages/search.user.vue b/packages/frontend/src/pages/search.user.vue index b9c2704bc7..85d869d9cb 100644 --- a/packages/frontend/src/pages/search.user.vue +++ b/packages/frontend/src/pages/search.user.vue @@ -25,7 +25,9 @@ SPDX-License-Identifier: AGPL-3.0-only diff --git a/packages/frontend/src/pages/emoji-edit-dialog.vue b/packages/frontend/src/pages/emoji-edit-dialog.vue index d0a6bba47b..853c1d6b0b 100644 --- a/packages/frontend/src/pages/emoji-edit-dialog.vue +++ b/packages/frontend/src/pages/emoji-edit-dialog.vue @@ -15,8 +15,8 @@ SPDX-License-Identifier: AGPL-3.0-only -
- +
+
@@ -239,6 +239,7 @@ async function del() { .footer { position: sticky; + z-index: 10000; bottom: 0; left: 0; padding: 12px; From 3137c104f23ac966340a66f7452f3a903d134633 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Wed, 31 Jul 2024 07:23:38 +0900 Subject: [PATCH 205/246] =?UTF-8?q?test:=20=E3=83=95=E3=82=A9=E3=83=AD?= =?UTF-8?q?=E3=83=BC=E3=81=97=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=E3=83=A6?= =?UTF-8?q?=E3=83=BC=E3=82=B6=E3=83=BC=E3=81=8B=E3=82=89=E3=81=AE=E8=87=AA?= =?UTF-8?q?=E5=88=86=E3=81=B8=E3=81=AE=E8=BF=94=E4=BF=A1=E3=81=8C=E5=90=AB?= =?UTF-8?q?=E3=81=BE=E3=82=8C=E3=82=8B=E3=81=93=E3=81=A8=E3=82=92=E7=A2=BA?= =?UTF-8?q?=E8=AA=8D=E3=81=99=E3=82=8B=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=20(#14333)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/test/e2e/timelines.ts | 30 ++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/packages/backend/test/e2e/timelines.ts b/packages/backend/test/e2e/timelines.ts index b7069dd82c..d12be2a9ac 100644 --- a/packages/backend/test/e2e/timelines.ts +++ b/packages/backend/test/e2e/timelines.ts @@ -703,6 +703,21 @@ describe('Timelines', () => { assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); + test.concurrent('withReplies: false でフォローしていないユーザーからの自分への返信が含まれる', async () => { + const [alice, bob] = await Promise.all([signup(), signup()]); + + await setTimeout(1000); + const aliceNote = await post(alice, { text: 'hi' }); + const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); + + await waitForPushToTl(); + + const res = await api('notes/local-timeline', { limit: 100 }, alice); + + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + }); + test.concurrent('[withReplies: true] 他人の他人への返信が含まれる', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); @@ -899,6 +914,21 @@ describe('Timelines', () => { assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); }); + test.concurrent('withReplies: false でフォローしていないユーザーからの自分への返信が含まれる', async () => { + const [alice, bob] = await Promise.all([signup(), signup()]); + + await setTimeout(1000); + const aliceNote = await post(alice, { text: 'hi' }); + const bobNote = await post(bob, { text: 'hi', replyId: aliceNote.id }); + + await waitForPushToTl(); + + const res = await api('notes/local-timeline', { limit: 100 }, alice); + + assert.strictEqual(res.body.some(note => note.id === aliceNote.id), true); + assert.strictEqual(res.body.some(note => note.id === bobNote.id), true); + }); + test.concurrent('[withReplies: true] 他人の他人への返信が含まれる', async () => { const [alice, bob, carol] = await Promise.all([signup(), signup(), signup()]); From 9dacc20d67777185c729dd71899885db72874692 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 31 Jul 2024 07:23:58 +0900 Subject: [PATCH 206/246] New Crowdin updates (#14331) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (English) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (English) --- locales/en-US.yml | 10 ++++++++-- locales/zh-CN.yml | 10 ++++++++-- locales/zh-TW.yml | 6 ++++++ 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index cfb5783a95..451300d973 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -167,7 +167,7 @@ emojiUrl: "Emoji URL" addEmoji: "Add an emoji" settingGuide: "Recommended settings" cacheRemoteFiles: "Cache remote files" -cacheRemoteFilesDescription: "When this setting is disabled, remote files are loaded directly from the remote instance. Disabling this will decrease storage usage, but increase traffic, as thumbnails will not be generated." +cacheRemoteFilesDescription: "When this setting is disabled, remote files are loaded directly from the remote servers. Disabling this will decrease storage usage, but increase traffic, as thumbnails will not be generated." youCanCleanRemoteFilesCache: "You can clear the cache by clicking the 🗑️ button in the file management view." cacheRemoteSensitiveFiles: "Cache sensitive remote files" cacheRemoteSensitiveFilesDescription: "When this setting is disabled, sensitive remote files are loaded directly from the remote instance without caching." @@ -212,6 +212,7 @@ perDay: "Per Day" stopActivityDelivery: "Stop sending activities" blockThisInstance: "Block this instance" silenceThisInstance: "Silence this instance" +mediaSilenceThisInstance: "Media-silence this server" operations: "Operations" software: "Software" version: "Version" @@ -232,7 +233,9 @@ clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote blockedInstances: "Blocked Instances" blockedInstancesDescription: "List the hostnames of the instances you want to block separated by linebreaks. Listed instances will no longer be able to communicate with this instance." silencedInstances: "Silenced instances" -silencedInstancesDescription: "List the hostnames of the instances that you want to silence. All accounts of the listed instances will be treated as silenced, can only make follow requests, and cannot mention local accounts if not followed. This will not affect blocked instances." +silencedInstancesDescription: "List the host names of the servers that you want to silence, separated by a new line. All accounts belonging to the listed servers will be treated as silenced, and can only make follow requests, and cannot mention local accounts if not followed. This will not affect the blocked servers." +mediaSilencedInstances: "Media-silenced servers" +mediaSilencedInstancesDescription: "List the host names of the servers that you want to media-silence, separated by a new line. All accounts belonging to the listed servers will be treated as sensitive, and can't use custom emojis. This will not affect the blocked servers." muteAndBlock: "Mutes and Blocks" mutedUsers: "Muted users" blockedUsers: "Blocked users" @@ -1121,6 +1124,8 @@ preventAiLearning: "Reject usage in Machine Learning (Generative AI)" preventAiLearningDescription: "Requests crawlers to not use posted text or image material etc. in machine learning (Predictive / Generative AI) data sets. This is achieved by adding a \"noai\" HTML-Response flag to the respective content. A complete prevention can however not be achieved through this flag, as it may simply be ignored." options: "Options" specifyUser: "Specific user" +lookupConfirm: "Do you want to look up?" +openTagPageConfirm: "Do you want to open a hashtag page?" specifyHost: "Specify a host" failedToPreviewUrl: "Could not preview" update: "Update" @@ -1962,6 +1967,7 @@ _soundSettings: driveFileTypeWarnDescription: "Select an audio file" driveFileDurationWarn: "The audio is too long." driveFileDurationWarnDescription: "Long audio may disrupt using Misskey. Still continue?" + driveFileError: "It couldn't load the sound. Please change the setting." _ago: future: "Future" justNow: "Just now" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 8eae32ca32..0a868aab44 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -212,6 +212,7 @@ perDay: "每天" stopActivityDelivery: "停止发送活动" blockThisInstance: "阻止此服务器向本服务器推流" silenceThisInstance: "使服务器静音" +mediaSilenceThisInstance: "隐藏此服务器的媒体文件" operations: "操作" software: "软件" version: "版本" @@ -230,9 +231,11 @@ clearQueueConfirmText: "未送达的帖子将不会被投递。 通常无需执 clearCachedFiles: "清除缓存" clearCachedFilesConfirm: "确定要清除所有缓存的远程文件?" blockedInstances: "被封锁的服务器" -blockedInstancesDescription: "设定要封锁的服务器,以换行来进行分割。被封锁的服务器将无法与本服务器进行交换通讯。子域名也同样会被封锁。" +blockedInstancesDescription: "设定要封锁的服务器,以换行分隔。被封锁的服务器将无法与本服务器进行交换通讯。子域名也同样会被封锁。" silencedInstances: "被静音的服务器" -silencedInstancesDescription: "设置要静音的服务器,以换行符分隔。被静音的服务器内所有的账户将默认处于「静音」状态,仅能发送关注请求,并且在未关注状态下无法提及本地账户。被阻止的实例不受影响。" +silencedInstancesDescription: "设置要静音的服务器,以换行分隔。被静音的服务器内所有的账户将默认处于「静音」状态,仅能发送关注请求,并且在未关注状态下无法提及本地账户。被阻止的实例不受影响。" +mediaSilencedInstances: "已隐藏媒体文件的服务器" +mediaSilencedInstancesDescription: "设置要隐藏媒体文件的服务器,以换行分隔。被设置为隐藏媒体文件服务器内所有账号的文件均按照「敏感内容」处理,且将无法使用自定义表情符号。被阻止的实例不受影响。" muteAndBlock: "静音/拉黑" mutedUsers: "已静音用户" blockedUsers: "已拉黑的用户" @@ -1121,6 +1124,8 @@ preventAiLearning: "拒绝接受生成式 AI 的学习" preventAiLearningDescription: "要求文章生成 AI 或图像生成 AI 不能够以发布的帖子和图像等内容作为学习对象。这是通过在 HTML 响应中包含 noai 标志来实现的,这不能完全阻止 AI 学习你的发布内容,并不是所有 AI 都会遵守这类请求。" options: "选项" specifyUser: "用户指定" +lookupConfirm: "确定查询?" +openTagPageConfirm: "确定打开话题标签页面?" specifyHost: "指定主机名" failedToPreviewUrl: "无法预览" update: "更新" @@ -1961,6 +1966,7 @@ _soundSettings: driveFileTypeWarnDescription: "请选择音频文件" driveFileDurationWarn: "音频过长" driveFileDurationWarnDescription: "使用长音频可能会影响 Misskey 的使用。即使这样也要继续吗?" + driveFileError: "无法读取声音。请更改设置。" _ago: future: "未来" justNow: "最近" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 8b53273c3b..476ccd8799 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -212,6 +212,7 @@ perDay: "每日" stopActivityDelivery: "停止發送活動" blockThisInstance: "封鎖此伺服器" silenceThisInstance: "禁言此伺服器" +mediaSilenceThisInstance: "將這個伺服器的媒體設為禁言" operations: "操作" software: "軟體" version: "版本" @@ -233,6 +234,8 @@ blockedInstances: "已封鎖的伺服器" blockedInstancesDescription: "請逐行輸入需要封鎖的伺服器。已封鎖的伺服器將無法與本伺服器進行通訊。" silencedInstances: "被禁言的伺服器" silencedInstancesDescription: "設定要禁言的伺服器主機名稱,以換行分隔。隸屬於禁言伺服器的所有帳戶都將被視為「禁言帳戶」,只能發出「追隨請求」,而且無法提及未追隨的本地帳戶。這不會影響已封鎖的實例。" +mediaSilencedInstances: "媒體被禁言的伺服器" +mediaSilencedInstancesDescription: "設定您想要對媒體設定禁言的伺服器,以換行符號區隔。來自被媒體禁言的伺服器所屬帳戶的所有檔案都會被視為敏感檔案,且自訂表情符號不能使用。被封鎖的伺服器不受影響。" muteAndBlock: "靜音和封鎖" mutedUsers: "被靜音的使用者" blockedUsers: "被封鎖的使用者" @@ -1121,6 +1124,8 @@ preventAiLearning: "拒絕接受生成式AI的訓練" preventAiLearningDescription: "要求站外生成式 AI 不使用您發佈的內容訓練模型。此功能會使伺服器於 HTML 回應新增「noai」標籤,而因為要視乎 AI 會否遵守該標籤,所以此功能無法完全阻止所有 AI 使用您的內容。" options: "選項" specifyUser: "指定使用者" +lookupConfirm: "要查詢嗎?" +openTagPageConfirm: "要開啟標籤的頁面嗎?" specifyHost: "指定主機" failedToPreviewUrl: "無法預覽" update: "更新" @@ -1962,6 +1967,7 @@ _soundSettings: driveFileTypeWarnDescription: "請選擇音效檔案" driveFileDurationWarn: "音效太長了" driveFileDurationWarnDescription: "使用長音效檔可能會影響 Misskey 的使用體驗。仍要使用此檔案嗎?" + driveFileError: "無法載入語音。請更改設定" _ago: future: "未來" justNow: "剛剛" From d63b854f96d9437f9764f9170c3ed3537cc98a2c Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 31 Jul 2024 08:12:35 +0900 Subject: [PATCH 207/246] tweak localization --- locales/ja-JP.yml | 2 +- packages/frontend/src/components/MkSystemWebhookEditor.vue | 2 +- packages/frontend/src/pages/settings/webhook.edit.vue | 2 +- packages/frontend/src/pages/settings/webhook.new.vue | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 522ad7e22a..b493183974 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -2492,7 +2492,7 @@ _webhookSettings: modifyWebhook: "Webhookを編集" name: "名前" secret: "シークレット" - events: "Webhookを実行するタイミング" + trigger: "トリガー" active: "有効" _events: follow: "フォローしたとき" diff --git a/packages/frontend/src/components/MkSystemWebhookEditor.vue b/packages/frontend/src/components/MkSystemWebhookEditor.vue index cad2e99e4d..f5c7a3160b 100644 --- a/packages/frontend/src/components/MkSystemWebhookEditor.vue +++ b/packages/frontend/src/components/MkSystemWebhookEditor.vue @@ -33,7 +33,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
diff --git a/packages/frontend/src/pages/settings/webhook.edit.vue b/packages/frontend/src/pages/settings/webhook.edit.vue index e9fb1e471e..058ef69c35 100644 --- a/packages/frontend/src/pages/settings/webhook.edit.vue +++ b/packages/frontend/src/pages/settings/webhook.edit.vue @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
{{ i18n.ts._webhookSettings._events.follow }} diff --git a/packages/frontend/src/pages/settings/webhook.new.vue b/packages/frontend/src/pages/settings/webhook.new.vue index 5bf85e48f4..d62357caaf 100644 --- a/packages/frontend/src/pages/settings/webhook.new.vue +++ b/packages/frontend/src/pages/settings/webhook.new.vue @@ -19,7 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only - +
{{ i18n.ts._webhookSettings._events.follow }} From 4b04b2989b3c8957cee292326846b3e019b4a1c6 Mon Sep 17 00:00:00 2001 From: taichan <40626578+tai-cha@users.noreply.github.com> Date: Wed, 31 Jul 2024 17:22:51 +0900 Subject: [PATCH 208/246] chore(locale): update index.d.ts (#14339) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/misskey-dev/misskey/commit/d63b854f96d9437f9764f9170c3ed3537cc98a2c での更新漏れ --- locales/index.d.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index c58e4ace7b..91d36a14a6 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -9402,9 +9402,9 @@ export interface Locale extends ILocale { */ "secret": string; /** - * Webhookを実行するタイミング + * トリガー */ - "events": string; + "trigger": string; /** * 有効 */ From d6ba12e24c78611d80a005efef4340681949931b Mon Sep 17 00:00:00 2001 From: taichan <40626578+tai-cha@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:10:36 +0900 Subject: [PATCH 209/246] =?UTF-8?q?Fix(frontend):=20LTL=E7=84=A1=E5=8A=B9?= =?UTF-8?q?=E6=99=82=E3=81=AB=E3=83=98=E3=83=83=E3=83=80=E3=83=BC=E3=81=AB?= =?UTF-8?q?STL=E3=81=8C=E8=A1=A8=E7=A4=BA=E3=81=95=E3=82=8C=E3=81=A6?= =?UTF-8?q?=E3=81=97=E3=81=BE=E3=81=86=20&=20=E3=83=87=E3=83=95=E3=82=A9?= =?UTF-8?q?=E3=83=AB=E3=83=88=E3=80=81=E3=82=AF=E3=83=A9=E3=82=B7=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=81=A7=E3=83=AA=E3=82=B9=E3=83=88=E3=81=8C=E6=B6=88?= =?UTF-8?q?=E3=81=88=E3=81=A6=E3=81=84=E3=82=8B=20(#14337)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix condition of STL available * Fix: condition of stl * Listがタイムラインのヘッダーから消えている --- packages/frontend/src/pages/timeline.vue | 5 +++++ packages/frontend/src/timelines.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/frontend/src/pages/timeline.vue b/packages/frontend/src/pages/timeline.vue index c5905c7ada..32f6dd0e5a 100644 --- a/packages/frontend/src/pages/timeline.vue +++ b/packages/frontend/src/pages/timeline.vue @@ -287,6 +287,11 @@ const headerTabs = computed(() => [...(defaultStore.reactiveState.pinnedUserList icon: basicTimelineIconClass(tl), iconOnly: true, })), { + icon: 'ti ti-list', + title: i18n.ts.lists, + iconOnly: true, + onClick: chooseList, +}, { icon: 'ti ti-antenna', title: i18n.ts.antennas, iconOnly: true, diff --git a/packages/frontend/src/timelines.ts b/packages/frontend/src/timelines.ts index 3ef95fd272..94eda3545e 100644 --- a/packages/frontend/src/timelines.ts +++ b/packages/frontend/src/timelines.ts @@ -39,7 +39,7 @@ export function isAvailableBasicTimeline(timeline: BasicTimelineType | undefined case 'local': return ($i == null && instance.policies.ltlAvailable) || ($i != null && $i.policies.ltlAvailable); case 'social': - return $i != null && instance.policies.ltlAvailable; + return $i != null && $i.policies.ltlAvailable; case 'global': return ($i == null && instance.policies.gtlAvailable) || ($i != null && $i.policies.gtlAvailable); default: From 1a521a44c0c0e3f5a8156a2cf4b2f8001ff3d004 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Wed, 31 Jul 2024 18:13:20 +0900 Subject: [PATCH 210/246] New Crowdin updates (#14335) * New translations ja-jp.yml (Japanese, Kansai) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (English) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (Vietnamese) * New translations ja-jp.yml (Spanish) * New translations ja-jp.yml (Czech) * New translations ja-jp.yml (German) * New translations ja-jp.yml (Italian) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Polish) * New translations ja-jp.yml (Indonesian) * New translations ja-jp.yml (Thai) * New translations ja-jp.yml (English) * New translations ja-jp.yml (English) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (Chinese Traditional) --- locales/cs-CZ.yml | 1 - locales/de-DE.yml | 1 - locales/en-US.yml | 4 ++-- locales/es-ES.yml | 1 - locales/id-ID.yml | 1 - locales/it-IT.yml | 1 - locales/ja-KS.yml | 1 - locales/ko-KR.yml | 1 - locales/pl-PL.yml | 1 - locales/th-TH.yml | 22 ++++++++++++++++++++-- locales/vi-VN.yml | 1 - locales/zh-CN.yml | 2 +- locales/zh-TW.yml | 2 +- 13 files changed, 24 insertions(+), 15 deletions(-) diff --git a/locales/cs-CZ.yml b/locales/cs-CZ.yml index aa970f823a..7db7424762 100644 --- a/locales/cs-CZ.yml +++ b/locales/cs-CZ.yml @@ -2010,7 +2010,6 @@ _webhookSettings: createWebhook: "Vytvořit Webhook" name: "Jméno" secret: "Tajné" - events: "Události Webhook" active: "Zapnuto" _events: follow: "Při sledování uživatele" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index a319af56cb..8e44a3bbd4 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -2191,7 +2191,6 @@ _webhookSettings: createWebhook: "Webhook erstellen" name: "Name" secret: "Secret" - events: "Webhook-Ereignisse" active: "Aktiviert" _events: follow: "Wenn du jemandem folgst" diff --git a/locales/en-US.yml b/locales/en-US.yml index 451300d973..2cb76fa746 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -398,7 +398,7 @@ mcaptcha: "mCaptcha" enableMcaptcha: "Enable mCaptcha" mcaptchaSiteKey: "Site key" mcaptchaSecretKey: "Secret key" -mcaptchaInstanceUrl: "mCaptcha instance URL" +mcaptchaInstanceUrl: "mCaptcha server URL" recaptcha: "reCAPTCHA" enableRecaptcha: "Enable reCAPTCHA" recaptchaSiteKey: "Site key" @@ -2426,7 +2426,7 @@ _webhookSettings: modifyWebhook: "Modify Webhook" name: "Name" secret: "Secret" - events: "Webhook Events" + trigger: "Trigger" active: "Enabled" _events: follow: "When following a user" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 3ae3ba3b8a..ef066a37ed 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -2382,7 +2382,6 @@ _webhookSettings: createWebhook: "Crear Webhook" name: "Nombre" secret: "Secreto" - events: "Eventos de webhook" active: "Activado" _events: follow: "Cuando se sigue a alguien" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index de50569e89..24f7482fca 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -2403,7 +2403,6 @@ _webhookSettings: modifyWebhook: "Sunting Webhook" name: "Nama" secret: "Secret" - events: "Webhook Events" active: "Aktif" _events: follow: "Ketika mengikuti pengguna" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 64cd26878e..2b4b1e425e 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -2412,7 +2412,6 @@ _webhookSettings: modifyWebhook: "Modifica Webhook" name: "Nome" secret: "Segreto" - events: "Quando eseguire il Webhook" active: "Attivo" _events: follow: "Quando segui un profilo" diff --git a/locales/ja-KS.yml b/locales/ja-KS.yml index 774031f6f5..5969082cf2 100644 --- a/locales/ja-KS.yml +++ b/locales/ja-KS.yml @@ -2391,7 +2391,6 @@ _webhookSettings: createWebhook: "Webhookをつくる" name: "名前" secret: "シークレット" - events: "Webhookを投げるタイミング" active: "有効" _events: follow: "フォローしたとき~!" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 7fcb681c9a..34c1cc3ebf 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -2411,7 +2411,6 @@ _webhookSettings: modifyWebhook: "Webhook 수정" name: "이름" secret: "시크릿" - events: "Webhook을 실행할 타이밍" active: "활성화" _events: follow: "누군가를 팔로우했을 때" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index 7513d056b4..73eff0941a 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -1544,7 +1544,6 @@ _webhookSettings: createWebhook: "Stwórz Webhook" name: "Nazwa" secret: "Sekret" - events: "Uruchomienie Webhooka" active: "Właczono" _events: follow: "Po zaobserwowaniu użytkownika" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index eb7cdc2365..63f2793428 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -60,6 +60,7 @@ copyFileId: "คัดลอกไฟล์ ID" copyFolderId: "คัดลอกโฟลเดอร์ ID" copyProfileUrl: "คัดลอกโปรไฟล์ URL" searchUser: "ค้นหาผู้ใช้" +searchThisUsersNotes: "ค้นหาโน้ตของผู้ใช้" reply: "ตอบกลับ" loadMore: "แสดงเพิ่มเติม" showMore: "แสดงเพิ่มเติม" @@ -154,6 +155,7 @@ editList: "แก้ไขรายชื่อ" selectChannel: "เลือกช่อง" selectAntenna: "เลือกเสาอากาศ" editAntenna: "แก้ไขเสาอากาศ" +createAntenna: "สร้างเสาอากาศ" selectWidget: "เลือกวิดเจ็ต" editWidgets: "แก้ไขวิดเจ็ต" editWidgetsExit: "เรียบร้อย" @@ -194,6 +196,7 @@ followConfirm: "ต้องการติดตาม {name} ใช่ไห proxyAccount: "บัญชีพร็อกซี่" proxyAccountDescription: "บัญชีพร็อกซี คือ บัญชีที่ทำหน้าที่ติดตาม(ผู้ใช้)ระยะไกลภายใต้เงื่อนไขบางประการ ตัวอย่างเช่น เมื่อผู้ใช้ท้องถิ่นเพิ่มผู้ใช้ระยะไกลลงรายชื่อ หากไม่มีใครติดตามผู้ใช้ระยะไกลในรายชื่อนั้น กิจกรรมก็จะไม่ถูกส่งมายังเซิร์ฟเวอร์ ดังนั้นจึงมีบัญชีพร็อกซีไว้ติดตามผู้ใช้ระยะไกลเหล่านั้น" host: "โฮสต์" +selectSelf: "เลือกตัวเอง" selectUser: "เลือกผู้ใช้งาน" recipient: "ผู้รับ" annotation: "หมายเหตุประกอบ" @@ -209,6 +212,7 @@ perDay: "ต่อวัน" stopActivityDelivery: "หยุดส่งกิจกรรม" blockThisInstance: "บล็อกเซิร์ฟเวอร์นี้" silenceThisInstance: "ปิดปากเซิร์ฟเวอร์นี้" +mediaSilenceThisInstance: "ปิดปากสื่อของเซิร์ฟเวอร์นี้" operations: "ดำเนินการ" software: "ซอฟต์แวร์" version: "เวอร์ชั่น" @@ -230,6 +234,8 @@ blockedInstances: "เซิร์ฟเวอร์ที่ถูกบล็ blockedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการบล็อก คั่นด้วยการขึ้นบรรทัดใหม่ เซิร์ฟเวอร์ที่ถูกบล็อกจะไม่สามารถติดต่อกับอินสแตนซ์นี้ได้" silencedInstances: "ปิดปากเซิร์ฟเวอร์นี้แล้ว" silencedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการปิดปาก คั่นด้วยการขึ้นบรรทัดใหม่, บัญชีทั้งหมดของเซิร์ฟเวอร์ดังกล่าวจะถือว่าถูกปิดปากเช่นกัน ทำได้เฉพาะคำขอติดตามเท่านั้น และไม่สามารถกล่าวถึงบัญชีในเซิร์ฟเวอร์นี้ได้หากไม่ได้ถูกติดตามกลับ | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก" +mediaSilencedInstances: "เซิร์ฟเวอร์ที่ถูกปิดปากสื่อ" +mediaSilencedInstancesDescription: "ระบุโฮสต์ของเซิร์ฟเวอร์ที่ต้องการปิดปากสื่อ คั่นด้วยการขึ้นบรรทัดใหม่, ไฟล์ที่ถูกส่งจากบัญชีของเซิร์ฟเวอร์ดังกล่าวจะถือว่าถูกปิดปาก แล้วจะถูกติดเครื่องหมายว่ามีเนื้อหาละเอียดอ่อน และเอโมจิแบบกำหนดเองก็จะใช้ไม่ได้ด้วย | สิ่งนี้ไม่มีผลต่ออินสแตนซ์ที่ถูกบล็อก" muteAndBlock: "ปิดเสียงและบล็อก" mutedUsers: "ผู้ใช้ที่ถูกปิดเสียง" blockedUsers: "ผู้ใช้ที่ถูกบล็อก" @@ -1106,6 +1112,8 @@ preservedUsernames: "ชื่อผู้ใช้ที่สงวนไว preservedUsernamesDescription: "ระบุชื่อผู้ใช้ที่จะสงวนชื่อไว้ คั่นด้วยการขึ้นบรรทัดใหม่ ชื่อผู้ใช้ที่ระบุที่นี่จะไม่สามารถใช้งานได้อีกต่อไปเมื่อสร้างบัญชีใหม่ ยกเว้นเมื่อผู้ดูแลระบบสร้างบัญชี นอกจากนี้ บัญชีที่มีอยู่แล้วจะไม่ได้รับผลกระทบ" createNoteFromTheFile: "เรียบเรียงโน้ตจากไฟล์นี้" archive: "เก็บถาวร" +archived: "เก็บถาวรแล้ว" +unarchive: "เลิกการเก็บถาวร" channelArchiveConfirmTitle: "ต้องการเก็บถาวรเจ้า {name} ใช่ไหม?" channelArchiveConfirmDescription: "เมื่อเก็บถาวรแล้ว จะไม่ปรากฏในรายการช่องหรือผลการค้นหาอีกต่อไป และจะไม่สามารถโพสต์ใหม่ได้อีกต่อไป" thisChannelArchived: "ช่องนี้ถูกเก็บถาวรแล้วนะ" @@ -1116,6 +1124,9 @@ preventAiLearning: "ปฏิเสธการเรียนรู้ด้ว preventAiLearningDescription: "ส่งคำร้องขอไม่ให้ใช้ ข้อความในโน้ตที่โพสต์, หรือเนื้อหารูปภาพ ฯลฯ ในการเรียนรู้ของเครื่อง(machine learning) / Predictive AI / Generative AI โดยการเพิ่มแฟล็ก “noai” ลง HTML-Response ให้กับเนื้อหาที่เกี่ยวข้อง แต่ทั้งนี้ ไม่ได้ป้องกัน AI จากการเรียนรู้ได้อย่างสมบูรณ์ เนื่องจากมี AI บางตัวเท่านั้นที่จะเคารพคำขอดังกล่าว" options: "ตัวเลือกบทบาท" specifyUser: "ผู้ใช้เฉพาะ" +lookupConfirm: "ต้องการเรียกดูข้อมูลใช่ไหม?" +openTagPageConfirm: "ต้องการเปิดหน้าแฮชแท็กใช่ไหม?" +specifyHost: "ระบุโฮสต์" failedToPreviewUrl: "ไม่สามารถดูตัวอย่างได้" update: "อัปเดต" rolesThatCanBeUsedThisEmojiAsReaction: "บทบาทที่สามารถใช้เอโมจินี้เป็นรีแอคชั่นได้" @@ -1250,6 +1261,8 @@ inquiry: "ติดต่อเรา" tryAgain: "โปรดลองอีกครั้ง" confirmWhenRevealingSensitiveMedia: "ตรวจสอบก่อนแสดงสื่อที่มีเนื้อหาละเอียดอ่อน" sensitiveMediaRevealConfirm: "สื่อนี้มีเนื้อหาละเอียดอ่อน, ต้องการแสดงใช่ไหม?" +createdLists: "รายชื่อที่ถูกสร้าง" +createdAntennas: "เสาอากาศที่ถูกสร้าง" _delivery: status: "สถานะการจัดส่ง" stop: "ระงับการส่ง" @@ -1954,6 +1967,7 @@ _soundSettings: driveFileTypeWarnDescription: "กรุณาเลือกไฟล์เสียง" driveFileDurationWarn: "เสียงยาวเกินไป" driveFileDurationWarnDescription: "การใช้เสียงที่ยาว อาจรบกวนการใช้งาน Misskey, ต้องการดำเนินการต่อใช่ไหม?" + driveFileError: "ไม่สามารถโหลดไฟล์เสียงได้ กรุณาเปลี่ยนแปลงการตั้งค่า" _ago: future: "อนาคต" justNow: "เมื่อกี๊นี้" @@ -2412,7 +2426,6 @@ _webhookSettings: modifyWebhook: "แก้ไข Webhook" name: "ชื่อ" secret: "ความลับ" - events: "อีเว้นท์ Webhook" active: "เปิดใช้งาน" _events: follow: "เมื่อกำลังติดตามผู้ใช้" @@ -2536,7 +2549,7 @@ _externalResourceInstaller: description: "เกิดปัญหาระหว่างการติดตั้งธีม กรุณาลองอีกครั้ง. รายละเอียดข้อผิดพลาดสามารถดูได้ในคอนโซล Javascript" _dataSaver: _media: - title: "โหลดมีเดีย" + title: "โหลดสื่อ" description: "กันไม่ให้ภาพและวิดีโอโหลดโดยอัตโนมัติ แตะรูปภาพ/วิดีโอที่ซ่อนอยู่เพื่อโหลด" _avatar: title: "รูปไอคอน" @@ -2616,3 +2629,8 @@ _mediaControls: pip: "รูปภาพในรูปภาม" playbackRate: "ความเร็วในการเล่น" loop: "เล่นวนซ้ำ" +_contextMenu: + title: "เมนูเนื้อหา" + app: "แอปพลิเคชัน" + appWithShift: "แอปฟลิเคชันด้วยปุ่มยกแคร่ (Shift)" + native: "UI ของเบราว์เซอร์" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index 317dea5150..aadbf8b16f 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -1918,7 +1918,6 @@ _webhookSettings: createWebhook: "Tạo Webhook" name: "Tên" secret: "Mã bí mật" - events: "Sự kiện Webhook" active: "Đã bật" _events: reaction: "Khi nhận được sự kiện" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 0a868aab44..1deb0effc3 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -2425,7 +2425,7 @@ _webhookSettings: modifyWebhook: "编辑 webhook" name: "名称" secret: "密钥" - events: "何时运行 Webhook" + trigger: "触发器" active: "已启用" _events: follow: "关注时" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 476ccd8799..16dc464e35 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -2426,7 +2426,7 @@ _webhookSettings: modifyWebhook: "編輯 Webhook" name: "名字" secret: "密鑰" - events: "何時運行 Webhook" + trigger: "觸發器" active: "已啟用" _events: follow: "當你追隨時" From 59e2e43a68ee39d40f7a95a068cb9cb4f235cfed Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 31 Jul 2024 11:20:28 +0000 Subject: [PATCH 211/246] Release: 2024.7.0 --- package.json | 2 +- packages/misskey-js/package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 42751be196..4bf7b0a918 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2024.7.0-rc.8", + "version": "2024.7.0", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 45f42e1846..f0e8733e67 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2024.7.0-rc.8", + "version": "2024.7.0", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", From b6785804539e547b3b7f38be9e6f705738a7c832 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 12:31:35 +0100 Subject: [PATCH 212/246] copy changes from NoteCreateService to NoteEditService --- CONTRIBUTING.md | 7 ++--- packages/backend/src/core/NoteEditService.ts | 27 ++++++++++++-------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 645b6d0ba0..35b3651d52 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -581,9 +581,10 @@ seems to do a decent job) *after that commit*, do all the extra work, on the same branch: * copy all changes: - * from `NoteCreateService.create` to `NoteCreateService.import` (and - vice versa if `git` got confused!) - * from `NoteCreateService` to `NoteEditService` + * in `packages/backend/src/core/NoteCreateService.ts`, from `create` to + `import` (and vice versa if `git` got confused!) + * from `packages/backend/src/core/NoteCreateService.ts` to + `packages/backend/src/core/NoteEditService.vue` * from `ApNoteService.createNote` to `ApNoteService.updateNote` * from `endoints/notes/create.ts` to `endoints/notes/edit.ts` * from `MkNote*` to `SkNote*` (if sensible) diff --git a/packages/backend/src/core/NoteEditService.ts b/packages/backend/src/core/NoteEditService.ts index 0cb58d04a2..5ff0f26e2b 100644 --- a/packages/backend/src/core/NoteEditService.ts +++ b/packages/backend/src/core/NoteEditService.ts @@ -31,7 +31,7 @@ import InstanceChart from '@/core/chart/charts/instance.js'; import ActiveUsersChart from '@/core/chart/charts/active-users.js'; import { GlobalEventService } from '@/core/GlobalEventService.js'; import { NotificationService } from '@/core/NotificationService.js'; -import { WebhookService } from '@/core/WebhookService.js'; +import { UserWebhookService } from '@/core/UserWebhookService.js'; import { QueueService } from '@/core/QueueService.js'; import { NoteEntityService } from '@/core/entities/NoteEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js'; @@ -51,7 +51,6 @@ import { CacheService } from '@/core/CacheService.js'; import { isReply } from '@/misc/is-reply.js'; import { trackPromise } from '@/misc/promise-tracker.js'; import { isUserRelated } from '@/misc/is-user-related.js'; -import { isNotNull } from '@/misc/is-not-null.js'; import { IdentifiableError } from '@/misc/identifiable-error.js'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention' | 'edited'; @@ -203,7 +202,7 @@ export class NoteEditService implements OnApplicationShutdown { private notificationService: NotificationService, private relayService: RelayService, private federatedInstanceService: FederatedInstanceService, - private webhookService: WebhookService, + private webhookService: UserWebhookService, private remoteUserResolveService: RemoteUserResolveService, private apDeliverManagerService: ApDeliverManagerService, private apRendererService: ApRendererService, @@ -388,6 +387,9 @@ export class NoteEditService implements OnApplicationShutdown { mentionedUsers = data.apMentions ?? await this.extractMentionedUsers(user, combinedTokens); } + // if the host is media-silenced, custom emojis are not allowed + if (this.utilityService.isMediaSilencedHost(meta.mediaSilencedHosts, user.host)) emojis = []; + tags = tags.filter(tag => Array.from(tag ?? '').length <= 128).splice(0, 32); if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) { @@ -631,7 +633,7 @@ export class NoteEditService implements OnApplicationShutdown { this.webhookService.getActiveWebhooks().then(webhooks => { webhooks = webhooks.filter(x => x.userId === user.id && x.on.includes('note')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'note', { + this.queueService.userWebhookDeliver(webhook, 'note', { note: noteObj, }); } @@ -666,7 +668,7 @@ export class NoteEditService implements OnApplicationShutdown { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === data.reply!.userId && x.on.includes('edited')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'edited', { + this.queueService.userWebhookDeliver(webhook, 'edited', { note: noteObj, }); } @@ -801,7 +803,7 @@ export class NoteEditService implements OnApplicationShutdown { const webhooks = (await this.webhookService.getActiveWebhooks()).filter(x => x.userId === u.id && x.on.includes('edited')); for (const webhook of webhooks) { - this.queueService.webhookDeliver(webhook, 'edited', { + this.queueService.userWebhookDeliver(webhook, 'edited', { note: detailPackedNote, }); } @@ -838,7 +840,7 @@ export class NoteEditService implements OnApplicationShutdown { const mentions = extractMentions(tokens); let mentionedUsers = (await Promise.all(mentions.map(m => this.remoteUserResolveService.resolveUser(m.username, m.host ?? user.host).catch(() => null), - ))).filter(isNotNull) as MiUser[]; + ))).filter(x => x !== null) as MiUser[]; // Drop duplicate users mentionedUsers = mentionedUsers.filter((u, i, self) => @@ -933,10 +935,13 @@ export class NoteEditService implements OnApplicationShutdown { } } - if (note.visibility !== 'specified' || !note.visibleUserIds.some(v => v === user.id)) { // 自分自身のHTL - this.fanoutTimelineService.push(`homeTimeline:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax, r); - if (note.fileIds.length > 0) { - this.fanoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r); + // 自分自身のHTL + if (note.userHost == null) { + if (note.visibility !== 'specified' || !note.visibleUserIds.some(v => v === user.id)) { + this.fanoutTimelineService.push(`homeTimeline:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax, r); + if (note.fileIds.length > 0) { + this.fanoutTimelineService.push(`homeTimelineWithFiles:${user.id}`, note.id, meta.perUserHomeTimelineCacheMax / 2, r); + } } } From 703c6ae4929c7965803963286d7ad8d126c07a2a Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 12:35:49 +0100 Subject: [PATCH 213/246] better filenames in CONTRIBUTING.md --- CONTRIBUTING.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 35b3651d52..9e7d771104 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -585,12 +585,16 @@ seems to do a decent job) `import` (and vice versa if `git` got confused!) * from `packages/backend/src/core/NoteCreateService.ts` to `packages/backend/src/core/NoteEditService.vue` - * from `ApNoteService.createNote` to `ApNoteService.updateNote` - * from `endoints/notes/create.ts` to `endoints/notes/edit.ts` - * from `MkNote*` to `SkNote*` (if sensible) + * in `packages/backend/src/core/activitypub/models/ApNoteService.ts`, + from `createNote` to `updateNote` + * from `packages/backend/src/server/api/endpoints/notes/create.ts` + to `packages/backend/src/server/api/endpoints/notes/edit.ts` + * from `packages/frontend/src/components/MkNote*.vue` to + `packages/frontend/src/components/SkNote*.vue` (if sensible) * from the global timeline to the bubble timeline (`packages/backend/src/server/api/stream/channels/global-timeline.ts`, `packages/backend/src/server/api/stream/channels/bubble-timeline.ts`, + `packages/frontend/src/timelines.ts`, `packages/frontend/src/components/MkTimeline.vue`, `packages/frontend/src/pages/timeline.vue`, `packages/frontend/src/ui/deck/tl-column.vue`, From 3434092a10a6f3488368011efd0cbeac3bd716d8 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 12:45:57 +0100 Subject: [PATCH 214/246] copy from MkNote to SkNote --- packages/frontend/src/components/SkNote.vue | 138 +++++++++++++------- 1 file changed, 91 insertions(+), 47 deletions(-) diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue index 98f250c8b3..ff47170f5d 100644 --- a/packages/frontend/src/components/SkNote.vue +++ b/packages/frontend/src/components/SkNote.vue @@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only ref="rootEl" v-hotkey="keymap" :class="[$style.root, { [$style.showActionsOnlyHover]: defaultStore.state.showNoteActionsOnlyHover }]" - :tabindex="!isDeleted ? '-1' : undefined" + :tabindex="isDeleted ? '-1' : '0'" >
@@ -36,7 +36,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- @@ -94,7 +94,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._animatedMFM.stop }}
- +
@@ -127,7 +127,7 @@ SPDX-License-Identifier: AGPL-3.0-only class="_button" :style="renoted ? 'color: var(--accent) !important;' : ''" @click.stop - @mousedown="renoted ? undoRenote(appearNote) : boostVisibility()" + @mousedown.prevent="renoted ? undoRenote(appearNote) : boostVisibility()" >

{{ number(appearNote.renoteCount) }}

@@ -155,10 +155,10 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ number(appearNote.reactionCount) }}

- - @@ -204,8 +204,7 @@ import MkPoll from '@/components/MkPoll.vue'; import MkUsersTooltip from '@/components/MkUsersTooltip.vue'; import MkUrlPreview from '@/components/MkUrlPreview.vue'; import MkButton from '@/components/MkButton.vue'; -import { pleaseLogin } from '@/scripts/please-login.js'; -import { focusPrev, focusNext } from '@/scripts/focus.js'; +import { pleaseLogin, type OpenOnRemoteOptions } from '@/scripts/please-login.js'; import { checkWordMute } from '@/scripts/check-word-mute.js'; import { userPage } from '@/filters/user.js'; import number from '@/filters/number.js'; @@ -231,7 +230,10 @@ import { showMovedDialog } from '@/scripts/show-moved-dialog.js'; import { shouldCollapsed } from '@/scripts/collapsed.js'; import { useRouter } from '@/router/supplier.js'; import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js'; +import { host } from '@/config.js'; import { isEnabledUrlPreview } from '@/instance.js'; +import { type Keymap } from '@/scripts/hotkey.js'; +import { focusPrev, focusNext } from '@/scripts/focus.js'; const props = withDefaults(defineProps<{ note: Misskey.entities.Note; @@ -302,7 +304,7 @@ const quoteButton = shallowRef(); const clipButton = shallowRef(); const likeButton = shallowRef(); const appearNote = computed(() => isRenote ? note.value.renote as Misskey.entities.Note : note.value); - +const galleryEl = shallowRef>(); const isMyRenote = $i && ($i.id === note.value.userId); const showContent = ref(defaultStore.state.uncollapseCW); const parsed = computed(() => appearNote.value.text ? mfm.parse(appearNote.value.text) : null); @@ -328,6 +330,11 @@ const defaultLike = computed(() => defaultStore.state.like ? defaultStore.state. const animated = computed(() => parsed.value ? checkAnimationFromMfm(parsed.value) : null); const allowAnim = ref(defaultStore.state.advancedMfm && defaultStore.state.animatedMfm ? true : false); +const pleaseLoginContext = computed(() => ({ + type: 'lookup', + url: `https://${host}/notes/${appearNote.value.id}`, +})); + /* Overload FunctionにLintが対応していないのでコメントアウト function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array | undefined | null, checkOnly: true): boolean; function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array | undefined | null, checkOnly: false): boolean | 'sensitiveMute'; @@ -348,15 +355,53 @@ function checkMute(noteToCheck: Misskey.entities.Note, mutedWords: Array reply(true), - 'e|a|plus': () => react(true), - '(q)': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); }, - 'up|k|shift+tab': focusBefore, - 'down|j|tab': focusAfter, - 'esc': blur, - 'm|o': () => showMenu(true), - 's': () => showContent.value !== showContent.value, -}; + 'r': () => { + if (renoteCollapsed.value) return; + reply(); + }, + 'e|a|plus': () => { + if (renoteCollapsed.value) return; + react(); + }, + 'q': () => { + if (renoteCollapsed.value) return; + if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); + }, + 'm': () => { + if (renoteCollapsed.value) return; + showMenu(); + }, + 'c': () => { + if (renoteCollapsed.value) return; + if (!defaultStore.state.showClipButtonInNoteFooter) return; + clip(); + }, + 'o': () => { + if (renoteCollapsed.value) return; + galleryEl.value?.openGallery(); + }, + 'v|enter': () => { + if (renoteCollapsed.value) { + renoteCollapsed.value = false; + } else if (appearNote.value.cw != null) { + showContent.value = !showContent.value; + } else if (isLong) { + collapsed.value = !collapsed.value; + } + }, + 'esc': { + allowRepeat: true, + callback: () => blur(), + }, + 'up|k|shift+tab': { + allowRepeat: true, + callback: () => focusBefore(), + }, + 'down|j|tab': { + allowRepeat: true, + callback: () => focusAfter(), + }, +} as const satisfies Keymap; provide('react', (reaction: string) => { misskeyApi('notes/reactions/create', { @@ -389,12 +434,14 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: renoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); useTooltip(quoteButton, async (showing) => { @@ -438,13 +485,15 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkReactionsViewerDetails, { + const { dispose } = os.popup(MkReactionsViewerDetails, { showing, reaction: '❤️', users, count: appearNote.value.reactionCount, targetElement: reactButton.value!, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } } @@ -460,7 +509,7 @@ function boostVisibility() { } function renote(visibility: Visibility, localOnly: boolean = false) { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); renoting = true; @@ -506,7 +555,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { } function quote() { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (props.mock) { return; @@ -560,22 +609,21 @@ function quote() { } } -function reply(viaKeyboard = false): void { - pleaseLogin(); +function reply(): void { + pleaseLogin(undefined, pleaseLoginContext.value); if (props.mock) { return; } os.post({ reply: appearNote.value, channel: appearNote.value.channel, - animation: !viaKeyboard, }).then(() => { focus(); }); } function like(): void { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); sound.playMisskeySfx('reaction'); if (props.mock) { @@ -595,7 +643,7 @@ function like(): void { } function react(viaKeyboard = false): void { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (appearNote.value.reactionAcceptance === 'likeOnly') { sound.playMisskeySfx('reaction'); @@ -613,7 +661,9 @@ function react(viaKeyboard = false): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); @@ -706,15 +756,13 @@ function onContextmenu(ev: MouseEvent): void { } } -function showMenu(viaKeyboard = false): void { +function showMenu(): void { if (props.mock) { return; } const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted, currentClip: currentClip?.value }); - os.popupMenu(menu, menuButton.value, { - viaKeyboard, - }).then(focus).finally(cleanup); + os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup); } async function menuVersions(viaKeyboard = false): Promise { @@ -724,7 +772,7 @@ async function menuVersions(viaKeyboard = false): Promise { }).then(focus).finally(cleanup); } -async function clip() { +async function clip(): Promise { if (props.mock) { return; } @@ -732,7 +780,7 @@ async function clip() { os.popupMenu(await getNoteClipMenu({ note: note.value, isDeleted, currentClip: currentClip?.value }), clipButton.value).then(focus); } -function showRenoteMenu(viaKeyboard = false): void { +function showRenoteMenu(): void { if (props.mock) { return; } @@ -752,23 +800,19 @@ function showRenoteMenu(viaKeyboard = false): void { } if (isMyRenote) { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); os.popupMenu([ getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote), { type: 'divider' }, getUnrenote(), - ], renoteTime.value, { - viaKeyboard: viaKeyboard, - }); + ], renoteTime.value); } else { os.popupMenu([ getCopyNoteLinkMenu(note.value, i18n.ts.copyLinkRenote), { type: 'divider' }, getAbuseNoteMenu(note.value, i18n.ts.reportAbuseRenote), ($i?.isModerator || $i?.isAdmin) ? getUnrenote() : undefined, - ], renoteTime.value, { - viaKeyboard: viaKeyboard, - }); + ], renoteTime.value); } } @@ -793,11 +837,11 @@ function blur() { } function focusBefore() { - focusPrev(rootEl.value ?? null); + focusPrev(rootEl.value); } function focusAfter() { - focusNext(rootEl.value ?? null); + focusNext(rootEl.value); } function readPromo() { @@ -835,7 +879,7 @@ function emitUpdReaction(emoji: string, delta: number) { &:focus-visible { outline: none; - &:after { + &::after { content: ""; pointer-events: none; display: block; @@ -848,7 +892,7 @@ function emitUpdReaction(emoji: string, delta: number) { margin: auto; width: calc(100% - 8px); height: calc(100% - 8px); - border: solid 1px var(--focus); + border: solid 2px var(--focus); border-radius: var(--radius); box-sizing: border-box; } From b4624ce03535fd6db8320c853cc09b4ad9349472 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 13:01:12 +0100 Subject: [PATCH 215/246] copy from MkNoteDetailed to SkNoteDetailed plus some extra fixes in MkNoteDetailed --- .../src/components/MkNoteDetailed.vue | 40 +++-- .../src/components/SkNoteDetailed.vue | 154 ++++++++++++------ 2 files changed, 131 insertions(+), 63 deletions(-) diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index 1354c0e7aa..e398868d54 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -458,12 +458,14 @@ useTooltip(quoteButton, async (showing) => { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: quoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); function boostVisibility() { @@ -512,7 +514,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } misskeyApi('notes/create', { @@ -528,7 +532,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } misskeyApi('notes/create', { @@ -543,7 +549,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { } function quote() { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (appearNote.value.channel) { @@ -563,7 +569,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -585,7 +593,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -643,7 +653,7 @@ function react(): void { } function like(): void { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); sound.playMisskeySfx('reaction'); misskeyApi('notes/like', { @@ -655,7 +665,9 @@ function like(): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -680,7 +692,9 @@ function undoRenote() : void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -718,11 +732,9 @@ function showMenu(): void { os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup); } -async function menuVersions(viaKeyboard = false): Promise { +async function menuVersions(): Promise { const { menu, cleanup } = await getNoteVersionsMenu({ note: note.value, menuVersionsButton }); - os.popupMenu(menu, menuVersionsButton.value, { - viaKeyboard, - }).then(focus).finally(cleanup); + os.popupMenu(menu, menuVersionsButton.value).then(focus).finally(cleanup); } async function clip(): Promise { diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue index 47c0f86ec0..ed0d689dc9 100644 --- a/packages/frontend/src/components/SkNoteDetailed.vue +++ b/packages/frontend/src/components/SkNoteDetailed.vue @@ -10,6 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only ref="rootEl" v-hotkey="keymap" :class="$style.root" + :tabindex="isDeleted ? '-1' : '0'" >
{{ i18n.ts.loadConversation }} @@ -27,7 +28,7 @@ SPDX-License-Identifier: AGPL-3.0-only
- @@ -105,7 +106,7 @@ SPDX-License-Identifier: AGPL-3.0-only {{ i18n.ts._animatedMFM.play }} {{ i18n.ts._animatedMFM.stop }}
- +
@@ -135,7 +136,7 @@ SPDX-License-Identifier: AGPL-3.0-only class="_button" :class="$style.noteFooterButton" :style="renoted ? 'color: var(--accent) !important;' : ''" - @mousedown="renoted ? undoRenote() : boostVisibility()" + @mousedown.prevent="renoted ? undoRenote() : boostVisibility()" >

{{ number(appearNote.renoteCount) }}

@@ -162,10 +163,10 @@ SPDX-License-Identifier: AGPL-3.0-only

{{ number(appearNote.reactionCount) }}

- - @@ -244,7 +245,7 @@ import MkPoll from '@/components/MkPoll.vue'; import MkUsersTooltip from '@/components/MkUsersTooltip.vue'; import MkUrlPreview from '@/components/MkUrlPreview.vue'; import SkInstanceTicker from '@/components/SkInstanceTicker.vue'; -import { pleaseLogin } from '@/scripts/please-login.js'; +import { pleaseLogin, type OpenOnRemoteOptions } from '@/scripts/please-login.js'; import { checkWordMute } from '@/scripts/check-word-mute.js'; import { userPage } from '@/filters/user.js'; import number from '@/filters/number.js'; @@ -257,6 +258,7 @@ import { reactionPicker } from '@/scripts/reaction-picker.js'; import { extractUrlFromMfm } from '@/scripts/extract-url-from-mfm.js'; import { $i } from '@/account.js'; import { i18n } from '@/i18n.js'; +import { host } from '@/config.js'; import { getNoteClipMenu, getNoteMenu } from '@/scripts/get-note-menu.js'; import { getNoteVersionsMenu } from '@/scripts/get-note-versions-menu.js'; import { useNoteCapture } from '@/scripts/use-note-capture.js'; @@ -272,6 +274,7 @@ import MkReactionIcon from '@/components/MkReactionIcon.vue'; import MkButton from '@/components/MkButton.vue'; import { boostMenuItems, type Visibility } from '@/scripts/boost-quote.js'; import { isEnabledUrlPreview } from '@/instance.js'; +import { type Keymap } from '@/scripts/hotkey.js'; const props = withDefaults(defineProps<{ note: Misskey.entities.Note; @@ -324,6 +327,7 @@ const quoteButton = shallowRef(); const clipButton = shallowRef(); const likeButton = shallowRef(); const appearNote = computed(() => isRenote ? note.value.renote as Misskey.entities.Note : note.value); +const galleryEl = shallowRef>(); const isMyRenote = $i && ($i.id === note.value.userId); const showContent = ref(defaultStore.state.uncollapseCW); const isDeleted = ref(false); @@ -358,14 +362,31 @@ if ($i) { let renoting = false; +const pleaseLoginContext = computed(() => ({ + type: 'lookup', + url: `https://${host}/notes/${appearNote.value.id}`, +})); + const keymap = { - 'r': () => reply(true), - 'e|a|plus': () => react(true), - '(q)': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); }, - 'esc': blur, - 'm|o': () => showMenu(true), - 's': () => showContent.value !== showContent.value, -}; + 'r': () => reply(), + 'e|a|plus': () => react(), + 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); }, + 'm': () => showMenu(), + 'c': () => { + if (!defaultStore.state.showClipButtonInNoteFooter) return; + clip(); + }, + 'o': () => galleryEl.value?.openGallery(), + 'v|enter': () => { + if (appearNote.value.cw != null) { + showContent.value = !showContent.value; + } + }, + 'esc': { + allowRepeat: true, + callback: () => blur(), + }, +} as const satisfies Keymap; provide('react', (reaction: string) => { misskeyApi('notes/reactions/create', { @@ -425,12 +446,14 @@ useTooltip(renoteButton, async (showing) => { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: renoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); useTooltip(quoteButton, async (showing) => { @@ -444,12 +467,14 @@ useTooltip(quoteButton, async (showing) => { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: quoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); function boostVisibility() { @@ -474,18 +499,20 @@ if (appearNote.value.reactionAcceptance === 'likeOnly') { if (users.length < 1) return; - os.popup(MkReactionsViewerDetails, { + const { dispose } = os.popup(MkReactionsViewerDetails, { showing, reaction: '❤️', users, count: appearNote.value.reactionCount, targetElement: reactButton.value!, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); } function renote(visibility: Visibility, localOnly: boolean = false) { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); renoting = true; @@ -496,7 +523,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } misskeyApi('notes/create', { @@ -512,7 +541,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } misskeyApi('notes/create', { @@ -527,7 +558,7 @@ function renote(visibility: Visibility, localOnly: boolean = false) { } function quote() { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (appearNote.value.channel) { @@ -547,7 +578,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -569,7 +602,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -578,20 +613,19 @@ function quote() { } } -function reply(viaKeyboard = false): void { - pleaseLogin(); +function reply(): void { + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); os.post({ reply: appearNote.value, channel: appearNote.value.channel, - animation: !viaKeyboard, }).then(() => { focus(); }); } -function react(viaKeyboard = false): void { - pleaseLogin(); +function react(): void { + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); if (appearNote.value.reactionAcceptance === 'likeOnly') { sound.playMisskeySfx('reaction'); @@ -600,12 +634,14 @@ function react(viaKeyboard = false): void { noteId: appearNote.value.id, override: defaultLike.value, }); - const el = reactButton.value as HTMLElement | null | undefined; + const el = reactButton.value; if (el) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); @@ -626,7 +662,7 @@ function react(viaKeyboard = false): void { } function like(): void { - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); showMovedDialog(); sound.playMisskeySfx('reaction'); misskeyApi('notes/like', { @@ -638,7 +674,9 @@ function like(): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -663,7 +701,9 @@ function undoRenote() : void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -696,27 +736,23 @@ function onContextmenu(ev: MouseEvent): void { } } -function showMenu(viaKeyboard = false): void { +function showMenu(): void { const { menu, cleanup } = getNoteMenu({ note: note.value, translating, translation, isDeleted }); - os.popupMenu(menu, menuButton.value, { - viaKeyboard, - }).then(focus).finally(cleanup); + os.popupMenu(menu, menuButton.value).then(focus).finally(cleanup); } -async function menuVersions(viaKeyboard = false): Promise { +async function menuVersions(): Promise { const { menu, cleanup } = await getNoteVersionsMenu({ note: note.value, menuVersionsButton }); - os.popupMenu(menu, menuVersionsButton.value, { - viaKeyboard, - }).then(focus).finally(cleanup); + os.popupMenu(menu, menuVersionsButton.value).then(focus).finally(cleanup); } -async function clip() { +async function clip(): Promise { os.popupMenu(await getNoteClipMenu({ note: note.value, isDeleted }), clipButton.value).then(focus); } -function showRenoteMenu(viaKeyboard = false): void { +function showRenoteMenu(): void { if (!isMyRenote) return; - pleaseLogin(); + pleaseLogin(undefined, pleaseLoginContext.value); os.popupMenu([{ text: i18n.ts.unrenote, icon: 'ti ti-trash', @@ -727,9 +763,7 @@ function showRenoteMenu(viaKeyboard = false): void { }); isDeleted.value = true; }, - }], renoteTime.value, { - viaKeyboard: viaKeyboard, - }); + }], renoteTime.value); } function focus() { @@ -829,6 +863,28 @@ onUnmounted(() => { transition: box-shadow 0.1s ease; overflow: clip; contain: content; + + &:focus-visible { + outline: none; + + &::after { + content: ""; + pointer-events: none; + display: block; + position: absolute; + z-index: 10; + top: 0; + left: 0; + right: 0; + bottom: 0; + margin: auto; + width: calc(100% - 8px); + height: calc(100% - 8px); + border: dashed 2px var(--focus); + border-radius: var(--radius); + box-sizing: border-box; + } + } } .footer { From 98c7b95ecc4ad420d6335a92c8892a9ae280e97c Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 13:05:53 +0100 Subject: [PATCH 216/246] copy from global-timeline to bubble-timeline --- .../src/server/api/stream/channels/bubble-timeline.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/server/api/stream/channels/bubble-timeline.ts b/packages/backend/src/server/api/stream/channels/bubble-timeline.ts index 01be2d2089..647e9cab81 100644 --- a/packages/backend/src/server/api/stream/channels/bubble-timeline.ts +++ b/packages/backend/src/server/api/stream/channels/bubble-timeline.ts @@ -11,6 +11,7 @@ import { bindThis } from '@/decorators.js'; import { RoleService } from '@/core/RoleService.js'; import type { MiMeta } from '@/models/Meta.js'; import { isRenotePacked, isQuotePacked } from '@/misc/is-renote.js'; +import type { JsonObject } from '@/misc/json-value.js'; import Channel, { MiChannelService } from '../channel.js'; class BubbleTimelineChannel extends Channel { @@ -35,13 +36,13 @@ class BubbleTimelineChannel extends Channel { } @bindThis - public async init(params: any) { + public async init(params: JsonObject) { const policies = await this.roleService.getUserPolicies(this.user ? this.user.id : null); if (!policies.btlAvailable) return; - this.withRenotes = params.withRenotes ?? true; - this.withFiles = params.withFiles ?? false; - this.withBots = params.withBots ?? true; + this.withRenotes = !!(params.withRenotes ?? true); + this.withFiles = !!(params.withFiles ?? false); + this.withBots = !!(params.withBots ?? true); this.instance = await this.metaService.fetch(); // Subscribe events From a1c4bb49ab7c343a3bc0bd2a3d1df5e80a864b14 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 13:08:07 +0100 Subject: [PATCH 217/246] re-generate misskey-js --- packages/misskey-js/etc/misskey-js.api.md | 10 ++-- packages/misskey-js/src/autogen/endpoint.ts | 13 +++++ packages/misskey-js/src/autogen/types.ts | 53 +++++++++++++++++++++ 3 files changed, 71 insertions(+), 5 deletions(-) diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md index 3df20956db..99aeed0273 100644 --- a/packages/misskey-js/etc/misskey-js.api.md +++ b/packages/misskey-js/etc/misskey-js.api.md @@ -346,9 +346,6 @@ type AdminSilenceUserRequest = operations['admin___silence-user']['requestBody'] // @public (undocumented) type AdminSuspendUserRequest = operations['admin___suspend-user']['requestBody']['content']['application/json']; -// @public (undocumented) -type AdminUnnsfwUserRequest = operations['admin___unnsfw-user']['requestBody']['content']['application/json']; - // @public (undocumented) type AdminSystemWebhookCreateRequest = operations['admin___system-webhook___create']['requestBody']['content']['application/json']; @@ -376,6 +373,9 @@ type AdminSystemWebhookUpdateRequest = operations['admin___system-webhook___upda // @public (undocumented) type AdminSystemWebhookUpdateResponse = operations['admin___system-webhook___update']['responses']['200']['content']['application/json']; +// @public (undocumented) +type AdminUnnsfwUserRequest = operations['admin___unnsfw-user']['requestBody']['content']['application/json']; + // @public (undocumented) type AdminUnsetUserAvatarRequest = operations['admin___unset-user-avatar']['requestBody']['content']['application/json']; @@ -3306,8 +3306,8 @@ type UsersUpdateMemoRequest = operations['users___update-memo']['requestBody'][' // Warnings were encountered during analysis: // // src/entities.ts:35:2 - (ae-forgotten-export) The symbol "ModerationLogPayloads" needs to be exported by the entry point index.d.ts -// src/streaming.types.ts:220:4 - (ae-forgotten-export) The symbol "ReversiUpdateKey" needs to be exported by the entry point index.d.ts -// src/streaming.types.ts:230:4 - (ae-forgotten-export) The symbol "ReversiUpdateSettings" needs to be exported by the entry point index.d.ts +// src/streaming.types.ts:236:4 - (ae-forgotten-export) The symbol "ReversiUpdateKey" needs to be exported by the entry point index.d.ts +// src/streaming.types.ts:246:4 - (ae-forgotten-export) The symbol "ReversiUpdateSettings" needs to be exported by the entry point index.d.ts // (No @packageDocumentation comment for this package) diff --git a/packages/misskey-js/src/autogen/endpoint.ts b/packages/misskey-js/src/autogen/endpoint.ts index a199f38200..628825d504 100644 --- a/packages/misskey-js/src/autogen/endpoint.ts +++ b/packages/misskey-js/src/autogen/endpoint.ts @@ -1051,7 +1051,12 @@ export const endpointReqTypes: Record Date: Fri, 2 Aug 2024 13:11:12 +0100 Subject: [PATCH 218/246] fixes for build --- locales/index.d.ts | 8 ++++++-- packages/frontend/src/pages/user/home.vue | 1 - 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/locales/index.d.ts b/locales/index.d.ts index 9f488b21a1..20d8a361e0 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -897,11 +897,11 @@ export interface Locale extends ILocale { */ "stopActivityDelivery": string; /** - * このインスタンスをブロック + * このサーバーをブロック */ "blockThisInstance": string; /** - * インスタンスをサイレンス + * サーバーをサイレンス */ "silenceThisInstance": string; /** @@ -9090,6 +9090,10 @@ export interface Locale extends ILocale { * グローバル */ "global": string; + /** + * バッッブル + */ + "bubble": string; }; "_play": { /** diff --git a/packages/frontend/src/pages/user/home.vue b/packages/frontend/src/pages/user/home.vue index 2bf388b62a..b997fe1c3f 100644 --- a/packages/frontend/src/pages/user/home.vue +++ b/packages/frontend/src/pages/user/home.vue @@ -185,7 +185,6 @@ import { defaultStore } from '@/store.js'; import { $i, iAmModerator } from '@/account.js'; import { dateString } from '@/filters/date.js'; import { confetti } from '@/scripts/confetti.js'; -import { defaultStore } from '@/store.js'; import { misskeyApi } from '@/scripts/misskey-api.js'; import { isFollowingVisibleForMe, isFollowersVisibleForMe } from '@/scripts/isFfVisibleForMe.js'; import { useRouter } from '@/router/supplier.js'; From 6b557130974162e1ac2295c913cd6dde1f410c05 Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 13:23:15 +0100 Subject: [PATCH 219/246] map new icons phopshor doesn't have anything decent for "folder symlink", the "folder dashed" I picked is pretty bad the three classes not prefixed with `ti ` are inside a conditional in `packages/frontend/src/pages/admin/abuse-report/notification-recipient.item.vue` --- packages/frontend/vite.replaceIcons.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/frontend/vite.replaceIcons.ts b/packages/frontend/vite.replaceIcons.ts index 494a327477..f060ddcd01 100644 --- a/packages/frontend/vite.replaceIcons.ts +++ b/packages/frontend/vite.replaceIcons.ts @@ -129,6 +129,7 @@ export function pluginReplaceIcons() { iconsReplace({ values: { 'icon ti ti-brand-youtube': 'icon ph-youtube-logo ph-bold ph-lg', + 'ti ti ti-folder-symlink': 'ph-folder-dashed ph-bold ph-lg', 'ti ti-123': 'ph-numpad ph-bold ph-lg', 'ti ti-access-point': 'ph-broadcast ph-bold ph-lg', 'ti ti-activity': 'ph-pulse ph-bold ph-lg', @@ -237,6 +238,7 @@ export function pluginReplaceIcons() { 'ti ti-flask': 'ph-flask ph-bold ph-lg', 'ti ti-folder': 'ph-folder ph-bold ph-lg', 'ti ti-folder-plus': 'ph-folder-plus ph-bold ph-lg', + 'ti ti-folder-symlink': 'ph-folder-dashed ph-bold ph-lg', 'ti ti-forms': 'ph-textbox ph-bold ph-lg', 'ti ti-ghost': 'ph-ghost ph-bold ph-lg', 'ti ti-grid-dots': 'ph-dots-nine ph-bold ph-lg', @@ -312,6 +314,7 @@ export function pluginReplaceIcons() { 'ti ti-rectangle': 'ph-frame-corners ph-bold ph-lg', 'ti ti-refresh': 'ph-arrows-counter-clockwise ph-bold ph-lg', 'ti ti-repeat-off': 'ph-repeat ph-bold ph-lg', + 'ti ti-restore': 'ph-box-arrow-up ph-box ph-lg', 'ti ti-robot': 'ph-robot ph-bold ph-lg', 'ti ti-rocket': 'ph-rocket-launch ph-bold ph-lg', 'ti ti-rocket-off': 'ph-rocket ph-bold ph-lg', @@ -362,6 +365,9 @@ export function pluginReplaceIcons() { 'ti ti-world-upload': 'ph-cloud-arrow-up ph-bold ph-lg', 'ti ti-world-x': 'ph-planet ph-bold ph-lg', 'ti ti-x': 'ph-x ph-bold ph-lg', + 'ti-help': 'ph-question ph-bold ph-lg', + 'ti-mail': 'ph-envelope ph-bold ph-lg', + 'ti-webhook': 'ph-webhooks-logo ph-bold ph-lg', 'ti ti-caret-down': 'ph-caret-down ph-bold ph-lg', 'ti ti-chevron-down': 'ph-caret-down ph-bold ph-lg', }, From fb082222c10aed2a3179cbc1ed19f973b4d95d5b Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 13:25:27 +0100 Subject: [PATCH 220/246] update icon-related instructions --- CONTRIBUTING.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9e7d771104..c31d925991 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -580,7 +580,7 @@ seems to do a decent job) *after that commit*, do all the extra work, on the same branch: -* copy all changes: +* copy all changes (commit after each step): * in `packages/backend/src/core/NoteCreateService.ts`, from `create` to `import` (and vice versa if `git` got confused!) * from `packages/backend/src/core/NoteCreateService.ts` to @@ -599,12 +599,18 @@ seems to do a decent job) `packages/frontend/src/pages/timeline.vue`, `packages/frontend/src/ui/deck/tl-column.vue`, `packages/frontend/src/widgets/WidgetTimeline.vue`) +* re-generate `misskey-js` (`pnpm build-misskey-js-with-types`) and commit +* build the frontend: `rm -rf built/; NODE_ENV=development pnpm --filter=frontend + build` (the `development` tells it to keep some of the original + filenames in the built files) * make sure there aren't any new `ti-*` classes (Tabler Icons), and - replace them with appropriate `ph-*` ones (Phosphor Icons). - `git grep '["'\'']ti[ -](?!fw)'` should show you what to change. + replace them with appropriate `ph-*` ones (Phosphor Icons): + `grep -rP '["'\'']ti[ -](?!fw)' -- built/` should show you what to change. NOTE: `ti-fw` is a special class that's defined by Misskey, leave it alone -* re-generate `misskey-js`: `pnpm build-misskey-js-with-types` + + after every change, re-build the frontend and check again, until + there are no more `ti-*` classes in the built files * run tests `pnpm test` and fix as much as you can * right now `megalodon` doesn't pass its tests, you probably need to run `pnpm --filter=backend test` (requires a test database, [see From ef99b1ca071ac63b87679873c522768c4f428b1d Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 13:47:40 +0100 Subject: [PATCH 221/246] put back dependency I had deleted by accident --- packages/backend/package.json | 1 + pnpm-lock.yaml | 49 +++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/packages/backend/package.json b/packages/backend/package.json index 7b994cf2d0..df4fb2b96e 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -114,6 +114,7 @@ "deep-email-validator": "0.1.21", "fast-xml-parser": "^4.4.0", "fastify": "4.28.1", + "fastify-multer": "^2.0.3", "fastify-raw-body": "4.3.0", "feed": "4.2.2", "file-type": "19.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a37460bd5f..b2c4d9ba47 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -232,6 +232,9 @@ importers: fastify: specifier: 4.28.1 version: 4.28.1 + fastify-multer: + specifier: ^2.0.3 + version: 2.0.3 fastify-raw-body: specifier: 4.3.0 version: 4.3.0 @@ -2962,6 +2965,10 @@ packages: '@fastify/ajv-compiler@3.5.0': resolution: {integrity: sha512-ebbEtlI7dxXF5ziNdr05mOY8NnDiPB1XvAlLHctRt/Rc+C3LCOVW5imUVX+mhvUhnNzmPBHewUkOFgGlCxgdAA==} + '@fastify/busboy@1.2.1': + resolution: {integrity: sha512-7PQA7EH43S0CxcOa9OeAnaeA0oQ+e/DHNPZwSQM9CQHW76jle5+OvLdibRp/Aafs9KXbLhxyjOTkRjWUbQEd3Q==} + engines: {node: '>=14'} + '@fastify/busboy@2.1.0': resolution: {integrity: sha512-+KpH+QxZU7O4675t3mnkQKcZZg56u+K/Ct2K+N2AZYNVK8kyeo/bI18tI8aPm3tvNNRyTWfj6s5tnGNlcbQRsA==} engines: {node: '>=14'} @@ -6466,6 +6473,10 @@ packages: resolution: {integrity: sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==} engines: {'0': node >= 0.8} + concat-stream@2.0.0: + resolution: {integrity: sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==} + engines: {'0': node >= 6.0} + config-chain@1.1.13: resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} @@ -7269,6 +7280,13 @@ packages: resolution: {integrity: sha512-kLY3jFlwIYwBNDojclKsNAC12sfD6NwW74QB2CoNGPvtVxjliYehVunB3HYyNi+n4Tt1dAcgwYvmKF/Z18flqg==} hasBin: true + fastify-multer@2.0.3: + resolution: {integrity: sha512-QnFqrRgxmUwWHTgX9uyQSu0C/hmVCfcxopqjApZ4uaZD5W9MJ+nHUlW4+9q7Yd3BRxDIuHvgiM5mjrh6XG8cAA==} + engines: {node: '>=10.17.0'} + + fastify-plugin@2.3.4: + resolution: {integrity: sha512-I+Oaj6p9oiRozbam30sh39BiuiqBda7yK2nmSPVwDCfIBlKnT8YB3MY+pRQc2Fcd07bf6KPGklHJaQ2Qu81TYQ==} + fastify-plugin@4.5.0: resolution: {integrity: sha512-79ak0JxddO0utAXAQ5ccKhvs6vX2MGyHHMMsmZkBANrq3hXc1CHzvNPHOcvTsVMEPl5I+NT+RO4YKMGehOfSIg==} @@ -10992,6 +11010,9 @@ packages: resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} engines: {node: '>=8'} + text-decoding@1.0.0: + resolution: {integrity: sha512-/0TJD42KDnVwKmDK6jj3xP7E2MG7SHAOG4tyTgyUCRPdHwvkquYNLEQltmdMa3owq3TkddCVcTsoctJI8VQNKA==} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -14014,6 +14035,10 @@ snapshots: ajv-formats: 2.1.1(ajv@8.17.1) fast-uri: 2.2.0 + '@fastify/busboy@1.2.1': + dependencies: + text-decoding: 1.0.0 + '@fastify/busboy@2.1.0': {} '@fastify/cookie@9.3.1': @@ -18518,6 +18543,13 @@ snapshots: readable-stream: 2.3.7 typedarray: 0.0.6 + concat-stream@2.0.0: + dependencies: + buffer-from: 1.1.2 + inherits: 2.0.4 + readable-stream: 3.6.0 + typedarray: 0.0.6 + config-chain@1.1.13: dependencies: ini: 1.3.8 @@ -19661,6 +19693,21 @@ snapshots: dependencies: strnum: 1.0.5 + fastify-multer@2.0.3: + dependencies: + '@fastify/busboy': 1.2.1 + append-field: 1.0.0 + concat-stream: 2.0.0 + fastify-plugin: 2.3.4 + mkdirp: 1.0.4 + on-finished: 2.4.1 + type-is: 1.6.18 + xtend: 4.0.2 + + fastify-plugin@2.3.4: + dependencies: + semver: 7.6.0 + fastify-plugin@4.5.0: {} fastify-raw-body@4.3.0: @@ -24000,6 +24047,8 @@ snapshots: glob: 7.2.3 minimatch: 3.1.2 + text-decoding@1.0.0: {} + text-table@0.2.0: {} textarea-caret@3.1.0: {} From 72758a2dbf5c0e93a3811a39f14d83cf372cad7b Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 13:47:49 +0100 Subject: [PATCH 222/246] =?UTF-8?q?fix=20mfm=E2=86=92sfm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/backend/src/server/web/FeedService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/web/FeedService.ts b/packages/backend/src/server/web/FeedService.ts index c88ac3e5bb..57a32ca934 100644 --- a/packages/backend/src/server/web/FeedService.ts +++ b/packages/backend/src/server/web/FeedService.ts @@ -15,7 +15,7 @@ import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.j import { bindThis } from '@/decorators.js'; import { IdService } from '@/core/IdService.js'; import { MfmService } from "@/core/MfmService.js"; -import { parse as mfmParse } from 'mfm-js'; +import { parse as mfmParse } from '@transfem-org/sfm-js'; @Injectable() export class FeedService { From c0fc6ce8cd5d3687073c863046ab2e2313d1b5bb Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 2 Aug 2024 13:48:09 +0100 Subject: [PATCH 223/246] update testing instructions --- CONTRIBUTING.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c31d925991..7a017ca7cc 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -609,12 +609,16 @@ seems to do a decent job) NOTE: `ti-fw` is a special class that's defined by Misskey, leave it alone - after every change, re-build the frontend and check again, until + after every change, re-build the frontend and check again, until there are no more `ti-*` classes in the built files -* run tests `pnpm test` and fix as much as you can - * right now `megalodon` doesn't pass its tests, you probably need to - run `pnpm --filter=backend test` (requires a test database, [see - above](#testing)) and `pnpm --filter=frontend test` + + commit! +* double-check the new migration, that they won't conflict with our db + changes: `git diff develop -- packages/backend/migration/` +* `pnpm clean; pnpm build` +* run tests `pnpm --filter='!megalodon' test` (requires a test + database, [see above](#testing)) and fix as much as you can + * right now `megalodon` doesn't pass its tests, so we skip them * run lint `pnpm --filter=backend lint` + `pnpm --filter=frontend eslint` and fix as much as you can From f0dd0b8993a904716fcbc37ff02d81865fa444b1 Mon Sep 17 00:00:00 2001 From: dakkar Date: Sat, 3 Aug 2024 18:04:06 +0100 Subject: [PATCH 224/246] revert AiScript hack for plugins aiscript 0.19 should have fixed the problem, and no longer `abort` when an error gets handled (or, in this case, logged) --- packages/frontend/src/plugin.ts | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/packages/frontend/src/plugin.ts b/packages/frontend/src/plugin.ts index a0a624ace7..81233a5a5e 100644 --- a/packages/frontend/src/plugin.ts +++ b/packages/frontend/src/plugin.ts @@ -28,31 +28,10 @@ export async function install(plugin: Plugin): Promise { }, log: (): void => { }, - /* dakkar 2024-06-20 - - passing an `err` triggers an unwanted side-effect inside the - AiScript Interpreter: - - - the plugin code throws an exception of any kind (in the - specific case that made us look, it was `note.text.split(...)` - on a note with no text) - - - the Interpreter's `handleError` calls `this.abort()` before - calling our `err` - - - from that point on, every evaluation of that Interpreter object - returns null - - - which, at least inside a noteViewInterruptor, causes all notes - to be replaced with a null - - I'm reporting this problem upstream, in the meantime we'll have - to do without error logs - */ - // err: (err): void => { - // pluginLogs.value.get(plugin.id).push(`${err}`); - // throw err; // install時のtry-catchに反応させる - // }, + err: (err): void => { + pluginLogs.value.get(plugin.id).push(`${err}`); + throw err; // install時のtry-catchに反応させる + }, }); initPlugin({ plugin, aiscript }); From dadf6496d1ecff14d3d8f2cc35addf25e171321a Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 10:39:43 +0100 Subject: [PATCH 225/246] remove double spaces from translations --- locales/ca-ES.yml | 4 ++-- locales/en-US.yml | 6 +++--- locales/es-ES.yml | 4 ++-- locales/fr-FR.yml | 2 +- locales/id-ID.yml | 2 +- locales/it-IT.yml | 4 ++-- locales/nl-NL.yml | 2 +- locales/pl-PL.yml | 2 +- locales/pt-PT.yml | 4 ++-- locales/tr-TR.yml | 2 +- locales/uz-UZ.yml | 2 +- locales/vi-VN.yml | 6 +++--- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 70676eb058..0b2acf8f05 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -540,7 +540,7 @@ objectStorageRegion: "Regió " objectStorageRegionDesc: "Especifica una regió com 'xx-east-1'. Si el teu servei no diferència regions has de posar 'us-east-1'. Deixa'l buit si fas servir variables d'entorn o un arxiu de configuració d'AWS." objectStorageUseSSL: "Fes servir SSL" objectStorageUseSSLDesc: "Desactiva'l si no tens pensat fer servir HTTPS per les connexions de l'API" -objectStorageUseProxy: "Connectar-se mitjançant un Proxy" +objectStorageUseProxy: "Connectar-se mitjançant un Proxy" objectStorageUseProxyDesc: "Desactiva'l si no faràs servir un Proxy per les connexions de l'API" objectStorageSetPublicRead: "Configurar les pujades com públiques " s3ForcePathStyleDesc: "Si s3ForcePathStyle es troba activat el nom del dipòsit s'ha d'incloure a l'adreça URL en comtes del nom del host. Potser que necessitis activar-ho quan facis servir, per exemple, Minio a un servidor propi." @@ -1739,7 +1739,7 @@ _email: _follow: title: "t'ha seguit" _receiveFollowRequest: - title: "Has rebut una sol·licitud de seguiment" + title: "Has rebut una sol·licitud de seguiment" _plugin: install: "Instal·lar un afegit " installWarn: "Si us plau, no instal·lis afegits que no siguin de confiança." diff --git a/locales/en-US.yml b/locales/en-US.yml index d36e5870ec..341ee56969 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -501,7 +501,7 @@ noMessagesYet: "No messages yet" newMessageExists: "There are new messages" onlyOneFileCanBeAttached: "You can only attach one file to a message" signinRequired: "Please register or sign in before continuing" -signinOrContinueOnRemote: "To continue, you need to move your server or sign up / log in to this server." +signinOrContinueOnRemote: "To continue, you need to move your server or sign up / log in to this server." invitations: "Invites" invitationCode: "Invitation code" checking: "Checking..." @@ -913,7 +913,7 @@ whatIsNew: "Show changes" translate: "Translate" translatedFrom: "Translated from {x}" accountDeletionInProgress: "Account deletion is currently in progress" -usernameInfo: "A name that identifies your account from others on this server. You can use the alphabet (a~z, A~Z), digits (0~9) or underscores (_). Usernames cannot be changed later." +usernameInfo: "A name that identifies your account from others on this server. You can use the alphabet (a~z, A~Z), digits (0~9) or underscores (_). Usernames cannot be changed later." aiChanMode: "Ai Mode" devMode: "Developer mode" keepCw: "Keep content warnings" @@ -2729,7 +2729,7 @@ _dataSaver: description: "Prevents images/videos from being loaded automatically. Hidden images/videos will be loaded when tapped." _avatar: title: "Avatar image" - description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic." + description: "Stop avatar image animation. Animated images can be larger in file size than normal images, potentially leading to further reductions in data traffic." _urlPreview: title: "URL preview thumbnails" description: "URL preview thumbnail images will no longer be loaded." diff --git a/locales/es-ES.yml b/locales/es-ES.yml index de05299e02..3f64576cb1 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -867,7 +867,7 @@ whatIsNew: "Mostrar cambios" translate: "Traducir" translatedFrom: "Traducido de {x}" accountDeletionInProgress: "La eliminación de la cuenta está en curso" -usernameInfo: "Un nombre que identifique su cuenta de otras en este servidor. Puede utilizar el alfabeto (a~z, A~Z), dígitos (0~9) o guiones bajos (_). Los nombres de usuario no se pueden cambiar posteriormente." +usernameInfo: "Un nombre que identifique su cuenta de otras en este servidor. Puede utilizar el alfabeto (a~z, A~Z), dígitos (0~9) o guiones bajos (_). Los nombres de usuario no se pueden cambiar posteriormente." aiChanMode: "Modo Ai" devMode: "Modo de desarrollador" keepCw: "Mantener la advertencia de contenido" @@ -2354,7 +2354,7 @@ _deck: newProfile: "Nuevo perfil" deleteProfile: "Eliminar perfil" introduction: "¡Crea la interfaz perfecta para tí organizando las columnas libremente!" - introduction2: "Presiona en la + de la derecha de la pantalla para añadir nuevas columnas donde quieras." + introduction2: "Presiona en la + de la derecha de la pantalla para añadir nuevas columnas donde quieras." widgetsIntroduction: "Por favor selecciona \"Editar Widgets\" en el menú columna y agrega un widget." useSimpleUiForNonRootPages: "Mostrar páginas no pertenecientes a la raíz con la interfaz simple" usedAsMinWidthWhenFlexible: "Se usará el ancho mínimo cuando la opción \"Autoajustar ancho\" esté habilitada" diff --git a/locales/fr-FR.yml b/locales/fr-FR.yml index 5176bd8f0f..9dfeef339c 100644 --- a/locales/fr-FR.yml +++ b/locales/fr-FR.yml @@ -1245,7 +1245,7 @@ _announcement: end: "Archiver l'annonce" tooManyActiveAnnouncementDescription: "Un grand nombre d'annonces actives peut baisser l'expérience utilisateur. Considérez d'archiver les annonces obsolètes." readConfirmTitle: "Marquer comme lu ?" - readConfirmText: "Cela marquera le contenu de « {title} » comme lu." + readConfirmText: "Cela marquera le contenu de « {title} » comme lu." shouldNotBeUsedToPresentPermanentInfo: "Puisque cela pourrait nuire considérablement à l'expérience utilisateur pour les nouveaux utilisateurs, il est recommandé d'utiliser les annonces pour afficher des informations temporaires plutôt que des informations persistantes." dialogAnnouncementUxWarn: "Avoir deux ou plus annonces de style dialogue en même temps pourrait nuire considérablement à l'expérience utilisateur. Veuillez les utiliser avec caution." silence: "Ne pas me notifier" diff --git a/locales/id-ID.yml b/locales/id-ID.yml index 048c9725bf..2f225c1199 100644 --- a/locales/id-ID.yml +++ b/locales/id-ID.yml @@ -584,7 +584,7 @@ sort: "Urutkan" ascendingOrder: "Urutkan naik" descendingOrder: "Urutkan menurun" scratchpad: "Scratchpad" -scratchpadDescription: "Scratchpad menyediakan lingkungan eksperimen untuk AiScript. Kamu bisa menulis, mengeksuksi, serta mengecek hasil yang berinteraksi dengan Misskey." +scratchpadDescription: "Scratchpad menyediakan lingkungan eksperimen untuk AiScript. Kamu bisa menulis, mengeksuksi, serta mengecek hasil yang berinteraksi dengan Misskey." output: "Keluaran" script: "Script" disablePagesScript: "Nonaktifkan script pada halaman" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 9de547c8f0..734b4bd0b1 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1783,7 +1783,7 @@ _ad: _forgotPassword: enterEmail: "Inserisci l'indirizzo di posta elettronica che hai registrato nel tuo profilo. Il collegamento necessario per ripristinare la password verrà inviato a questo indirizzo." ifNoEmail: "Se il tuo indirizzo email non risulta registrato, contatta l'amministrazione dell'istanza." - contactAdmin: "Poiché questa istanza non permette di impostare l'indirizzo mail, contatta l'amministrazione per ripristinare la password.\n" + contactAdmin: "Poiché questa istanza non permette di impostare l'indirizzo mail, contatta l'amministrazione per ripristinare la password.\n" _gallery: my: "Le mie pubblicazioni" liked: "Pubblicazioni che mi piacciono" @@ -2405,7 +2405,7 @@ _deck: roleTimeline: "Timeline Ruolo" _dialog: charactersExceeded: "Hai superato il limite di {max} caratteri! ({current})" - charactersBelow: "Sei al di sotto del minimo di {min} caratteri! ({current})" + charactersBelow: "Sei al di sotto del minimo di {min} caratteri! ({current})" _disabledTimeline: title: "Timeline disabilitata" description: "Il ruolo in cui sei non ti permette di leggere questa timeline" diff --git a/locales/nl-NL.yml b/locales/nl-NL.yml index 2154e248af..686d532c4c 100644 --- a/locales/nl-NL.yml +++ b/locales/nl-NL.yml @@ -251,7 +251,7 @@ upload: "Uploaden" keepOriginalUploading: "Origineel beeld behouden." keepOriginalUploadingDescription: "Bewaar de originele versie bij het uploaden van afbeeldingen. Indien uitgeschakeld, wordt bij het uploaden een alternatieve versie voor webpublicatie genereert." fromDrive: "Van schijf" -fromUrl: "Van URL" +fromUrl: "Van URL" uploadFromUrl: "Uploaden vanaf een URL" uploadFromUrlDescription: "URL van het bestand dat je wil uploaden" uploadFromUrlRequested: "Uploadverzoek" diff --git a/locales/pl-PL.yml b/locales/pl-PL.yml index d0306bc5d9..b20eabf7f2 100644 --- a/locales/pl-PL.yml +++ b/locales/pl-PL.yml @@ -865,7 +865,7 @@ whatIsNew: "Pokaż zmiany" translate: "Przetłumacz" translatedFrom: "Przetłumaczone z {x}" accountDeletionInProgress: "Trwa usuwanie konta" -usernameInfo: "Nazwa, która identyfikuje Twoje konto spośród innych na tym serwerze. Możesz użyć alfabetu (a~z, A~Z), cyfr (0~9) lub podkreślników (_). Nazwy użytkownika nie mogą być później zmieniane." +usernameInfo: "Nazwa, która identyfikuje Twoje konto spośród innych na tym serwerze. Możesz użyć alfabetu (a~z, A~Z), cyfr (0~9) lub podkreślników (_). Nazwy użytkownika nie mogą być później zmieniane." aiChanMode: "Tryb Ai" devMode: "Tryb programisty" keepCw: "Zostaw ostrzeżenia o zawartości" diff --git a/locales/pt-PT.yml b/locales/pt-PT.yml index 6dd3077898..484c79ed06 100644 --- a/locales/pt-PT.yml +++ b/locales/pt-PT.yml @@ -225,7 +225,7 @@ done: "Concluído" processing: "Em Progresso" preview: "Pré-visualizar" default: "Predefinição" -defaultValueIs: "Predefinição: {value}" +defaultValueIs: "Predefinição: {value}" noCustomEmojis: "Não há emojis" noJobs: "Não há tarefas" federating: "Federando" @@ -1418,7 +1418,7 @@ _charts: _timelines: home: "Início" _play: - new: "Criar Play" + new: "Criar Play" edit: "Editar Play" created: "Play criado" updated: "Play editado" diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index cf6729a81d..266fb3161c 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -359,7 +359,7 @@ smtpUser: "Kullanıcı Adı" smtpPass: "Şifre" notificationSetting: "Bildirim ayarları" instanceTicker: "Notların sunucu bilgileri" -noCrawleDescription: "Arama motorlarından profilinde, notlarında, sayfalarında vb. dolaşılmamasını ve dizine eklememesini talep et." +noCrawleDescription: "Arama motorlarından profilinde, notlarında, sayfalarında vb. dolaşılmamasını ve dizine eklememesini talep et." clearCache: "Ön belleği temizle" onlineUsersCount: "{n} kullanıcı çevrim içi" user: "Kullanıcı" diff --git a/locales/uz-UZ.yml b/locales/uz-UZ.yml index 75442b3cf1..2023771104 100644 --- a/locales/uz-UZ.yml +++ b/locales/uz-UZ.yml @@ -443,7 +443,7 @@ text: "Matn" enable: "Yoqish" next: "Keyingisi" retype: "Qayta kiriting" -noteOf: "{user} tomonidan joylandi\n" +noteOf: "{user} tomonidan joylandi\n" quoteAttached: "Iqtibos" quoteQuestion: "Iqtibos sifatida qo'shilsinmi?" noMessagesYet: "Bu yerda xabarlar yo'q" diff --git a/locales/vi-VN.yml b/locales/vi-VN.yml index ca79af7687..87b4403c27 100644 --- a/locales/vi-VN.yml +++ b/locales/vi-VN.yml @@ -1288,7 +1288,7 @@ _achievements: _iLoveMisskey: title: "Tôi Yêu Misskey" description: "Đăng lời nói \"I ❤ #Misskey\"" - flavor: "Xin chân thành cảm ơn bạn đã sử dụng Misskey!! by Đội ngũ phát triển" + flavor: "Xin chân thành cảm ơn bạn đã sử dụng Misskey!! by Đội ngũ phát triển" _foundTreasure: title: "Tìm kiếm kho báu" description: "Tìm thấy được những kho báu cất giấu" @@ -1329,7 +1329,7 @@ _achievements: description: "Bấm chỗ này" _justPlainLucky: title: "Chỉ là một cuộc máy mắn" - description: "Mỗi 10 giây thu nhận được với tỷ lệ 0.005%" + description: "Mỗi 10 giây thu nhận được với tỷ lệ 0.005%" _setNameToSyuilo: title: "Ngưỡng mộ với vị thần" description: "Đạt tên là syuilo" @@ -1483,7 +1483,7 @@ _wordMute: muteWordsDescription: "Separate with spaces for an AND condition or with line breaks for an OR condition." muteWordsDescription2: "Bao quanh các từ khóa bằng dấu gạch chéo để sử dụng cụm từ thông dụng." _instanceMute: - instanceMuteDescription: "Thao tác này sẽ ẩn mọi tút/lượt đăng lại từ các máy chủ được liệt kê, bao gồm cả những tút dạng trả lời từ máy chủ bị ẩn." + instanceMuteDescription: "Thao tác này sẽ ẩn mọi tút/lượt đăng lại từ các máy chủ được liệt kê, bao gồm cả những tút dạng trả lời từ máy chủ bị ẩn." instanceMuteDescription2: "Tách bằng cách xuống dòng" title: "Ẩn tút từ những máy chủ đã liệt kê." heading: "Danh sách những máy chủ bị ẩn" From 6379deb5a741586ae5667043e99712dac71e9083 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 10:44:56 +0100 Subject: [PATCH 226/246] fail `AbuseReportService.resolve` harder without remote users as @fEmber noticed, if `findOneByOrFail` throws, we would have marked the report as resolved, without logging that this way, the whole operation fails (the frontend should not send us ids of users that can't be resolved!) --- packages/backend/src/core/AbuseReportService.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/AbuseReportService.ts b/packages/backend/src/core/AbuseReportService.ts index 69c51509ba..ed10a4c5c6 100644 --- a/packages/backend/src/core/AbuseReportService.ts +++ b/packages/backend/src/core/AbuseReportService.ts @@ -93,6 +93,17 @@ export class AbuseReportService { id: In(params.map(it => it.reportId)), }); + const targetUserMap = new Map(); + for (const report of reports) { + const shouldForward = paramsMap.get(report.id)!.forward; + + if (shouldForward && report.targetUserHost != null) { + return targetUserMap.set(report.id, await this.usersRepository.findOneByOrFail({ id: report.targetUserId })); + } else { + return targetUserMap.set(report.id, null); + } + } + for (const report of reports) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const ps = paramsMap.get(report.id)!; @@ -103,9 +114,9 @@ export class AbuseReportService { forwarded: ps.forward && report.targetUserHost !== null, }); - if (ps.forward && report.targetUserHost != null) { + const targetUser = targetUserMap.get(report.id)!; + if (targetUser != null) { const actor = await this.instanceActorService.getInstanceActor(); - const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId }); // eslint-disable-next-line const flag = this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment); From 02748edd17a2b200806757eba50492fc68c582c3 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 11:03:09 +0100 Subject: [PATCH 227/246] remove spurious `.then()` --- packages/backend/src/core/AbuseReportService.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/backend/src/core/AbuseReportService.ts b/packages/backend/src/core/AbuseReportService.ts index ed10a4c5c6..05f11870a1 100644 --- a/packages/backend/src/core/AbuseReportService.ts +++ b/packages/backend/src/core/AbuseReportService.ts @@ -129,8 +129,7 @@ export class AbuseReportService { reportId: report.id, report: report, forwarded: ps.forward && report.targetUserHost !== null, - }) - .then(); + }); } return this.abuseUserReportsRepository.findBy({ id: In(reports.map(it => it.id)) }) From 151470d882eaac1f9bc2b334abb432c1fa427e35 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 11:14:24 +0100 Subject: [PATCH 228/246] make "media silenced" work like "silenced" that is, silencing `foo.com` also silences `sub.foo.com` --- packages/backend/src/core/UtilityService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/core/UtilityService.ts b/packages/backend/src/core/UtilityService.ts index 0d6af8b33a..22871e44f8 100644 --- a/packages/backend/src/core/UtilityService.ts +++ b/packages/backend/src/core/UtilityService.ts @@ -45,7 +45,7 @@ export class UtilityService { @bindThis public isMediaSilencedHost(silencedHosts: string[] | undefined, host: string | null): boolean { if (!silencedHosts || host == null) return false; - return silencedHosts.some(x => host.toLowerCase() === x); + return silencedHosts.some(x => `.${host.toLowerCase()}`.endsWith(`.${x}`)); } @bindThis From cb5de3fbfc204cf95bf7e3963ddd1e881ef440d9 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 11:24:43 +0100 Subject: [PATCH 229/246] fix type for env variable --- packages/backend/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 87c2d55aa3..c2463ea5ca 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -227,7 +227,7 @@ export function loadConfig(): Config { if (configFiles.length === 0 && !process.env['MK_WARNED_ABOUT_CONFIG']) { console.log('No config files loaded, check if this is intentional'); - process.env['MK_WARNED_ABOUT_CONFIG'] = true; + process.env['MK_WARNED_ABOUT_CONFIG'] = '1'; } const config = configFiles.map(path => fs.readFileSync(path, 'utf-8')) From f85e8a42786d8f46498cbaeb3eccc214ac499742 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 11:35:03 +0100 Subject: [PATCH 230/246] appease the linter --- packages/backend/src/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index c2463ea5ca..64f2d2ac65 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -459,7 +459,7 @@ function applyEnvOverrides(config: Source) { _apply_top([['sentryForFrontend', 'sentryForBackend'], 'options', ['dsn', 'profileSampleRate', 'serverName', 'includeLocalVariables', 'proxy', 'keepAlive', 'caCerts']]); _apply_top(['sentryForBackend', 'enableNodeProfiling']); _apply_top([['clusterLimit', 'deliverJobConcurrency', 'inboxJobConcurrency', 'relashionshipJobConcurrency', 'deliverJobPerSec', 'inboxJobPerSec', 'relashionshipJobPerSec', 'deliverJobMaxAttempts', 'inboxJobMaxAttempts']]); - _apply_top([['outgoingAddress', 'outgoingAddressFamily', 'proxy', 'proxySmtp', 'mediaProxy', 'proxyRemoteFiles','videoThumbnailGenerator']]); + _apply_top([['outgoingAddress', 'outgoingAddressFamily', 'proxy', 'proxySmtp', 'mediaProxy', 'proxyRemoteFiles', 'videoThumbnailGenerator']]); _apply_top([['maxFileSize', 'maxNoteLength', 'pidFile']]); _apply_top(['import', ['downloadTimeout', 'maxFileSize']]); _apply_top([['signToActivityPubGet', 'checkActivityPubGetSignature']]); From 65ae788d90f666d3c835b31a01f641778b82ba8d Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 18:05:15 +0100 Subject: [PATCH 231/246] update our icons to the new custom font mostly, `ph-bold` was replacing the font-family, so we're now using `sk-icons-lg` --- packages/frontend/src/pages/settings/general.vue | 10 +++++----- packages/frontend/src/ui/_common_/common.ts | 2 +- packages/frontend/vite.replaceIcons.ts | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/frontend/src/pages/settings/general.vue b/packages/frontend/src/pages/settings/general.vue index 47681e6cde..75afe67be7 100644 --- a/packages/frontend/src/pages/settings/general.vue +++ b/packages/frontend/src/pages/settings/general.vue @@ -98,8 +98,8 @@ SPDX-License-Identifier: AGPL-3.0-only - - + + {{ i18n.ts.limitWidthOfReaction }}
@@ -213,8 +213,8 @@ SPDX-License-Identifier: AGPL-3.0-only - - + +
@@ -590,7 +590,7 @@ function testNotification(): void { async function testNotificationDot() { const success = await worksOnInstance(); - + if (success) { os.toast(i18n.ts.notificationDotWorking); } else { diff --git a/packages/frontend/src/ui/_common_/common.ts b/packages/frontend/src/ui/_common_/common.ts index 0dcbf717c6..f719e73259 100644 --- a/packages/frontend/src/ui/_common_/common.ts +++ b/packages/frontend/src/ui/_common_/common.ts @@ -125,7 +125,7 @@ export function openInstanceMenu(ev: MouseEvent) { } : undefined, { type: 'link', text: i18n.ts.aboutMisskey, - icon: 'sk-icons sk-shark ph-bold', + icon: 'sk-icons sk-shark sk-icons-lg', to: '/about-sharkey', }], ev.currentTarget ?? ev.target, { align: 'left', diff --git a/packages/frontend/vite.replaceIcons.ts b/packages/frontend/vite.replaceIcons.ts index f060ddcd01..da038e288a 100644 --- a/packages/frontend/vite.replaceIcons.ts +++ b/packages/frontend/vite.replaceIcons.ts @@ -129,7 +129,7 @@ export function pluginReplaceIcons() { iconsReplace({ values: { 'icon ti ti-brand-youtube': 'icon ph-youtube-logo ph-bold ph-lg', - 'ti ti ti-folder-symlink': 'ph-folder-dashed ph-bold ph-lg', + 'ti ti ti-folder-symlink': 'sk-icons sk-foldermove sk-icons-lg', 'ti ti-123': 'ph-numpad ph-bold ph-lg', 'ti ti-access-point': 'ph-broadcast ph-bold ph-lg', 'ti ti-activity': 'ph-pulse ph-bold ph-lg', @@ -238,7 +238,7 @@ export function pluginReplaceIcons() { 'ti ti-flask': 'ph-flask ph-bold ph-lg', 'ti ti-folder': 'ph-folder ph-bold ph-lg', 'ti ti-folder-plus': 'ph-folder-plus ph-bold ph-lg', - 'ti ti-folder-symlink': 'ph-folder-dashed ph-bold ph-lg', + 'ti ti-folder-symlink': 'sk-icons sk-foldermove sk-icons-lg', 'ti ti-forms': 'ph-textbox ph-bold ph-lg', 'ti ti-ghost': 'ph-ghost ph-bold ph-lg', 'ti ti-grid-dots': 'ph-dots-nine ph-bold ph-lg', From e9255d45f88a506d7c9f9ea31bd917e4d92a41d4 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 19:23:03 +0100 Subject: [PATCH 232/246] fix spacing (thanks linter) --- packages/backend/src/core/MfmService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/core/MfmService.ts b/packages/backend/src/core/MfmService.ts index 048910cb52..1b6951ca19 100644 --- a/packages/backend/src/core/MfmService.ts +++ b/packages/backend/src/core/MfmService.ts @@ -678,7 +678,7 @@ export class MfmService { let result = new XMLSerializer().serializeToString(body); if (inline) { - result = result.replace(/^

/,'').replace(/<\/p>$/,''); + result = result.replace(/^

/, '').replace(/<\/p>$/, ''); } return result; From 4c409dd6c6df1f709b70977ad87c438e75d6fba8 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 19:51:11 +0100 Subject: [PATCH 233/246] fix comparison (thanks linter) --- packages/backend/src/core/CustomEmojiService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts index dd5f79a22b..cd906a72af 100644 --- a/packages/backend/src/core/CustomEmojiService.ts +++ b/packages/backend/src/core/CustomEmojiService.ts @@ -144,7 +144,7 @@ export class CustomEmojiService implements OnApplicationShutdown { if (data.driveFile != null) { const file = await this.driveFilesRepository.findOneBy({ url: emoji.originalUrl, userHost: emoji.host ? emoji.host : IsNull() }); - if (file && file.id != data.driveFile.id) { + if (file && file.id !== data.driveFile.id) { await this.driveService.deleteFile(file, false, moderator ? moderator : undefined); } } From 8a37ed668e21dfee60d308de67e185ab2c7ea407 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 20:28:50 +0100 Subject: [PATCH 234/246] fix variable name is MkMediaList --- packages/frontend/src/components/MkMediaList.vue | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/frontend/src/components/MkMediaList.vue b/packages/frontend/src/components/MkMediaList.vue index 9e78b69574..4bc2b9fba7 100644 --- a/packages/frontend/src/components/MkMediaList.vue +++ b/packages/frontend/src/components/MkMediaList.vue @@ -178,14 +178,14 @@ onMounted(() => { textBox.className = 'pswp__alt-text _acrylic'; el.appendChild(textBox); - pwsp.on('change', () => { - if (pwsp.currSlide?.data.comment) { + pswp.on('change', () => { + if (pswp.currSlide?.data.comment) { textBox.style.display = ''; } else { textBox.style.display = 'none'; } - textBox.textContent = pwsp.currSlide?.data.comment; + textBox.textContent = pswp.currSlide?.data.comment; }); }, }); From 51b031d3fc86cb23ccc0a1dbd091cdaf94646785 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 20:30:14 +0100 Subject: [PATCH 235/246] avoid double spaces --- packages/frontend/src/components/MkNoteDetailed.vue | 2 +- packages/frontend/src/components/SkNoteDetailed.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue index e398868d54..33fc6e06d6 100644 --- a/packages/frontend/src/components/MkNoteDetailed.vue +++ b/packages/frontend/src/components/MkNoteDetailed.vue @@ -361,7 +361,7 @@ const pleaseLoginContext = computed(() => ({ const keymap = { 'r': () => reply(), 'e|a|plus': () => react(), - 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); }, + 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); }, 'm': () => showMenu(), 'c': () => { if (!defaultStore.state.showClipButtonInNoteFooter) return; diff --git a/packages/frontend/src/components/SkNoteDetailed.vue b/packages/frontend/src/components/SkNoteDetailed.vue index ed0d689dc9..14b3007a1a 100644 --- a/packages/frontend/src/components/SkNoteDetailed.vue +++ b/packages/frontend/src/components/SkNoteDetailed.vue @@ -370,7 +370,7 @@ const pleaseLoginContext = computed(() => ({ const keymap = { 'r': () => reply(), 'e|a|plus': () => react(), - 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); }, + 'q': () => { if (canRenote.value && !renoted.value && !renoting) renote(defaultStore.state.visibilityOnBoost); }, 'm': () => showMenu(), 'c': () => { if (!defaultStore.state.showClipButtonInNoteFooter) return; From 87deb87456e9bfcfabb280671cad61e875dd6c54 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 20:32:03 +0100 Subject: [PATCH 236/246] put back bits that were lost in the merge --- packages/frontend/src/pages/search.note.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/frontend/src/pages/search.note.vue b/packages/frontend/src/pages/search.note.vue index 3eae84ce64..7f36a2774c 100644 --- a/packages/frontend/src/pages/search.note.vue +++ b/packages/frontend/src/pages/search.note.vue @@ -90,6 +90,10 @@ const props = withDefaults(defineProps<{ host: '', }); +const searchQuery = ref(toRef(props, 'query').value); +const notePagination = ref(); +const user = ref(null); +const hostInput = ref(toRef(props, 'host').value); const router = useRouter(); const key = ref(0); const order = ref(false); From ae12e216ab67c61b6dfb40e6d0d02d3ae533f1d7 Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 20:32:34 +0100 Subject: [PATCH 237/246] remove useless semicolon --- packages/frontend/src/scripts/copy-to-clipboard.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/scripts/copy-to-clipboard.ts b/packages/frontend/src/scripts/copy-to-clipboard.ts index 7e0bb25606..08f5b52dae 100644 --- a/packages/frontend/src/scripts/copy-to-clipboard.ts +++ b/packages/frontend/src/scripts/copy-to-clipboard.ts @@ -8,4 +8,4 @@ */ export function copyToClipboard(input: string | null) { if (input) navigator.clipboard.writeText(input); -}; +} From 652a8c5110c064a2a8d87699dd52b1b8a9d7e5dc Mon Sep 17 00:00:00 2001 From: dakkar Date: Tue, 6 Aug 2024 20:33:25 +0100 Subject: [PATCH 238/246] fix spacing --- packages/frontend/src/ui/_common_/common.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/ui/_common_/common.ts b/packages/frontend/src/ui/_common_/common.ts index f719e73259..17079b3ddc 100644 --- a/packages/frontend/src/ui/_common_/common.ts +++ b/packages/frontend/src/ui/_common_/common.ts @@ -108,7 +108,7 @@ export function openInstanceMenu(ev: MouseEvent) { icon: 'ph-hand-coins ph-bold ph-lg', href: instance.donationUrl, target: '_blank', - }: undefined, (!instance.impressumUrl && !instance.tosUrl && !instance.privacyPolicyUrl && !instance.donationUrl) ? undefined : { type: 'divider' }, { + } : undefined, (!instance.impressumUrl && !instance.tosUrl && !instance.privacyPolicyUrl && !instance.donationUrl) ? undefined : { type: 'divider' }, { type: 'a', text: i18n.ts.document, icon: 'ti ti-bulb', From ee2bc0d3707fade4f25a0f2b273c39c596c1b071 Mon Sep 17 00:00:00 2001 From: dakkar Date: Wed, 14 Aug 2024 11:30:43 +0100 Subject: [PATCH 239/246] move lines to same place as upstream --- packages/frontend/src/pages/search.note.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/frontend/src/pages/search.note.vue b/packages/frontend/src/pages/search.note.vue index 7f36a2774c..66c5c92480 100644 --- a/packages/frontend/src/pages/search.note.vue +++ b/packages/frontend/src/pages/search.note.vue @@ -90,12 +90,12 @@ const props = withDefaults(defineProps<{ host: '', }); +const router = useRouter(); +const key = ref(0); const searchQuery = ref(toRef(props, 'query').value); const notePagination = ref(); const user = ref(null); const hostInput = ref(toRef(props, 'host').value); -const router = useRouter(); -const key = ref(0); const order = ref(false); const filetype = ref(null); From 917eb821e55af9e197153ecd5d547625aa243b76 Mon Sep 17 00:00:00 2001 From: dakkar Date: Wed, 14 Aug 2024 11:31:21 +0100 Subject: [PATCH 240/246] fix indent --- packages/frontend/src/pages/flash/flash.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/src/pages/flash/flash.vue b/packages/frontend/src/pages/flash/flash.vue index b6d6b318c3..dde6660dbc 100644 --- a/packages/frontend/src/pages/flash/flash.vue +++ b/packages/frontend/src/pages/flash/flash.vue @@ -114,7 +114,7 @@ function share(ev: MouseEvent) { action: shareWithNavigator, }] : []), ], ev.currentTarget ?? ev.target); - } +} function copyLink() { if (!flash.value) return; From 5b808a97b2ef4b63033b8d1782bd668787cea21f Mon Sep 17 00:00:00 2001 From: dakkar Date: Wed, 14 Aug 2024 11:50:39 +0100 Subject: [PATCH 241/246] update all our uses of `os.popup` --- packages/frontend/src/components/MkNote.vue | 24 ++++++++++++---- .../frontend/src/components/MkNoteSub.vue | 28 ++++++++++++++----- .../frontend/src/components/MkPostForm.vue | 7 ++++- packages/frontend/src/components/SkNote.vue | 24 ++++++++++++---- .../frontend/src/components/SkNoteSub.vue | 28 ++++++++++++++----- 5 files changed, 84 insertions(+), 27 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 70651507ed..e5710d5513 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -520,7 +520,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } if (!props.mock) { @@ -538,7 +540,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } if (!props.mock) { @@ -578,7 +582,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -600,7 +606,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -638,7 +646,9 @@ function like(): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -717,7 +727,9 @@ function undoRenote(note) : void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } diff --git a/packages/frontend/src/components/MkNoteSub.vue b/packages/frontend/src/components/MkNoteSub.vue index 410b1735d3..9caed62ce2 100644 --- a/packages/frontend/src/components/MkNoteSub.vue +++ b/packages/frontend/src/components/MkNoteSub.vue @@ -207,7 +207,9 @@ function react(viaKeyboard = false): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); @@ -238,7 +240,9 @@ function like(): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -263,7 +267,9 @@ function undoRenote() : void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -291,7 +297,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } misskeyApi('notes/create', { @@ -307,7 +315,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } misskeyApi('notes/create', { @@ -342,7 +352,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -364,7 +376,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue index d778bc046c..2bc607fbb6 100644 --- a/packages/frontend/src/components/MkPostForm.vue +++ b/packages/frontend/src/components/MkPostForm.vue @@ -374,7 +374,12 @@ function watchForDraft() { } function MFMWindow() { - os.popup(defineAsyncComponent(() => import('@/components/SkMfmWindow.vue')), {}, {}, 'closed'); + const { dispose } = os.popup( + defineAsyncComponent(() => import('@/components/SkMfmWindow.vue')), + {}, + { + closed: () => dispose(), + }); } function checkMissingMention() { diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue index ff47170f5d..5f416a639d 100644 --- a/packages/frontend/src/components/SkNote.vue +++ b/packages/frontend/src/components/SkNote.vue @@ -520,7 +520,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } if (!props.mock) { @@ -538,7 +540,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } if (!props.mock) { @@ -578,7 +582,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -600,7 +606,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -638,7 +646,9 @@ function like(): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -717,7 +727,9 @@ function undoRenote(note) : void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } diff --git a/packages/frontend/src/components/SkNoteSub.vue b/packages/frontend/src/components/SkNoteSub.vue index c654163845..c2986b2524 100644 --- a/packages/frontend/src/components/SkNoteSub.vue +++ b/packages/frontend/src/components/SkNoteSub.vue @@ -221,7 +221,9 @@ function react(viaKeyboard = false): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } else { blur(); @@ -252,7 +254,9 @@ function like(): void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -277,7 +281,9 @@ function undoRenote() : void { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } } @@ -305,7 +311,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } misskeyApi('notes/create', { @@ -321,7 +329,9 @@ function renote(visibility: Visibility, localOnly: boolean = false) { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } misskeyApi('notes/create', { @@ -356,7 +366,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); @@ -378,7 +390,9 @@ function quote() { const rect = el.getBoundingClientRect(); const x = rect.left + (el.offsetWidth / 2); const y = rect.top + (el.offsetHeight / 2); - os.popup(MkRippleEffect, { x, y }, {}, 'end'); + const { dispose } = os.popup(MkRippleEffect, { x, y }, { + end: () => dispose(), + }); } os.toast(i18n.ts.quoted); From c2b825b3000e6d953a3ba54910a898986cd72ee9 Mon Sep 17 00:00:00 2001 From: dakkar Date: Wed, 14 Aug 2024 12:28:57 +0100 Subject: [PATCH 242/246] a few more fixes to `os.popup` calls --- packages/frontend/src/components/MkNote.vue | 6 ++++-- packages/frontend/src/components/SkNote.vue | 6 ++++-- packages/frontend/src/scripts/get-note-versions-menu.ts | 5 +++-- packages/frontend/src/widgets/WidgetSearch.vue | 5 +++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index e5710d5513..b33a0ba694 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -455,12 +455,14 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: quoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); if ($i) { diff --git a/packages/frontend/src/components/SkNote.vue b/packages/frontend/src/components/SkNote.vue index 5f416a639d..5bad2a2d13 100644 --- a/packages/frontend/src/components/SkNote.vue +++ b/packages/frontend/src/components/SkNote.vue @@ -455,12 +455,14 @@ if (!props.mock) { if (users.length < 1) return; - os.popup(MkUsersTooltip, { + const { dispose } = os.popup(MkUsersTooltip, { showing, users, count: appearNote.value.renoteCount, targetElement: quoteButton.value, - }, {}, 'closed'); + }, { + closed: () => dispose(), + }); }); if ($i) { diff --git a/packages/frontend/src/scripts/get-note-versions-menu.ts b/packages/frontend/src/scripts/get-note-versions-menu.ts index 9108191d73..345cec9018 100644 --- a/packages/frontend/src/scripts/get-note-versions-menu.ts +++ b/packages/frontend/src/scripts/get-note-versions-menu.ts @@ -27,12 +27,13 @@ export async function getNoteVersionsMenu(props: { const cleanups = [] as (() => void)[]; function openVersion(info): void { - os.popup(defineAsyncComponent(() => import('@/components/SkOldNoteWindow.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/SkOldNoteWindow.vue')), { note: appearNote, oldText: info.text, updatedAt: info.oldDate ? info.oldDate : info.updatedAt, }, { - }, 'closed'); + closed: () => dispose(), + }); } const menu: MenuItem[] = []; diff --git a/packages/frontend/src/widgets/WidgetSearch.vue b/packages/frontend/src/widgets/WidgetSearch.vue index aeb1bc6ee0..294c97e293 100644 --- a/packages/frontend/src/widgets/WidgetSearch.vue +++ b/packages/frontend/src/widgets/WidgetSearch.vue @@ -143,11 +143,12 @@ async function search() { key.value++; - os.popup(defineAsyncComponent(() => import('@/components/SkSearchResultWindow.vue')), { + const { dispose } = os.popup(defineAsyncComponent(() => import('@/components/SkSearchResultWindow.vue')), { noteKey: key.value, notePagination: notePagination.value, }, { - }, 'closed'); + closed: () => dispose(), + }); } defineExpose({ From eb3abf502394df75c0ece5aa801504324c38fcca Mon Sep 17 00:00:00 2001 From: dakkar Date: Fri, 16 Aug 2024 12:29:09 +0100 Subject: [PATCH 243/246] add `warnForMissingAltText` key to translation index --- locales/index.d.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/locales/index.d.ts b/locales/index.d.ts index 435fc9dc7f..0ba2fa96ab 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -2144,6 +2144,10 @@ export interface Locale extends ILocale { * 画像を新しいタブで開く */ "openImageInNewTab": string; + /** + * 代替テキストを入れ忘れたときに警告する + */ + "warnForMissingAltText": string; /** * ダッシュボード */ From b9097d968cf38cd80b63c5ee38ca2beef288b26a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=8B=E3=81=A3=E3=81=93=E3=81=8B=E3=82=8A?= <67428053+kakkokari-gtyih@users.noreply.github.com> Date: Sun, 11 Aug 2024 16:25:57 +0900 Subject: [PATCH 244/246] =?UTF-8?q?fix(backend):=20getApType=E3=81=A7?= =?UTF-8?q?=E3=82=A8=E3=83=A9=E3=83=BC=E3=82=92=E6=8A=95=E3=81=92=E3=81=AA?= =?UTF-8?q?=E3=81=84=E3=82=88=E3=81=86=E3=81=AB=20(misskey=20#14361)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 2 ++ .../core/activitypub/models/ApNoteService.ts | 5 +-- packages/backend/src/core/activitypub/type.ts | 32 +++++++++++++------ 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b996216ac1..a7da62a4ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,6 +118,8 @@ サーバー管理者は各サーバーの必要に応じ`drive_file` `("uri")`に対するインデックスを張りなおすことでより安定しDBの探索が行われる可能性があります。詳細 は [GitHub](https://github.com/misskey-dev/misskey/pull/14323#issuecomment-2257562228)で確認可能です - Fix: 自分のフォロワー限定投稿に対するリプライがホームタイムラインで見えないことが有る問題を修正 - Fix: フォローしていないユーザによるフォロワー限定投稿に対するリプライがソーシャルタイムラインで表示されることがある問題を修正 +- Fix: ActivityPubのエンティティタイプ判定で不明なタイプを受け取った場合でも処理を継続するように + - キュー処理のつまりが改善される可能性があります ### Misskey.js - Feat: `/drive/files/create` のリクエストに対応(`multipart/form-data`に対応) diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts index 0766a8cd85..cc5addcf20 100644 --- a/packages/backend/src/core/activitypub/models/ApNoteService.ts +++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts @@ -83,9 +83,10 @@ export class ApNoteService { @bindThis public validateNote(object: IObject, uri: string): Error | null { const expectHost = this.utilityService.extractDbHost(uri); + const apType = getApType(object); - if (!validPost.includes(getApType(object))) { - return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${getApType(object)}`); + if (apType == null || !validPost.includes(apType)) { + return new IdentifiableError('d450b8a9-48e4-4dab-ae36-f4db763fda7c', `invalid Note: invalid object type ${apType ?? 'undefined'}`); } if (object.id && this.utilityService.extractDbHost(object.id) !== expectHost) { diff --git a/packages/backend/src/core/activitypub/type.ts b/packages/backend/src/core/activitypub/type.ts index 8edd8a1aba..c92e2b805f 100644 --- a/packages/backend/src/core/activitypub/type.ts +++ b/packages/backend/src/core/activitypub/type.ts @@ -60,11 +60,14 @@ export function getApId(value: string | IObject): string { /** * Get ActivityStreams Object type + * + * タイプ判定ができなかった場合に、あえてエラーではなくnullを返すようにしている。 + * 詳細: https://github.com/misskey-dev/misskey/issues/14239 */ -export function getApType(value: IObject): string { +export function getApType(value: IObject): string | null { if (typeof value.type === 'string') return value.type; if (Array.isArray(value.type) && typeof value.type[0] === 'string') return value.type[0]; - throw new Error('cannot detect type'); + return null; } export function getOneApHrefNullable(value: ApObject | undefined): string | undefined { @@ -108,8 +111,10 @@ export interface IOrderedCollection extends IObject { export const validPost = ['Note', 'Question', 'Article', 'Audio', 'Document', 'Image', 'Page', 'Video', 'Event']; -export const isPost = (object: IObject): object is IPost => - validPost.includes(getApType(object)); +export const isPost = (object: IObject): object is IPost => { + const type = getApType(object); + return type != null && validPost.includes(type); +}; export interface IPost extends IObject { type: 'Note' | 'Question' | 'Article' | 'Audio' | 'Document' | 'Image' | 'Page' | 'Video' | 'Event'; @@ -159,8 +164,10 @@ export const isTombstone = (object: IObject): object is ITombstone => export const validActor = ['Person', 'Service', 'Group', 'Organization', 'Application']; -export const isActor = (object: IObject): object is IActor => - validActor.includes(getApType(object)); +export const isActor = (object: IObject): object is IActor => { + const type = getApType(object); + return type != null && validActor.includes(type); +}; export interface IActor extends IObject { type: 'Person' | 'Service' | 'Organization' | 'Group' | 'Application'; @@ -246,12 +253,16 @@ export interface IKey extends IObject { publicKeyPem: string | Buffer; } +export const validDocumentTypes = ['Audio', 'Document', 'Image', 'Page', 'Video']; + export interface IApDocument extends IObject { type: 'Audio' | 'Document' | 'Image' | 'Page' | 'Video'; } -export const isDocument = (object: IObject): object is IApDocument => - ['Audio', 'Document', 'Image', 'Page', 'Video'].includes(getApType(object)); +export const isDocument = (object: IObject): object is IApDocument => { + const type = getApType(object); + return type != null && validDocumentTypes.includes(type); +}; export interface IApImage extends IApDocument { type: 'Image'; @@ -329,7 +340,10 @@ export const isAccept = (object: IObject): object is IAccept => getApType(object export const isReject = (object: IObject): object is IReject => getApType(object) === 'Reject'; export const isAdd = (object: IObject): object is IAdd => getApType(object) === 'Add'; export const isRemove = (object: IObject): object is IRemove => getApType(object) === 'Remove'; -export const isLike = (object: IObject): object is ILike => getApType(object) === 'Like' || getApType(object) === 'EmojiReaction' || getApType(object) === 'EmojiReact'; +export const isLike = (object: IObject): object is ILike => { + const type = getApType(object); + return type != null && ['Like', 'EmojiReaction', 'EmojiReact'].includes(type); +}; export const isAnnounce = (object: IObject): object is IAnnounce => getApType(object) === 'Announce'; export const isBlock = (object: IObject): object is IBlock => getApType(object) === 'Block'; export const isFlag = (object: IObject): object is IFlag => getApType(object) === 'Flag'; From 5358c4f1d02e7045268810054d6e5402ea2b7c3c Mon Sep 17 00:00:00 2001 From: Marie Date: Fri, 16 Aug 2024 13:50:02 +0000 Subject: [PATCH 245/246] chore: fix typo in icon name --- packages/frontend/vite.replaceIcons.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/frontend/vite.replaceIcons.ts b/packages/frontend/vite.replaceIcons.ts index da038e288a..92ac568ef3 100644 --- a/packages/frontend/vite.replaceIcons.ts +++ b/packages/frontend/vite.replaceIcons.ts @@ -170,7 +170,7 @@ export function pluginReplaceIcons() { 'ti ti-bolt': 'ph-lightning ph-bold ph-lg', 'ti ti-bookmark': 'ph-bookmark ph-bold ph-lg', 'ti ti-brand-x': 'ph-twitter-logo ph-bold ph-lg', - 'ti ti-bulb': 'ph-libghtbulb ph-bold ph-lg', + 'ti ti-bulb': 'ph-lightbulb ph-bold ph-lg', 'ti ti-cake': 'ph-cake ph-bold ph-lg', 'ti ti-calendar': 'ph-calendar ph-bold ph-lg', 'ti ti-calendar-time': 'ph-calendar ph-bold ph-lg', From 27935a6061fd9f92303abcc058865a4e9e9e3e47 Mon Sep 17 00:00:00 2001 From: Marie Date: Fri, 16 Aug 2024 15:52:40 +0000 Subject: [PATCH 246/246] upd: apply suggestions on en-US locales Suggestions made by @Leah --- locales/en-US.yml | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 341ee56969..97b3710920 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -192,8 +192,8 @@ addAccount: "Add account" reloadAccountsList: "Reload account list" loginFailed: "Failed to sign in" showOnRemote: "View on remote instance" -continueOnRemote: "リモートで続行" -chooseServerOnMisskeyHub: "Choose a server from the Misskey Hub" +continueOnRemote: "Continue on remote instance" +chooseServerOnMisskeyHub: "Choose a instance from Misskey Hub" specifyServerHost: "Specify a server host directly" inputHostName: "Enter the domain" general: "General" @@ -222,7 +222,7 @@ perDay: "Per Day" stopActivityDelivery: "Stop sending activities" blockThisInstance: "Block this instance" silenceThisInstance: "Silence this instance" -mediaSilenceThisInstance: "Media-silence this server" +mediaSilenceThisInstance: "Silence media from this instance" operations: "Operations" software: "Software" version: "Version" @@ -243,9 +243,9 @@ clearCachedFilesConfirm: "Are you sure that you want to delete all cached remote blockedInstances: "Blocked Instances" blockedInstancesDescription: "List the hostnames of the instances you want to block separated by linebreaks. Listed instances will no longer be able to communicate with this instance." silencedInstances: "Silenced instances" -silencedInstancesDescription: "List the host names of the servers that you want to silence, separated by a new line. All accounts belonging to the listed servers will be treated as silenced, and can only make follow requests, and cannot mention local accounts if not followed. This will not affect the blocked servers." -mediaSilencedInstances: "Media-silenced servers" -mediaSilencedInstancesDescription: "List the host names of the servers that you want to media-silence, separated by a new line. All accounts belonging to the listed servers will be treated as sensitive, and can't use custom emojis. This will not affect the blocked servers." +silencedInstancesDescription: "List the host names of the instances that you want to silence, separated by a new line. All accounts belonging to the listed instances will be treated as silenced, and can only make follow requests, and cannot mention local accounts if not followed. This will not affect the blocked instances." +mediaSilencedInstances: "Media-silenced instances" +mediaSilencedInstancesDescription: "List the host names of the instances that you want to media-silence, separated by a new line. All accounts belonging to the listed instances will be treated as sensitive, and can't use custom emojis. This will not affect the blocked instances." muteAndBlock: "Mutes and Blocks" mutedUsers: "Muted users" blockedUsers: "Blocked users" @@ -501,7 +501,7 @@ noMessagesYet: "No messages yet" newMessageExists: "There are new messages" onlyOneFileCanBeAttached: "You can only attach one file to a message" signinRequired: "Please register or sign in before continuing" -signinOrContinueOnRemote: "To continue, you need to move your server or sign up / log in to this server." +signinOrContinueOnRemote: "To continue, you need to go to your instance to perform this action or sign up / log in to the instance you are trying to interact with." invitations: "Invites" invitationCode: "Invitation code" checking: "Checking..." @@ -1177,8 +1177,8 @@ preventAiLearning: "Reject usage in Machine Learning (Generative AI)" preventAiLearningDescription: "Requests crawlers to not use posted text or image material etc. in machine learning (Predictive / Generative AI) data sets. This is achieved by adding a \"noai\" HTML-Response flag to the respective content. A complete prevention can however not be achieved through this flag, as it may simply be ignored." options: "Options" specifyUser: "Specific user" -lookupConfirm: "Do you want to look up?" -openTagPageConfirm: "Do you want to open a hashtag page?" +lookupConfirm: "Are you sure that you want to look this up?" +openTagPageConfirm: "Are you sure you want to open this hashtags page?" specifyHost: "Specify a host" failedToPreviewUrl: "Could not preview" update: "Update" @@ -1321,7 +1321,7 @@ alwaysConfirmFollow: "Always confirm when following" inquiry: "Contact" tryAgain: "Please try again later" confirmWhenRevealingSensitiveMedia: "Confirm when revealing sensitive media" -sensitiveMediaRevealConfirm: "This might be a sensitive media. Are you sure to reveal?" +sensitiveMediaRevealConfirm: "This media might be sensitive. Are you sure you want to reveal it?" createdLists: "Created lists" createdAntennas: "Created antennas" _delivery: @@ -1778,7 +1778,7 @@ _role: canManageAvatarDecorations: "Manage avatar decorations" driveCapacity: "Drive capacity" alwaysMarkNsfw: "Always mark files as NSFW" - canUpdateBioMedia: "Allow to edit an icon or a banner image" + canUpdateBioMedia: "Allow users to edit their avatar or banner" pinMax: "Maximum number of pinned notes" antennaMax: "Maximum number of antennas" wordMuteMax: "Maximum number of characters allowed in word mutes" @@ -2036,7 +2036,7 @@ _soundSettings: driveFileTypeWarnDescription: "Select an audio file" driveFileDurationWarn: "The audio is too long." driveFileDurationWarnDescription: "Long audio may disrupt using Sharkey. Still continue?" - driveFileError: "The audio couldn't be loaded. Please change the setting." + driveFileError: "The audio couldn't be loaded. Please make sure you selected an audio file." _ago: future: "Future" justNow: "Just now" @@ -2529,8 +2529,8 @@ _abuseReport: mail: "Email" webhook: "Webhook" _captions: - mail: "Send the email to moderators' email addresses when you receive abuse." - webhook: "Send a notification to SystemWebhook when you receive or resolve abuse." + mail: "Send an email to the moderators when an abuse report is received." + webhook: "Send a notification to the SystemWebhook when an abuse report is received or resolved." keywords: "Keywords" notifiedUser: "Users to notify" notifiedWebhook: "Webhook to use"