From aaf3f343ea0a67adca545d78e2568a2896f295c9 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 8 Aug 2025 21:20:23 +0900 Subject: [PATCH 01/42] Update about-misskey.vue --- packages/frontend/src/pages/about-misskey.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue index 057deec4cf..eadc6a2509 100644 --- a/packages/frontend/src/pages/about-misskey.vue +++ b/packages/frontend/src/pages/about-misskey.vue @@ -286,6 +286,9 @@ const patronsWithIcon = [{ }, { name: '井上千二十四', icon: 'https://assets.misskey-hub.net/patrons/193afa1f039b4c339866039c3dcd74bf.jpg', +}, { + name: 'NigN', + icon: 'https://assets.misskey-hub.net/patrons/1ccaef8e73ec4a50b59ff7cd688ceb84.jpg', }]; const patrons = [ @@ -399,6 +402,7 @@ const patrons = [ 'みりめい', '東雲 琥珀', 'ほとラズ', + 'スズカケン', ]; const thereIsTreasure = ref($i && !claimedAchievements.includes('foundTreasure')); From 076a83466e9168929b34932a40b0d8fe42912f17 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 8 Aug 2025 21:26:53 +0900 Subject: [PATCH 02/42] =?UTF-8?q?=F0=9F=8E=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/components/MkEmojiPicker.vue | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue index 654aceb8f5..0248d75f75 100644 --- a/packages/frontend/src/components/MkEmojiPicker.vue +++ b/packages/frontend/src/components/MkEmojiPicker.vue @@ -585,6 +585,14 @@ defineExpose({ grid-template-columns: var(--columns); font-size: 30px; + > .config { + aspect-ratio: 1 / 1; + width: auto; + height: auto; + min-width: 0; + font-size: 14px; + } + > .item { aspect-ratio: 1 / 1; width: auto; From 85e3e496880316c4b55199ea651c210a25420a6e Mon Sep 17 00:00:00 2001 From: tamaina Date: Fri, 8 Aug 2025 21:31:31 +0900 Subject: [PATCH 03/42] fix(backend): Fix and create unit test of CleanRemoteNotesProcessorService (#16368) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * wip * test(backend): CleanRemoteNotesProcessorService (basic) * test(backend): CleanRemoteNotesProcessorService (advanced) * :v: * a * split initiator query * no order by * ??? * old → older --- .../CleanRemoteNotesProcessorService.ts | 171 ++--- .../CleanRemoteNotesProcessorService.ts | 631 ++++++++++++++++++ 2 files changed, 726 insertions(+), 76 deletions(-) create mode 100644 packages/backend/test/unit/queue/processors/CleanRemoteNotesProcessorService.ts diff --git a/packages/backend/src/queue/processors/CleanRemoteNotesProcessorService.ts b/packages/backend/src/queue/processors/CleanRemoteNotesProcessorService.ts index 6c64d6aa39..da3bb804c2 100644 --- a/packages/backend/src/queue/processors/CleanRemoteNotesProcessorService.ts +++ b/packages/backend/src/queue/processors/CleanRemoteNotesProcessorService.ts @@ -5,9 +5,8 @@ import { setTimeout } from 'node:timers/promises'; import { Inject, Injectable } from '@nestjs/common'; -import { And, Brackets, In, IsNull, LessThan, MoreThan, Not } from 'typeorm'; import { DI } from '@/di-symbols.js'; -import type { MiMeta, MiNote, NoteFavoritesRepository, NotesRepository, UserNotePiningsRepository } from '@/models/_.js'; +import type { MiMeta, MiNote, NotesRepository } from '@/models/_.js'; import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; import { IdService } from '@/core/IdService.js'; @@ -25,12 +24,6 @@ export class CleanRemoteNotesProcessorService { @Inject(DI.notesRepository) private notesRepository: NotesRepository, - @Inject(DI.noteFavoritesRepository) - private noteFavoritesRepository: NoteFavoritesRepository, - - @Inject(DI.userNotePiningsRepository) - private userNotePiningsRepository: UserNotePiningsRepository, - private idService: IdService, private queueLoggerService: QueueLoggerService, ) { @@ -61,6 +54,69 @@ export class CleanRemoteNotesProcessorService { const MAX_NOTE_COUNT_PER_QUERY = 50; + //#retion queries + // We use string literals instead of query builder for several reasons: + // - for removeCondition, we need to use it in having clause, which is not supported by Brackets. + // - for recursive part, we need to preserve the order of columns, but typeorm query builder does not guarantee the order of columns in the result query + + // The condition for removing the notes. + // The note must be: + // - old enough (older than the newestLimit) + // - a remote note (userHost is not null). + // - not have clipped + // - not have pinned on the user profile + // - not has been favorite by any user + const removeCondition = 'note.id < :newestLimit' + + ' AND note."clippedCount" = 0' + + ' AND note."userHost" IS NOT NULL' + // using both userId and noteId instead of just noteId to use index on user_note_pining table. + // This is safe because notes are only pinned by the user who created them. + + ' AND NOT EXISTS(SELECT 1 FROM "user_note_pining" WHERE "noteId" = note."id" AND "userId" = note."userId")' + // We cannot use userId trick because users can favorite notes from other users. + + ' AND NOT EXISTS(SELECT 1 FROM "note_favorite" WHERE "noteId" = note."id")' + ; + + // The initiator query contains the oldest ${MAX_NOTE_COUNT_PER_QUERY} remote non-clipped notes + const initiatorQuery = this.notesRepository.createQueryBuilder('note') + .select('note.id', 'id') + .where(removeCondition) + .andWhere('note.id > :cursor') + .orderBy('note.id', 'ASC') + .limit(MAX_NOTE_COUNT_PER_QUERY); + + // The union query queries the related notes and replies related to the initiator query + const unionQuery = ` + SELECT "note"."id", "note"."replyId", "note"."renoteId", rn."initiatorId" + FROM "note" "note" + INNER JOIN "related_notes" "rn" + ON "note"."replyId" = rn.id + OR "note"."renoteId" = rn.id + OR "note"."id" = rn."replyId" + OR "note"."id" = rn."renoteId" + `; + + const selectRelatedNotesFromInitiatorIdsQuery = ` + SELECT "note"."id" AS "id", "note"."replyId" AS "replyId", "note"."renoteId" AS "renoteId", "note"."id" AS "initiatorId" + FROM "note" "note" WHERE "note"."id" IN (:...initiatorIds) + `; + + const recursiveQuery = `(${selectRelatedNotesFromInitiatorIdsQuery}) UNION (${unionQuery})`; + + const removableInitiatorNotesQuery = this.notesRepository.createQueryBuilder('note') + .select('rn."initiatorId"') + .innerJoin('related_notes', 'rn', 'note.id = rn.id') + .groupBy('rn."initiatorId"') + .having(`bool_and(${removeCondition})`); + + const notesQuery = this.notesRepository.createQueryBuilder('note') + .addCommonTableExpression(recursiveQuery, 'related_notes', { recursive: true }) + .select('note.id', 'id') + .addSelect('rn."initiatorId"') + .innerJoin('related_notes', 'rn', 'note.id = rn.id') + .where(`rn."initiatorId" IN (${removableInitiatorNotesQuery.getQuery()})`) + .distinctOn(['note.id']); + //#endregion + const stats = { deletedCount: 0, oldest: null as number | null, @@ -74,77 +130,45 @@ export class CleanRemoteNotesProcessorService { let cursor = '0'; // oldest note ID to start from while (true) { + //#region check time const batchBeginAt = Date.now(); - // We use string literals instead of query builder for several reasons: - // - for removeCondition, we need to use it in having clause, which is not supported by Brackets. - // - for recursive part, we need to preserve the order of columns, but typeorm query builder does not guarantee the order of columns in the result query + const elapsed = batchBeginAt - startAt; - // The condition for removing the notes. - // The note must be: - // - old enough (older than the newestLimit) - // - a remote note (userHost is not null). - // - not have clipped - // - not have pinned on the user profile - // - not has been favorite by any user - const removeCondition = 'note.id < :newestLimit' - + ' AND note."clippedCount" = 0' - + ' AND note."userHost" IS NOT NULL' - // using both userId and noteId instead of just noteId to use index on user_note_pining table. - // This is safe because notes are only pinned by the user who created them. - + ' AND NOT EXISTS(SELECT 1 FROM "user_note_pining" WHERE "noteId" = note."id" AND "userId" = note."userId")' - // We cannot use userId trick because users can favorite notes from other users. - + ' AND NOT EXISTS(SELECT 1 FROM "note_favorite" WHERE "noteId" = note."id")' - ; + if (elapsed >= maxDuration) { + this.logger.info(`Reached maximum duration of ${maxDuration}ms, stopping...`); + job.log('Reached maximum duration, stopping cleaning.'); + job.updateProgress(100); + break; + } - // The initiator query contains the oldest ${MAX_NOTE_COUNT_PER_QUERY} remote non-clipped notes - const initiatorQuery = ` - SELECT "note"."id" AS "id", "note"."replyId" AS "replyId", "note"."renoteId" AS "renoteId", "note"."id" AS "initiatorId" - FROM "note" "note" WHERE ${removeCondition} AND "note"."id" > :cursor ORDER BY "note"."id" ASC LIMIT ${MAX_NOTE_COUNT_PER_QUERY}`; + job.updateProgress((elapsed / maxDuration) * 100); + //#endregion - // The union query queries the related notes and replies related to the initiator query - const unionQuery = ` - SELECT "note"."id", "note"."replyId", "note"."renoteId", rn."initiatorId" - FROM "note" "note" - INNER JOIN "related_notes" "rn" - ON "note"."replyId" = rn.id - OR "note"."renoteId" = rn.id - OR "note"."id" = rn."replyId" - OR "note"."id" = rn."renoteId" - `; - const recursiveQuery = `(${initiatorQuery}) UNION (${unionQuery})`; - - const removableInitiatorNotesQuery = this.notesRepository.createQueryBuilder('note') - .select('rn."initiatorId"') - .innerJoin('related_notes', 'rn', 'note.id = rn.id') - .groupBy('rn."initiatorId"') - .having(`bool_and(${removeCondition})`); - - const notesQuery = this.notesRepository.createQueryBuilder('note') - .addCommonTableExpression(recursiveQuery, 'related_notes', { recursive: true }) - .select('note.id', 'id') - .addSelect('rn."initiatorId"') - .innerJoin('related_notes', 'rn', 'note.id = rn.id') - .where(`rn."initiatorId" IN (${ removableInitiatorNotesQuery.getQuery() })`) - .setParameters({ cursor, newestLimit }); - - const notes: { id: MiNote['id'], initiatorId: MiNote['id'] }[] = await notesQuery.getRawMany(); - - const fetchedCount = notes.length; + // First, we fetch the initiator notes that are older than the newestLimit. + const initiatorNotes: { id: MiNote['id'] }[] = await initiatorQuery.setParameters({ cursor, newestLimit }).getRawMany(); // update the cursor to the newest initiatorId found in the fetched notes. - // We don't use 'id' since the note can be newer than the initiator note. - for (const note of notes) { - if (cursor < note.initiatorId) { - cursor = note.initiatorId; - } + const newCursor = initiatorNotes.reduce((max, note) => note.id > max ? note.id : max, cursor); + + if (initiatorNotes.length === 0 || cursor === newCursor || newCursor >= newestLimit) { + // If no notes were found or the cursor did not change, we can stop. + job.log('No more notes to clean. (no initiator notes found or cursor did not change.)'); + break; } + const notes: { id: MiNote['id'], initiatorId: MiNote['id'] }[] = await notesQuery.setParameters({ + initiatorIds: initiatorNotes.map(note => note.id), + newestLimit, + }).getRawMany(); + + cursor = newCursor; + if (notes.length > 0) { await this.notesRepository.delete(notes.map(note => note.id)); - for (const note of notes) { - const t = this.idService.parse(note.id).date.getTime(); + for (const { id } of notes) { + const t = this.idService.parse(id).date.getTime(); if (stats.oldest === null || t < stats.oldest) { stats.oldest = t; } @@ -156,19 +180,14 @@ export class CleanRemoteNotesProcessorService { stats.deletedCount += notes.length; } - job.log(`Deleted ${notes.length} of ${fetchedCount}; ${Date.now() - batchBeginAt}ms`); + job.log(`Deleted ${notes.length} from ${initiatorNotes.length} initiators; ${Date.now() - batchBeginAt}ms`); - const elapsed = Date.now() - startAt; - - if (elapsed >= maxDuration) { - this.logger.info(`Reached maximum duration of ${maxDuration}ms, stopping...`); - job.log('Reached maximum duration, stopping cleaning.'); - job.updateProgress(100); + if (initiatorNotes.length < MAX_NOTE_COUNT_PER_QUERY) { + // If we fetched less than the maximum, it means there are no more notes to process. + job.log(`No more notes to clean. (fewer than MAX_NOTE_COUNT_PER_QUERY =${MAX_NOTE_COUNT_PER_QUERY}.)`); break; } - job.updateProgress((elapsed / maxDuration) * 100); - await setTimeout(1000 * 5); // Wait a moment to avoid overwhelming the db } diff --git a/packages/backend/test/unit/queue/processors/CleanRemoteNotesProcessorService.ts b/packages/backend/test/unit/queue/processors/CleanRemoteNotesProcessorService.ts new file mode 100644 index 0000000000..15f8eda865 --- /dev/null +++ b/packages/backend/test/unit/queue/processors/CleanRemoteNotesProcessorService.ts @@ -0,0 +1,631 @@ +/* + * 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 ms from 'ms'; +import { + type MiNote, + type MiUser, + type NotesRepository, + type NoteFavoritesRepository, + type UserNotePiningsRepository, + type UsersRepository, + type UserProfilesRepository, + MiMeta, +} from '@/models/_.js'; +import { CleanRemoteNotesProcessorService } from '@/queue/processors/CleanRemoteNotesProcessorService.js'; +import { DI } from '@/di-symbols.js'; +import { IdService } from '@/core/IdService.js'; +import { QueueLoggerService } from '@/queue/QueueLoggerService.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { secureRndstr } from '@/misc/secure-rndstr.js'; + +describe('CleanRemoteNotesProcessorService', () => { + let app: TestingModule; + let service: CleanRemoteNotesProcessorService; + let idService: IdService; + let notesRepository: NotesRepository; + let noteFavoritesRepository: NoteFavoritesRepository; + let userNotePiningsRepository: UserNotePiningsRepository; + let usersRepository: UsersRepository; + let userProfilesRepository: UserProfilesRepository; + + // Local user + let alice: MiUser; + // Remote user 1 + let bob: MiUser; + // Remote user 2 + let carol: MiUser; + + const meta = new MiMeta(); + + // Mock job object + const createMockJob = () => ({ + log: jest.fn(), + updateProgress: jest.fn(), + }); + + async function createUser(data: Partial = {}) { + const id = idService.gen(); + const un = data.username || secureRndstr(16); + const user = await usersRepository + .insert({ + id, + username: un, + usernameLower: un.toLowerCase(), + ...data, + }) + .then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + + await userProfilesRepository.save({ + userId: id, + }); + + return user; + } + + async function createNote(data: Partial, user: MiUser, time?: number): Promise { + const id = idService.gen(time); + const note = await notesRepository + .insert({ + id: id, + text: `note_${id}`, + userId: user.id, + userHost: user.host, + visibility: 'public', + ...data, + }) + .then(x => notesRepository.findOneByOrFail(x.identifiers[0])); + return note; + } + + beforeAll(async () => { + app = await Test + .createTestingModule({ + imports: [ + GlobalModule, + ], + providers: [ + CleanRemoteNotesProcessorService, + IdService, + { + provide: QueueLoggerService, + useFactory: () => ({ + logger: { + createSubLogger: () => ({ + info: jest.fn(), + warn: jest.fn(), + succ: jest.fn(), + }), + }, + }), + }, + ], + }) + .overrideProvider(DI.meta).useFactory({ factory: () => meta }) + .compile(); + + service = app.get(CleanRemoteNotesProcessorService); + idService = app.get(IdService); + notesRepository = app.get(DI.notesRepository); + noteFavoritesRepository = app.get(DI.noteFavoritesRepository); + userNotePiningsRepository = app.get(DI.userNotePiningsRepository); + usersRepository = app.get(DI.usersRepository); + userProfilesRepository = app.get(DI.userProfilesRepository); + + alice = await createUser({ username: 'alice', host: null }); + bob = await createUser({ username: 'bob', host: 'remote1.example.com' }); + carol = await createUser({ username: 'carol', host: 'remote2.example.com' }); + + app.enableShutdownHooks(); + }); + + beforeEach(() => { + // Reset mocks + jest.clearAllMocks(); + + // Set default meta values + meta.enableRemoteNotesCleaning = true; + meta.remoteNotesCleaningMaxProcessingDurationInMinutes = 0.3; + meta.remoteNotesCleaningExpiryDaysForEachNotes = 30; + }, 60 * 1000); + + afterEach(async () => { + // Clean up test data + await Promise.all([ + notesRepository.createQueryBuilder().delete().execute(), + userNotePiningsRepository.createQueryBuilder().delete().execute(), + noteFavoritesRepository.createQueryBuilder().delete().execute(), + ]); + }, 60 * 1000); + + afterAll(async () => { + await app.close(); + }); + + describe('basic', () => { + test('should skip cleaning when enableRemoteNotesCleaning is false', async () => { + meta.enableRemoteNotesCleaning = false; + const job = createMockJob(); + + const result = await service.process(job as any); + + expect(result).toEqual({ + deletedCount: 0, + oldest: null, + newest: null, + skipped: true, + }); + }); + + test('should return success result when enableRemoteNotesCleaning is true and no notes to clean', async () => { + const job = createMockJob(); + + await createNote({}, alice); + const result = await service.process(job as any); + + expect(result).toEqual({ + deletedCount: 0, + oldest: null, + newest: null, + skipped: false, + }); + }, 3000); + + test('should clean remote notes and return stats', async () => { + // Remote notes + const remoteNotes = await Promise.all([ + createNote({}, bob), + createNote({}, carol), + createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000), + createNote({}, carol, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 2000), // Note older than expiry + ]); + + // Local notes + const localNotes = await Promise.all([ + createNote({}, alice), + createNote({}, alice, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000), + ]); + + const job = createMockJob(); + + const result = await service.process(job as any); + + expect(result).toEqual({ + deletedCount: 2, + oldest: expect.any(Number), + newest: expect.any(Number), + skipped: false, + }); + + // Check side-by-side from all notes + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.length).toBe(4); + expect(remainingNotes.some(n => n.id === remoteNotes[0].id)).toBe(true); + expect(remainingNotes.some(n => n.id === remoteNotes[1].id)).toBe(true); + expect(remainingNotes.some(n => n.id === remoteNotes[2].id)).toBe(false); + expect(remainingNotes.some(n => n.id === remoteNotes[3].id)).toBe(false); + expect(remainingNotes.some(n => n.id === localNotes[0].id)).toBe(true); + expect(remainingNotes.some(n => n.id === localNotes[1].id)).toBe(true); + }); + }); + + describe('advanced', () => { + // お気に入り + test('should not delete note that is favorited by any user', async () => { + const job = createMockJob(); + + // Create old remote note that should be deleted + const olderRemoteNote = await createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + + // Favorite the note + await noteFavoritesRepository.save({ + id: idService.gen(), + userId: alice.id, + noteId: olderRemoteNote.id, + }); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); + expect(result.skipped).toBe(false); + + const remainingNote = await notesRepository.findOneBy({ id: olderRemoteNote.id }); + expect(remainingNote).not.toBeNull(); + }); + + // ピン留め + test('should not delete note that is pinned by the user', async () => { + const job = createMockJob(); + + // Create old remote note that should be deleted + const olderRemoteNote = await createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + + // Pin the note by the user who created it + await userNotePiningsRepository.save({ + id: idService.gen(), + userId: bob.id, // Same user as the note creator + noteId: olderRemoteNote.id, + }); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); + expect(result.skipped).toBe(false); + + const remainingNote = await notesRepository.findOneBy({ id: olderRemoteNote.id }); + expect(remainingNote).not.toBeNull(); + }); + + // クリップ + test('should not delete note that is clipped', async () => { + const job = createMockJob(); + + // Create old remote note that is clipped + const clippedNote = await createNote({ + clippedCount: 1, // Clipped + }, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); + expect(result.skipped).toBe(false); + + const remainingNote = await notesRepository.findOneBy({ id: clippedNote.id }); + expect(remainingNote).not.toBeNull(); + }); + + // 古いreply, renoteが含まれている時の挙動 + test('should handle reply/renote relationships correctly', async () => { + const job = createMockJob(); + + // Create old remote notes with reply/renote relationships + const originalNote = await createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + const replyNote = await createNote({ + replyId: originalNote.id, + }, carol, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 2000); + const renoteNote = await createNote({ + renoteId: originalNote.id, + }, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 3000); + + const result = await service.process(job as any); + + // Should delete all three notes as they are all old and remote + expect(result.deletedCount).toBe(3); + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.some(n => n.id === originalNote.id)).toBe(false); + expect(remainingNotes.some(n => n.id === replyNote.id)).toBe(false); + expect(remainingNotes.some(n => n.id === renoteNote.id)).toBe(false); + }); + + // 古いリモートノートに新しいリプライがある時、どちらも削除されない + test('should not delete both old remote note with new reply', async () => { + const job = createMockJob(); + + // Create old remote note that should be deleted + const oldNote = await createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + + // Create a reply note that is newer than the expiry period + const recentReplyNote = await createNote({ + replyId: oldNote.id, + }, carol, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) + 1000); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); // Only the old note should be deleted + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.some(n => n.id === oldNote.id)).toBe(true); + expect(remainingNotes.some(n => n.id === recentReplyNote.id)).toBe(true); // Recent reply note should remain + }); + + // 古いリモートノートに新しいリプライと古いリプライがある時、全て残る + test('should not delete old remote note with new reply and old reply', async () => { + const job = createMockJob(); + + // Create old remote note that should be deleted + const oldNote = await createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + + // Create a reply note that is newer than the expiry period + const recentReplyNote = await createNote({ + replyId: oldNote.id, + }, carol, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) + 1000); + + // Create an old reply note that should be deleted + const oldReplyNote = await createNote({ + replyId: oldNote.id, + }, carol, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 2000); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.some(n => n.id === oldNote.id)).toBe(true); + expect(remainingNotes.some(n => n.id === recentReplyNote.id)).toBe(true); // Recent reply note should remain + expect(remainingNotes.some(n => n.id === oldReplyNote.id)).toBe(true); // Old reply note should be deleted + }); + + // リプライがお気に入りされているとき、どちらも削除されない + test('should not delete reply note that is favorited', async () => { + const job = createMockJob(); + + // Create old remote note that should be deleted + const olderRemoteNote = await createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + + // Create a reply note that is newer than the expiry period + const replyNote = await createNote({ + replyId: olderRemoteNote.id, + }, carol, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 2000); + + // Favorite the reply note + await noteFavoritesRepository.save({ + id: idService.gen(), + userId: alice.id, + noteId: replyNote.id, + }); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); // Only the old note should be deleted + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.some(n => n.id === olderRemoteNote.id)).toBe(true); + expect(remainingNotes.some(n => n.id === replyNote.id)).toBe(true); // Recent reply note should remain + }); + + // リプライがピン留めされているとき、どちらも削除されない + test('should not delete reply note that is pinned', async () => { + const job = createMockJob(); + + // Create old remote note that should be deleted + const olderRemoteNote = await createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + + // Create a reply note that is newer than the expiry period + const replyNote = await createNote({ + replyId: olderRemoteNote.id, + }, carol, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 2000); + + // Pin the reply note + await userNotePiningsRepository.save({ + id: idService.gen(), + userId: carol.id, + noteId: replyNote.id, + }); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); // Only the old note should be deleted + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.some(n => n.id === olderRemoteNote.id)).toBe(true); + expect(remainingNotes.some(n => n.id === replyNote.id)).toBe(true); // Reply note should remain + }); + + // リプライがクリップされているとき、どちらも削除されない + test('should not delete reply note that is clipped', async () => { + const job = createMockJob(); + + // Create old remote note that should be deleted + const olderRemoteNote = await createNote({}, bob, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000); + + // Create a reply note that is old but clipped + const replyNote = await createNote({ + replyId: olderRemoteNote.id, + clippedCount: 1, // Clipped + }, carol, Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 2000); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); // Both notes should be kept because reply is clipped + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.some(n => n.id === olderRemoteNote.id)).toBe(true); + expect(remainingNotes.some(n => n.id === replyNote.id)).toBe(true); + }); + + test('should handle mixed scenarios with multiple conditions', async () => { + const job = createMockJob(); + + // Create various types of notes + const oldTime = Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000; + + // Should be deleted: old remote note with no special conditions + const deletableNote = await createNote({}, bob, oldTime); + + // Should NOT be deleted: old remote note but favorited + const favoritedNote = await createNote({}, carol, oldTime); + await noteFavoritesRepository.save({ + id: idService.gen(), + userId: alice.id, + noteId: favoritedNote.id, + }); + + // Should NOT be deleted: old remote note but pinned + const pinnedNote = await createNote({}, bob, oldTime); + await userNotePiningsRepository.save({ + id: idService.gen(), + userId: bob.id, + noteId: pinnedNote.id, + }); + + // Should NOT be deleted: old remote note but clipped + const clippedNote = await createNote({ + clippedCount: 2, + }, carol, oldTime); + + // Should NOT be deleted: old local note + const localNote = await createNote({}, alice, oldTime); + + // Should NOT be deleted: new remote note + const newerRemoteNote = await createNote({}, bob); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(1); // Only deletableNote should be deleted + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.length).toBe(5); + expect(remainingNotes.some(n => n.id === deletableNote.id)).toBe(false); // Deleted + expect(remainingNotes.some(n => n.id === favoritedNote.id)).toBe(true); // Kept + expect(remainingNotes.some(n => n.id === pinnedNote.id)).toBe(true); // Kept + expect(remainingNotes.some(n => n.id === clippedNote.id)).toBe(true); // Kept + expect(remainingNotes.some(n => n.id === localNote.id)).toBe(true); // Kept + expect(remainingNotes.some(n => n.id === newerRemoteNote.id)).toBe(true); // Kept + }); + + // 大量のノート + test('should handle large number of notes correctly', async () => { + const AMOUNT = 130; + const job = createMockJob(); + + const oldTime = Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000; + const noteIds = []; + for (let i = 0; i < AMOUNT; i++) { + const note = await createNote({}, bob, oldTime - i); + noteIds.push(note.id); + } + + const result = await service.process(job as any); + + // Should delete all notes, but may require multiple batches + expect(result.deletedCount).toBe(AMOUNT); + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.length).toBe(0); + }); + + // 大量のノート + リプライ or リノート + test('should handle large number of notes with replies correctly', async () => { + const AMOUNT = 130; + const job = createMockJob(); + + const oldTime = Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000; + const noteIds = []; + for (let i = 0; i < AMOUNT; i++) { + const note = await createNote({}, bob, oldTime - i - AMOUNT); + noteIds.push(note.id); + if (i % 2 === 0) { + // Create a reply for every second note + await createNote({ replyId: note.id }, carol, oldTime - i); + } else { + // Create a renote for every second note + await createNote({ renoteId: note.id }, bob, oldTime - i); + } + } + + const result = await service.process(job as any); + // Should delete all notes, but may require multiple batches + expect(result.deletedCount).toBe(AMOUNT * 2); + expect(result.skipped).toBe(false); + }); + + // 大量の古いノート + 新しいリプライ or リノート + test('should handle large number of old notes with new replies correctly', async () => { + const AMOUNT = 130; + const job = createMockJob(); + + const oldTime = Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000; + const newTime = Date.now(); + const noteIds = []; + for (let i = 0; i < AMOUNT; i++) { + const note = await createNote({}, bob, oldTime - i); + noteIds.push(note.id); + if (i % 2 === 0) { + // Create a reply for every second note + await createNote({ replyId: note.id }, carol, newTime + i); + } else { + // Create a renote for every second note + await createNote({ renoteId: note.id }, bob, newTime + i); + } + } + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(0); + expect(result.skipped).toBe(false); + }); + + // 大量の残す対象(clippedCount: 1)と大量の削除対象 + test('should handle large number of notes, mixed conditions with clippedCount', async () => { + const AMOUNT_BASE = 70; + const job = createMockJob(); + + const oldTime = Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000; + const noteIds = []; + for (let i = 0; i < AMOUNT_BASE; i++) { + const note = await createNote({ clippedCount: 1 }, bob, oldTime - i - AMOUNT_BASE); + noteIds.push(note.id); + } + for (let i = 0; i < AMOUNT_BASE; i++) { + const note = await createNote({}, carol, oldTime - i); + noteIds.push(note.id); + } + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(AMOUNT_BASE); // Assuming half are deletable + expect(result.skipped).toBe(false); + }); + + // 大量の残す対象(リプライ)と大量の削除対象 + test('should handle large number of notes, mixed conditions with replies', async () => { + const AMOUNT_BASE = 70; + const job = createMockJob(); + const oldTime = Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 1000; + const newTime = Date.now(); + for (let i = 0; i < AMOUNT_BASE; i++) { + // should remain + const note = await createNote({}, carol, oldTime - AMOUNT_BASE - i); + // should remain + await createNote({ replyId: note.id }, bob, newTime + i); + } + + const noteIdsExpectedToBeDeleted = []; + for (let i = 0; i < AMOUNT_BASE; i++) { + // should be deleted + const note = await createNote({}, bob, oldTime - i); + noteIdsExpectedToBeDeleted.push(note.id); + } + + const result = await service.process(job as any); + expect(result.deletedCount).toBe(AMOUNT_BASE); // Assuming all replies are deletable + expect(result.skipped).toBe(false); + + const remainingNotes = await notesRepository.find(); + expect(remainingNotes.length).toBe(AMOUNT_BASE * 2); // Only replies should remain + noteIdsExpectedToBeDeleted.forEach(id => { + expect(remainingNotes.some(n => n.id === id)).toBe(false); // All original notes should be deleted + }); + }); + + test('should update cursor correctly during batch processing', async () => { + const job = createMockJob(); + + // Create notes with specific timing to test cursor behavior + const baseTime = Date.now() - ms(`${meta.remoteNotesCleaningExpiryDaysForEachNotes} days`) - 10000; + + const note1 = await createNote({}, bob, baseTime); + const note2 = await createNote({}, carol, baseTime - 1000); + const note3 = await createNote({}, bob, baseTime - 2000); + + const result = await service.process(job as any); + + expect(result.deletedCount).toBe(3); + expect(result.newest).toBe(idService.parse(note1.id).date.getTime()); + expect(result.oldest).toBe(idService.parse(note3.id).date.getTime()); + expect(result.skipped).toBe(false); + }); + }); +}); From 3da04fcae4edf197827a9ca6e8a2c38eb7990056 Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 8 Aug 2025 21:31:59 +0900 Subject: [PATCH 04/42] New Crowdin updates (#16360) * New translations ja-jp.yml (Catalan) * New translations ja-jp.yml (Chinese Simplified) * New translations ja-jp.yml (Thai) * New translations ja-jp.yml (Italian) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (Turkish) * New translations ja-jp.yml (Turkish) * New translations ja-jp.yml (Turkish) * New translations ja-jp.yml (Korean) * New translations ja-jp.yml (Chinese Traditional) * New translations ja-jp.yml (Spanish) --- locales/ca-ES.yml | 1 + locales/es-ES.yml | 1 + locales/it-IT.yml | 16 +++++++++++++++- locales/ko-KR.yml | 1 + locales/th-TH.yml | 1 + locales/tr-TR.yml | 31 ++++++++++++++++--------------- locales/zh-CN.yml | 1 + locales/zh-TW.yml | 5 +++-- 8 files changed, 39 insertions(+), 18 deletions(-) diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 65ac41edeb..7f26a96d37 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -1465,6 +1465,7 @@ _settings: contentsUpdateFrequency_description2: "Quan s'activa el mode en temps real, el contingut s'actualitza en temps real, independentment d'aquesta configuració." showUrlPreview: "Mostrar vista prèvia d'URL" showAvailableReactionsFirstInNote: "Mostra les reacciones que pots fer servir al damunt" + showPageTabBarBottom: "Mostrar les pestanyes de les línies de temps a la part inferior" _chat: showSenderName: "Mostrar el nom del remitent" sendOnEnter: "Introdueix per enviar" diff --git a/locales/es-ES.yml b/locales/es-ES.yml index 578c550296..20289f605c 100644 --- a/locales/es-ES.yml +++ b/locales/es-ES.yml @@ -1465,6 +1465,7 @@ _settings: contentsUpdateFrequency_description2: "Cuando el modo en tiempo real está activado, el contenido se actualiza en tiempo real independientemente de esta configuración." showUrlPreview: "Mostrar la vista previa de la URL" showAvailableReactionsFirstInNote: "Mostrar las reacciones disponibles en la parte superior." + showPageTabBarBottom: "Mostrar la barra de pestañas de la página en la parte inferior." _chat: showSenderName: "Mostrar el nombre del remitente" sendOnEnter: "Intro para enviar" diff --git a/locales/it-IT.yml b/locales/it-IT.yml index 53d52dbf7e..fb32deec50 100644 --- a/locales/it-IT.yml +++ b/locales/it-IT.yml @@ -1198,7 +1198,7 @@ replies: "Risposte" renotes: "Rinota" loadReplies: "Leggi le risposte" loadConversation: "Leggi la conversazione" -pinnedList: "Elenco in primo piano" +pinnedList: "Lista in primo piano" keepScreenOn: "Mantenere lo schermo acceso" verifiedLink: "Abbiamo confermato la validità di questo collegamento" notifyNotes: "Notifica nuove Note" @@ -1370,6 +1370,10 @@ defaultImageCompressionLevel: "Livello predefinito di compressione immagini" defaultImageCompressionLevel_description: "La compressione diminuisce la qualità dell'immagine, poca compressione mantiene alta qualità delle immagini. Aumentandola, si riducono le dimensioni del file, a discapito della qualità dell'immagine." inMinutes: "min" inDays: "giorni" +safeModeEnabled: "La modalità sicura è attiva" +pluginsAreDisabledBecauseSafeMode: "Tutti i plugin sono disattivati, poiché la modalità sicura è attiva." +customCssIsDisabledBecauseSafeMode: "Il CSS personalizzato non è stato applicato, poiché la modalità sicura è attiva." +themeIsDefaultBecauseSafeMode: "Quando la modalità sicura è attiva, viene utilizzato il tema predefinito. Quando la modalità sicura viene disattivata, il tema torna a essere quello precedente." _order: newest: "Prima i più recenti" oldest: "Meno recenti prima" @@ -1461,6 +1465,7 @@ _settings: contentsUpdateFrequency_description2: "Quando la modalità è in tempo reale, arriveranno a prescindere." showUrlPreview: "Mostra anteprima dell'URL" showAvailableReactionsFirstInNote: "Mostra le reazioni disponibili in alto" + showPageTabBarBottom: "Visualizza le schede della pagina nella parte inferiore" _chat: showSenderName: "Mostra il nome del mittente" sendOnEnter: "Invio spedisce" @@ -1634,6 +1639,10 @@ _serverSettings: fanoutTimelineDbFallback: "Elaborazione dati alternativa" fanoutTimelineDbFallbackDescription: "Attivando l'elaborazione alternativa, verrà interrogato ulteriormente il database se la timeline non è nella cache. \nDisattivando, si può ridurre ulteriormente il carico del server, evitando l'elaborazione alternativa, ma limitando l'intervallo recuperabile delle timeline." reactionsBufferingDescription: "Attivando questa opzione, puoi migliorare significativamente le prestazioni durante la creazione delle reazioni e ridurre il carico sul database. Tuttavia, aumenterà l'impiego di memoria Redis." + remoteNotesCleaning: "Pulizia automatica dei contenuti remoti" + remoteNotesCleaning_description: "Se abilitata, verranno periodicamente rimosse le vecchie Note remote senza relazioni, per ridurre il sovraccarico del sistema." + remoteNotesCleaningMaxProcessingDuration: "Durata massima del processo di pulizia" + remoteNotesCleaningExpiryDaysForEachNotes: "Periodo minimo di conservazione delle note" inquiryUrl: "URL di contatto" inquiryUrlDescription: "Specificare l'URL al modulo di contatto, oppure le informazioni con i dati di contatto dell'amministrazione." openRegistration: "Registrazioni aperte" @@ -1652,6 +1661,8 @@ _serverSettings: userGeneratedContentsVisibilityForVisitor: "Visibilità dei contenuti generati dagli utenti ai non utenti" userGeneratedContentsVisibilityForVisitor_description: "Questa funzionalità è utile per impedire che contenuti remoti inappropriati e difficili da moderare vengano inavvertitamente resi pubblici su Internet tramite il proprio server." userGeneratedContentsVisibilityForVisitor_description2: "Esistono dei rischi nell'esporre incondizionatamente su internet tutto il contenuto del tuo server, incluso il contenuto remoto ricevuto da altri server. In particolare, occorre prestare attenzione, perché le persone non consapevoli della federazione potrebbero erroneamente credere che il contenuto remoto sia stato invece creato all'interno del proprio server." + restartServerSetupWizardConfirm_title: "Vuoi ripetere la procedura guidata di configurazione iniziale del server?" + restartServerSetupWizardConfirm_text: "Verranno ripristinate alcune tue impostazioni personalizzate." _userGeneratedContentsVisibilityForVisitor: all: "Tutto pubblico" localOnly: "Pubblica solo contenuti locali, mantieni privati ​​i contenuti remoti" @@ -3062,6 +3073,7 @@ _bootErrors: otherOption1: "Nelle impostazioni, cancellare le impostazioni del client e svuotare la cache" otherOption2: "Avviare il client predefinito" otherOption3: "Avviare lo strumento di riparazione" + otherOption4: "Avvia Misskey in modalità sicura" _search: searchScopeAll: "Tutte" searchScopeLocal: "Locale" @@ -3098,6 +3110,8 @@ _serverSetupWizard: doYouConnectToFediverse_description1: "Collegandosi a una rete di server distribuiti, denominata Fediverso, potrai scambiare contenuti con altri server, tramite il protocollo di comunicazione ActivityPub." doYouConnectToFediverse_description2: "Connettersi al Fediverso è anche detto \"federazione\"." youCanConfigureMoreFederationSettingsLater: "Puoi svolgere la configurazione avanzata anche dopo. Ad esempio specificando quali server possono federarsi." + remoteContentsCleaning: "Pulizia automatica dei contenuti in arrivo" + remoteContentsCleaning_description: "Con la federazione funzionante, riceverai sempre più contenuti. Abilitando la pulizia automatica, i contenuti non referenziati e obsoleti verranno rimossi automaticamente dai tuoi server, risparmiando spazio di archiviazione." adminInfo: "Informazioni sull'amministratore" adminInfo_description: "Imposta le informazioni dell'amministratore utilizzate per accettare le richieste." adminInfo_mustBeFilled: "Questa operazione è necessaria su un server aperto o se è attiva la federazione." diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index a06e1231b5..4950f78b4d 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -1465,6 +1465,7 @@ _settings: contentsUpdateFrequency_description2: "실시간 모드가 켜져 있을 때는 이 설정과 상관없이 실시간으로 콘텐츠가 업데이트됩니다." showUrlPreview: "URL 미리보기 표시" showAvailableReactionsFirstInNote: "이용 가능한 리액션을 선두로 표시" + showPageTabBarBottom: "페이지의 탭 바를 아래쪽에 표시" _chat: showSenderName: "발신자 이름 표시" sendOnEnter: "엔터로 보내기" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index 110c089b39..519d10daa6 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -1461,6 +1461,7 @@ _settings: contentsUpdateFrequency_description2: "เมื่อโหมดเรียลไทม์เปิดอยู่ เนื้อหาจะอัปเดตแบบเรียลไทม์โดยไม่ขึ้นกับการตั้งค่านี้" showUrlPreview: "แสดงตัวอย่าง URL" showAvailableReactionsFirstInNote: "แสดงรีแอคชั่นที่ใช้ได้ไว้หน้าสุด" + showPageTabBarBottom: "แสดงแท็บบาร์ของเพจที่ด้านล่าง" _chat: showSenderName: "แสดงชื่อผู้ส่ง" sendOnEnter: "กด Enter เพื่อส่ง" diff --git a/locales/tr-TR.yml b/locales/tr-TR.yml index fd4aed4a28..8604cf1af6 100644 --- a/locales/tr-TR.yml +++ b/locales/tr-TR.yml @@ -1,6 +1,6 @@ --- _lang_: "Türkçe" -headlineMisskey: "Notlarla birbirine bağlanan bir ağ" +headlineMisskey: "Notlarla birbirine bağlı bir ağ" introMisskey: "Hoş geldiniz! Misskey, açık kaynaklı, merkezi olmayan bir mikroblog hizmetidir.\nDüşüncelerinizi çevrenizdeki herkesle paylaşmak için “notlar” oluşturun. 📡\n“Tepkiler” ile herkesin notları hakkındaki duygularınızı hızlıca ifade edebilirsiniz. 👍\nYeni bir dünyayı keşfedelim! 🚀" poweredByMisskeyDescription: "{name}, açık kaynak platformu Misskey (kısaca “Misskey örneği” olarak anılır) tarafından desteklenen hizmetlerden biridir." monthAndDay: "{month}/{day}" @@ -23,7 +23,7 @@ renotedBy: "{user} tarafından renot edildi" noNotes: "Not yok" noNotifications: "Bildirim yok" instance: "Sunucu" -settings: "Ayarlarlar" +settings: "Ayarlar" notificationSettings: "Bildirim Ayarları" basicSettings: "Temel Ayarlar" otherSettings: "Diğer Ayarlar" @@ -237,7 +237,7 @@ clearQueueConfirmText: "Kuyrukta kalan teslim edilmemiş notlar birleştirilmeye clearCachedFiles: "Clear cache" clearCachedFilesConfirm: "Tüm önbelleğe alınmış uzak dosyaları silmek istediğinizden emin misiniz?" blockedInstances: "Engellenen Sunucu" -blockedInstancesDescription: "Engellemek istediğiniz örneklerin ana bilgisayar adlarını satır sonlarıyla ayırarak listeleyin. Listelenen örnekler artık bu örnekle iletişim kuramayacaktır." +blockedInstancesDescription: "Engellemek istediğiniz sunucuların ana bilgisayar adlarını satır sonlarıyla ayırarak listeleyin. Listelenen örnekler artık bu örnekle iletişim kuramayacaktır." silencedInstances: "Susturulmuş sunucular" silencedInstancesDescription: "Sessize almak istediğiniz sunucuların ana bilgisayar adlarını yeni bir satırla ayırarak listeleyin. Listelenen sunuculara ait tüm hesaplar sessize alınmış olarak kabul edilecek ve yalnızca takip isteklerinde bulunabilecek, takip edilmedikleri takdirde yerel hesapları etiketleyemeyeceklerdir. Bu, engellenen sunucuları etkilemeyecektir." mediaSilencedInstances: "Medya susturulmuş sunucular" @@ -311,7 +311,7 @@ basicNotesBeforeCreateAccount: "Önemli notlar" termsOfService: "Hizmet Şartları" start: "Başla" home: "Ana sayfa" -remoteUserCaution: "Bu kullanıcı uzak bir örnekten geldiği için, gösterilen bilgiler eksik olabilir." +remoteUserCaution: "Bu kullanıcı uzak bir sunucudan geldiği için, gösterilen bilgiler eksik olabilir." activity: "Etkinlik" images: "Görseller" image: "Görsel" @@ -499,8 +499,8 @@ signinOrContinueOnRemote: "Devam etmek için sunucunuzu taşıyın veya bu sunuc invitations: "Davetler" invitationCode: "Davet kodu" checking: "Kontrol ediliyor..." -available: "Mevcut" -unavailable: "Mevcut değil" +available: "Kullanılabilir" +unavailable: "Kullanılamaz" usernameInvalidFormat: "Büyük ve küçük harfler, rakamlar ve alt çizgi kullanabilirsiniz. (a~z、A~Z、0~9)" tooShort: "Çok kısa" tooLong: "Çok uzun" @@ -619,7 +619,7 @@ unsetUserBannerConfirm: "Banner'ı kaldırmak istediğinizden emin misiniz?" deleteAllFiles: "Tüm dosyaları sil" deleteAllFilesConfirm: "Tüm dosyaları silmek istediğinizden emin misiniz?" removeAllFollowing: "Takip ettiğiniz tüm kullanıcıları takipten çıkarın" -removeAllFollowingDescription: "Bu komutu çalıştırmak, {host} adresindeki tüm hesapları takipten çıkarır. Örneğin, örnek artık mevcut değilse bu komutu çalıştırın." +removeAllFollowingDescription: "Bu komutu çalıştırmak, {host} adresindeki tüm hesapları takipten çıkarır. Örneğin, sunucu artık mevcut değilse bu komutu çalıştırın." userSuspended: "Bu kullanıcı askıya alınmıştır." userSilenced: "Bu kullanıcı susturuluyor." yourAccountSuspendedTitle: "Bu hesap askıya alınmıştır." @@ -1066,19 +1066,19 @@ collapseRenotesDescription: "Daha önce tepki verdiğiniz veya yeniden not aldı internalServerError: "İç Sunucu Hatası" internalServerErrorDescription: "Sunucu beklenmedik bir hatayla karşılaştı." copyErrorInfo: "Hata ayrıntılarını kopyala" -joinThisServer: "Bu örnekte kaydolun" -exploreOtherServers: "Başka bir örnek arayın" +joinThisServer: "Bu sunucuda kaydolun" +exploreOtherServers: "Başka bir sunucu arayın" letsLookAtTimeline: "Timeline'a bir göz atın" disableFederationConfirm: "Federasyonu gerçekten devre dışı bırakmak mı?" disableFederationConfirmWarn: "Federasyondan ayrılsa bile, aksi belirtilmedikçe gönderiler herkese açık olmaya devam edecektir. Genellikle bunu yapmanız gerekmez." disableFederationOk: "Devre Dışı" invitationRequiredToRegister: "Bu etkinlik davetle katılımlıdır. Geçerli bir davet kodu girerek kaydolmanız gerekir." -emailNotSupported: "Bu örnek, E-Posta göndermeyi desteklemiyor." +emailNotSupported: "Bu sunucu, E-Posta göndermeyi desteklemiyor." postToTheChannel: "Kanalına gönder" cannotBeChangedLater: "Bu daha sonra değiştirilemez." reactionAcceptance: "Tepki Kabulü" likeOnly: "Sadece beğeniler" -likeOnlyForRemote: "Tüm (Yalnızca uzak örnekler için beğeniler)" +likeOnlyForRemote: "Tüm (Yalnızca uzak sunucu için beğeniler)" nonSensitiveOnly: "Hassas olmayanlar için" nonSensitiveOnlyForLocalLikeOnlyForRemote: "Yalnızca hassas olmayanlar (Yalnızca uzaktan beğeniler)" rolesAssignedToMe: "Bana atanan roller" @@ -1100,7 +1100,7 @@ retryAllQueuesNow: "Tüm kuyrukları yeniden çalıştırmayı deneyin" retryAllQueuesConfirmTitle: "Gerçekten hepsini tekrar denemek istiyor musunuz?" retryAllQueuesConfirmText: "Bu, sunucu yükünü geçici olarak artıracaktır." enableChartsForRemoteUser: "Uzak kullanıcı veri grafikleri oluşturun" -enableChartsForFederatedInstances: "Uzak örnek veri grafikleri oluşturun" +enableChartsForFederatedInstances: "Uzak sunucu veri grafikleri oluşturun" enableStatsForFederatedInstances: "Uzak sunucu istatistiklerini alın" showClipButtonInNoteFooter: "Not eylem menüsüne “Klip” ekle" reactionsDisplaySize: "Tepki ekran boyutu" @@ -1465,6 +1465,7 @@ _settings: contentsUpdateFrequency_description2: "Gerçek zamanlı mod açık olduğunda, bu ayardan bağımsız olarak içerik gerçek zamanlı olarak güncellenir." showUrlPreview: "URL önizlemesini göster" showAvailableReactionsFirstInNote: "Mevcut tepkileri en üstte göster." + showPageTabBarBottom: "Sayfa sekme çubuğunu aşağıda göster" _chat: showSenderName: "Gönderenin adını göster" sendOnEnter: "Enter tuşuna basarak gönderin" @@ -1911,7 +1912,7 @@ _achievements: _loggedInOnNewYearsDay: title: "Yeni yılınız kutlu olsun!" description: "Yılın ilk gününde oturum açıldı" - flavor: "Bu örnekte bir başka harika yıla" + flavor: "Bu sunucuda bir başka harika yıla" _cookieClicked: title: "Çerezleri tıklayarak oynanan bir oyun" description: "Çerezi tıkladı" @@ -1976,7 +1977,7 @@ _role: ltlAvailable: "Yerel zaman çizelgesini görüntüleyebilir" canPublicNote: "Halka açık notlar gönderebilir" mentionMax: "Bir notta maksimum bahsetme sayısı" - canInvite: "Örnek davet kodları oluşturabilir" + canInvite: "Sunucu davet kodları oluşturabilir" inviteLimit: "Davet sınırı" inviteLimitCycle: "Davet sınırı bekleme süresi" inviteExpirationTime: "Davet süresi dolma aralığı" @@ -2072,7 +2073,7 @@ _ad: adsTooClose: "Mevcut reklam aralığı çok düşük olduğu için kullanıcı deneyimini önemli ölçüde kötüleştirebilir." _forgotPassword: enterEmail: "Kayıt olurken kullandığınız E-Posta adresini girin. Şifrenizi sıfırlayabileceğiniz bir bağlantı bu adrese gönderilecektir." - ifNoEmail: "Kayıt sırasında E-Posta kullanmadıysanız, lütfen bunun yerine örnek yöneticisiyle iletişime geçin." + ifNoEmail: "Kayıt sırasında E-Posta kullanmadıysanız, lütfen bunun yerine sunucu yöneticisiyle iletişime geçin." contactAdmin: "This instance does not support using email addresses, please contact the instance administrator to reset your password instead." _gallery: my: "Benim Galerim" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 8843fc682e..c6a7e15bf5 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -1465,6 +1465,7 @@ _settings: contentsUpdateFrequency_description2: "当实时模式开启时,无论此设置如何,内容都会实时更新。" showUrlPreview: "显示 URL 预览" showAvailableReactionsFirstInNote: "在顶部显示可用的回应" + showPageTabBarBottom: "在下方显示页面标签栏" _chat: showSenderName: "显示发送者的名字" sendOnEnter: "回车键发送" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 00d4a3a9ac..1a2aaa6a12 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -1373,7 +1373,7 @@ inDays: "日" safeModeEnabled: "啟用安全模式" pluginsAreDisabledBecauseSafeMode: "由於啟用安全模式,所有的外掛都被停用。" customCssIsDisabledBecauseSafeMode: "由於啟用安全模式,所有的客製 CSS 都被停用。" -themeIsDefaultBecauseSafeMode: "啟用安全模式時將使用預設主題,關閉安全模式時將恢復預設主題。" +themeIsDefaultBecauseSafeMode: "在安全模式啟用期間將使用預設主題。關閉安全模式後會恢復原本的設定。" _order: newest: "最新的在前" oldest: "最舊的在前" @@ -1465,6 +1465,7 @@ _settings: contentsUpdateFrequency_description2: "當即時模式開啟時,不論此設定為何,內容都會即時更新。" showUrlPreview: "顯示網址預覽" showAvailableReactionsFirstInNote: "將可用的反應顯示在頂部" + showPageTabBarBottom: "在底部顯示頁面的標籤列" _chat: showSenderName: "顯示發送者的名稱" sendOnEnter: "按下 Enter 發送訊息" @@ -1549,7 +1550,7 @@ _initialAccountSetting: theseSettingsCanEditLater: "這裡的設定可以在之後變更。" youCanEditMoreSettingsInSettingsPageLater: "除此之外,還可以在「設定」頁面進行各種設定。之後請確認看看。" followUsers: "為了構築時間軸,試著追隨您感興趣的使用者吧。" - pushNotificationDescription: "啟用推送通知後,就可以在裝置上接收來自{name}的通知了。" + pushNotificationDescription: "啟用推送通知後,就可以在裝置上接收來自 {name} 的通知了。" initialAccountSettingCompleted: "初始設定完成了!" haveFun: "盡情享受{name}吧!" youCanContinueTutorial: "您可以繼續學習如何使用{name}(Misskey),也可以就此打住,立即開始使用。" From 215725a3ace6938d9854d56f394771220c8221b2 Mon Sep 17 00:00:00 2001 From: Sayamame-beans <61457993+Sayamame-beans@users.noreply.github.com> Date: Fri, 8 Aug 2025 21:35:02 +0900 Subject: [PATCH 05/42] =?UTF-8?q?Fix:=20SystemWebhook=E8=A8=AD=E5=AE=9A?= =?UTF-8?q?=E3=81=A7secret=E3=82=92=E7=A9=BA=E3=81=AB=E5=87=BA=E6=9D=A5?= =?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(#16371)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix(backend): allow system-webhook secret to be empty * docs(changelog): update changelog * chore: run build-misskey-js-with-types --- CHANGELOG.md | 1 + .../src/server/api/endpoints/admin/system-webhook/create.ts | 3 +-- .../src/server/api/endpoints/admin/system-webhook/update.ts | 3 +-- packages/misskey-js/src/autogen/types.ts | 6 ++++-- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1dc3e2fe9..d6cb37162b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ ### Server - Enhance: ノートの削除処理の効率化 - Enhance: 全体的なパフォーマンスの向上 +- Fix: SystemWebhook設定でsecretを空に出来ない問題を修正 ## 2025.7.0 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 index 28071e7a33..93d293ed41 100644 --- a/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts @@ -48,8 +48,8 @@ export const paramDef = { }, secret: { type: 'string', - minLength: 1, maxLength: 1024, + default: '', }, }, required: [ @@ -57,7 +57,6 @@ export const paramDef = { 'name', 'on', 'url', - 'secret', ], } as const; 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 index 8d68bb8f87..e021806398 100644 --- a/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts +++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts @@ -52,8 +52,8 @@ export const paramDef = { }, secret: { type: 'string', - minLength: 1, maxLength: 1024, + default: '', }, }, required: [ @@ -62,7 +62,6 @@ export const paramDef = { 'name', 'on', 'url', - 'secret', ], } as const; diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 50a96174c7..f0efd63d3a 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -11887,7 +11887,8 @@ export interface operations { name: string; on: ('abuseReport' | 'abuseReportResolved' | 'userCreated' | 'inactiveModeratorsWarning' | 'inactiveModeratorsInvitationOnlyChanged')[]; url: string; - secret: string; + /** @default */ + secret?: string; }; }; }; @@ -12231,7 +12232,8 @@ export interface operations { name: string; on: ('abuseReport' | 'abuseReportResolved' | 'userCreated' | 'inactiveModeratorsWarning' | 'inactiveModeratorsInvitationOnlyChanged')[]; url: string; - secret: string; + /** @default */ + secret?: string; }; }; }; From 96a165d729e2f72a8ab401983562273ac4415aba Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 8 Aug 2025 12:36:36 +0000 Subject: [PATCH 06/42] Bump version to 2025.8.0-alpha.6 --- 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 4ed9498433..9a9d178413 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2025.8.0-alpha.5", + "version": "2025.8.0-alpha.6", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 0b6ff82c0e..718cefa301 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2025.8.0-alpha.5", + "version": "2025.8.0-alpha.6", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", From e67ff36e57ea1dcb5ee64a732b328c1ba764198e Mon Sep 17 00:00:00 2001 From: syuilo <4439005+syuilo@users.noreply.github.com> Date: Fri, 8 Aug 2025 21:50:05 +0900 Subject: [PATCH 07/42] =?UTF-8?q?enhance(frontend):=20AiScript=E3=81=AEcod?= =?UTF-8?q?e-splitting=E3=81=8C=E6=AD=A3=E3=81=97=E3=81=8F=E8=A1=8C?= =?UTF-8?q?=E3=82=8F=E3=82=8C=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/frontend/src/plugin.ts | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/packages/frontend/src/plugin.ts b/packages/frontend/src/plugin.ts index d47c6cd0e5..632c913ad7 100644 --- a/packages/frontend/src/plugin.ts +++ b/packages/frontend/src/plugin.ts @@ -3,14 +3,13 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { ref, defineAsyncComponent } from 'vue'; -import { Interpreter, Parser, utils, values } from '@syuilo/aiscript'; +import { ref } from 'vue'; import { compareVersions } from 'compare-versions'; import { isSafeMode } from '@@/js/config.js'; import * as Misskey from 'misskey-js'; +import type { Parser, Interpreter, values } from '@syuilo/aiscript'; import type { FormWithDefault } from '@/utility/form.js'; import { genId } from '@/utility/id.js'; -import { aiScriptReadline, createAiScriptEnv } from '@/aiscript/api.js'; import { store } from '@/store.js'; import * as os from '@/os.js'; import { misskeyApi } from '@/utility/misskey-api.js'; @@ -39,7 +38,13 @@ export type AiScriptPluginMeta = { config?: Record; }; -const parser = new Parser(); +let _parser: Parser | null = null; + +async function getParser(): Promise { + const { Parser } = await import('@syuilo/aiscript'); + _parser ??= new Parser(); + return _parser; +} export function isSupportedAiScriptVersion(version: string): boolean { try { @@ -54,6 +59,8 @@ export async function parsePluginMeta(code: string): Promise throw new Error('code is required'); } + const { Interpreter, utils } = await import('@syuilo/aiscript'); + const lv = utils.getLangVersion(code); if (lv == null) { throw new Error('No language version annotation found'); @@ -63,6 +70,7 @@ export async function parsePluginMeta(code: string): Promise let ast; try { + const parser = await getParser(); ast = parser.parse(code); } catch (err) { throw new Error('Aiscript syntax error'); @@ -255,7 +263,10 @@ async function launchPlugin(id: Plugin['installId']): Promise { await authorizePlugin(plugin); - const aiscript = new Interpreter(createPluginEnv({ + const { Interpreter, utils } = await import('@syuilo/aiscript'); + const { aiScriptReadline } = await import('@/aiscript/api.js'); + + const aiscript = new Interpreter(await createPluginEnv({ plugin: plugin, storageKey: 'plugins:' + plugin.installId, }), { @@ -280,6 +291,7 @@ async function launchPlugin(id: Plugin['installId']): Promise { pluginContexts.set(plugin.installId, aiscript); + const parser = await getParser(); aiscript.exec(parser.parse(plugin.src)).then( () => { console.info('Plugin installed:', plugin.name, 'v' + plugin.version); @@ -336,9 +348,12 @@ export function changePluginActive(plugin: Plugin, active: boolean) { } } -function createPluginEnv(opts: { plugin: Plugin; storageKey: string }): Record { +async function createPluginEnv(opts: { plugin: Plugin; storageKey: string }): Promise> { const id = opts.plugin.installId; + const { utils, values } = await import('@syuilo/aiscript'); + const { createAiScriptEnv } = await import('@/aiscript/api.js'); + const config = new Map(); for (const [k, v] of Object.entries(opts.plugin.config ?? {})) { config.set(k, utils.jsToVal(typeof opts.plugin.configData[k] !== 'undefined' ? opts.plugin.configData[k] : v.default)); From 9539995458d8eb58c73bcbd0bf6d6a7c7fcfae0c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 9 Aug 2025 10:34:12 +0900 Subject: [PATCH 08/42] fix(deps): update [root] update dependencies (#16349) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 20 +- pnpm-lock.yaml | 646 +++++++++++++++++++++++++++++-------------------- 2 files changed, 400 insertions(+), 266 deletions(-) diff --git a/package.json b/package.json index 9a9d178413..3195a538bf 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "type": "git", "url": "https://github.com/misskey-dev/misskey.git" }, - "packageManager": "pnpm@10.13.1", + "packageManager": "pnpm@10.14.0", "workspaces": [ "packages/frontend-shared", "packages/frontend", @@ -53,7 +53,7 @@ }, "dependencies": { "cssnano": "7.1.0", - "esbuild": "0.25.6", + "esbuild": "0.25.8", "execa": "9.6.0", "fast-glob": "3.3.3", "glob": "11.0.3", @@ -62,20 +62,20 @@ "postcss": "8.5.6", "tar": "7.4.3", "terser": "5.43.1", - "typescript": "5.8.3" + "typescript": "5.9.2" }, "devDependencies": { "@misskey-dev/eslint-plugin": "2.1.0", - "@types/node": "22.16.4", - "@typescript-eslint/eslint-plugin": "8.37.0", - "@typescript-eslint/parser": "8.37.0", + "@types/node": "22.17.1", + "@typescript-eslint/eslint-plugin": "8.39.0", + "@typescript-eslint/parser": "8.39.0", "cross-env": "7.0.3", - "cypress": "14.5.2", - "eslint": "9.31.0", + "cypress": "14.5.4", + "eslint": "9.33.0", "globals": "16.3.0", "ncp": "2.0.0", - "pnpm": "10.13.1", - "start-server-and-test": "2.0.12" + "pnpm": "10.14.0", + "start-server-and-test": "2.0.13" }, "optionalDependencies": { "@tensorflow/tfjs-core": "4.22.0" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b1d75fe2ca..014d4b0b51 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -22,8 +22,8 @@ importers: specifier: 7.1.0 version: 7.1.0(postcss@8.5.6) esbuild: - specifier: 0.25.6 - version: 0.25.6 + specifier: 0.25.8 + version: 0.25.8 execa: specifier: 9.6.0 version: 9.6.0 @@ -49,30 +49,30 @@ importers: specifier: 5.43.1 version: 5.43.1 typescript: - specifier: 5.8.3 - version: 5.8.3 + specifier: 5.9.2 + version: 5.9.2 devDependencies: '@misskey-dev/eslint-plugin': specifier: 2.1.0 - version: 2.1.0(@eslint/compat@1.1.1)(@stylistic/eslint-plugin@2.13.0(eslint@9.31.0)(typescript@5.8.3))(@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3))(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0))(eslint@9.31.0)(globals@16.3.0) + version: 2.1.0(@eslint/compat@1.1.1)(@stylistic/eslint-plugin@2.13.0(eslint@9.33.0)(typescript@5.9.2))(@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2))(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0))(eslint@9.33.0)(globals@16.3.0) '@types/node': - specifier: 22.16.4 - version: 22.16.4 + specifier: 22.17.1 + version: 22.17.1 '@typescript-eslint/eslint-plugin': - specifier: 8.37.0 - version: 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3) + specifier: 8.39.0 + version: 8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/parser': - specifier: 8.37.0 - version: 8.37.0(eslint@9.31.0)(typescript@5.8.3) + specifier: 8.39.0 + version: 8.39.0(eslint@9.33.0)(typescript@5.9.2) cross-env: specifier: 7.0.3 version: 7.0.3 cypress: - specifier: 14.5.2 - version: 14.5.2 + specifier: 14.5.4 + version: 14.5.4 eslint: - specifier: 9.31.0 - version: 9.31.0 + specifier: 9.33.0 + version: 9.33.0 globals: specifier: 16.3.0 version: 16.3.0 @@ -80,11 +80,11 @@ importers: specifier: 2.0.0 version: 2.0.0 pnpm: - specifier: 10.13.1 - version: 10.13.1 + specifier: 10.14.0 + version: 10.14.0 start-server-and-test: - specifier: 2.0.12 - version: 2.0.12 + specifier: 2.0.13 + version: 2.0.13 optionalDependencies: '@tensorflow/tfjs-core': specifier: 4.22.0 @@ -575,10 +575,10 @@ importers: version: 8.18.1 '@typescript-eslint/eslint-plugin': specifier: 8.34.0 - version: 8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3) + version: 8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.33.0)(typescript@5.8.3))(eslint@9.33.0)(typescript@5.8.3) '@typescript-eslint/parser': specifier: 8.34.0 - version: 8.34.0(eslint@9.31.0)(typescript@5.8.3) + version: 8.34.0(eslint@9.33.0)(typescript@5.8.3) aws-sdk-client-mock: specifier: 4.1.0 version: 4.1.0 @@ -587,7 +587,7 @@ importers: version: 7.0.3 eslint-plugin-import: specifier: 2.31.0 - version: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0) + version: 2.31.0(@typescript-eslint/parser@8.34.0(eslint@9.33.0)(typescript@5.8.3))(eslint@9.33.0) execa: specifier: 8.0.1 version: 8.0.1 @@ -991,10 +991,10 @@ importers: version: 8.18.1 '@typescript-eslint/eslint-plugin': specifier: 8.38.0 - version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/parser': specifier: 8.38.0 - version: 8.38.0(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(eslint@9.33.0)(typescript@5.9.2) '@vitest/coverage-v8': specifier: 3.2.4 version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.17.0)(happy-dom@18.0.1)(jsdom@26.1.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.10.4(@types/node@22.17.0)(typescript@5.9.2))(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)) @@ -1015,10 +1015,10 @@ importers: version: 14.5.3 eslint-plugin-import: specifier: 2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0) + version: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0) eslint-plugin-vue: specifier: 10.4.0 - version: 10.4.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(vue-eslint-parser@10.2.0(eslint@9.31.0)) + version: 10.4.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(vue-eslint-parser@10.2.0(eslint@9.33.0)) fast-glob: specifier: 3.3.3 version: 3.3.3 @@ -1081,7 +1081,7 @@ importers: version: 3.0.5 vue-eslint-parser: specifier: 10.2.0 - version: 10.2.0(eslint@9.31.0) + version: 10.2.0(eslint@9.33.0) vue-tsc: specifier: 3.0.5 version: 3.0.5(typescript@5.9.2) @@ -1106,10 +1106,10 @@ importers: version: 22.17.0 '@typescript-eslint/eslint-plugin': specifier: 8.38.0 - version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/parser': specifier: 8.38.0 - version: 8.38.0(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(eslint@9.33.0)(typescript@5.9.2) rollup: specifier: 4.46.2 version: 4.46.2 @@ -1227,10 +1227,10 @@ importers: version: 8.18.1 '@typescript-eslint/eslint-plugin': specifier: 8.38.0 - version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/parser': specifier: 8.38.0 - version: 8.38.0(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(eslint@9.33.0)(typescript@5.9.2) '@vitest/coverage-v8': specifier: 3.2.4 version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.17.0)(happy-dom@18.0.1)(jsdom@26.1.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.10.4(@types/node@22.17.0)(typescript@5.9.2))(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)) @@ -1245,10 +1245,10 @@ importers: version: 10.0.0 eslint-plugin-import: specifier: 2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0) + version: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0) eslint-plugin-vue: specifier: 10.4.0 - version: 10.4.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(vue-eslint-parser@10.2.0(eslint@9.31.0)) + version: 10.4.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(vue-eslint-parser@10.2.0(eslint@9.33.0)) fast-glob: specifier: 3.3.3 version: 3.3.3 @@ -1284,7 +1284,7 @@ importers: version: 3.0.5 vue-eslint-parser: specifier: 10.2.0 - version: 10.2.0(eslint@9.31.0) + version: 10.2.0(eslint@9.33.0) vue-tsc: specifier: 3.0.5 version: 3.0.5(typescript@5.9.2) @@ -1303,16 +1303,16 @@ importers: version: 22.17.0 '@typescript-eslint/eslint-plugin': specifier: 8.38.0 - version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/parser': specifier: 8.38.0 - version: 8.38.0(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(eslint@9.33.0)(typescript@5.9.2) esbuild: specifier: 0.25.8 version: 0.25.8 eslint-plugin-vue: specifier: 10.4.0 - version: 10.4.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(vue-eslint-parser@10.2.0(eslint@9.31.0)) + version: 10.4.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(vue-eslint-parser@10.2.0(eslint@9.33.0)) nodemon: specifier: 3.1.10 version: 3.1.10 @@ -1321,7 +1321,7 @@ importers: version: 5.9.2 vue-eslint-parser: specifier: 10.2.0 - version: 10.2.0(eslint@9.31.0) + version: 10.2.0(eslint@9.33.0) packages/icons-subsetter: dependencies: @@ -1352,10 +1352,10 @@ importers: version: 1.0.2 '@typescript-eslint/eslint-plugin': specifier: 8.38.0 - version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/parser': specifier: 8.38.0 - version: 8.38.0(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(eslint@9.33.0)(typescript@5.9.2) packages/misskey-bubble-game: dependencies: @@ -1380,10 +1380,10 @@ importers: version: 3.0.8 '@typescript-eslint/eslint-plugin': specifier: 8.38.0 - version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/parser': specifier: 8.38.0 - version: 8.38.0(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(eslint@9.33.0)(typescript@5.9.2) esbuild: specifier: 0.25.8 version: 0.25.8 @@ -1420,10 +1420,10 @@ importers: version: 22.16.4 '@typescript-eslint/eslint-plugin': specifier: 8.37.0 - version: 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3) + version: 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.33.0)(typescript@5.8.3))(eslint@9.33.0)(typescript@5.8.3) '@typescript-eslint/parser': specifier: 8.37.0 - version: 8.37.0(eslint@9.31.0)(typescript@5.8.3) + version: 8.37.0(eslint@9.33.0)(typescript@5.8.3) '@vitest/coverage-v8': specifier: 3.2.4 version: 3.2.4(vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.16.4)(happy-dom@18.0.1)(jsdom@26.1.0(bufferutil@4.0.9)(canvas@3.1.0)(utf-8-validate@6.0.5))(msw@2.10.4(@types/node@22.16.4)(typescript@5.8.3))(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3)) @@ -1465,10 +1465,10 @@ importers: version: 22.16.4 '@typescript-eslint/eslint-plugin': specifier: 8.37.0 - version: 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3) + version: 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.33.0)(typescript@5.8.3))(eslint@9.33.0)(typescript@5.8.3) '@typescript-eslint/parser': specifier: 8.37.0 - version: 8.37.0(eslint@9.31.0)(typescript@5.8.3) + version: 8.37.0(eslint@9.33.0)(typescript@5.8.3) openapi-types: specifier: 12.1.3 version: 12.1.3 @@ -1496,10 +1496,10 @@ importers: version: 22.17.0 '@typescript-eslint/eslint-plugin': specifier: 8.38.0 - version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/parser': specifier: 8.38.0 - version: 8.38.0(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(eslint@9.33.0)(typescript@5.9.2) esbuild: specifier: 0.25.8 version: 0.25.8 @@ -1530,13 +1530,13 @@ importers: devDependencies: '@typescript-eslint/parser': specifier: 8.38.0 - version: 8.38.0(eslint@9.31.0)(typescript@5.9.2) + version: 8.38.0(eslint@9.33.0)(typescript@5.9.2) '@typescript/lib-webworker': specifier: npm:@types/serviceworker@0.0.74 version: '@types/serviceworker@0.0.74' eslint-plugin-import: specifier: 2.32.0 - version: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0) + version: 2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0) nodemon: specifier: 3.1.10 version: 3.1.10 @@ -1988,10 +1988,6 @@ packages: resolution: {integrity: sha512-UJnjoFsmxfKUdNYdWgOB0mWUypuLvAfQPH1+pyvRJs6euowbFkFC6P13w1l8mJyi3vxYMxc9kld5jZEGRQs6bw==} engines: {node: '>=18'} - '@cypress/request@3.0.8': - resolution: {integrity: sha512-h0NFgh1mJmm1nr4jCwkGHwKneVYKghUyWe6TMNrk0B9zsjAJxpg8C4/+BAcmLgCPa1vj1V8rNUaILl+zYRUWBQ==} - engines: {node: '>= 6'} - '@cypress/request@3.0.9': resolution: {integrity: sha512-I3l7FdGRXluAS44/0NguwWlO83J18p0vlr2FYHrJkWdNYhgVoiYo61IXPqaOsL+vNxU1ZqMACzItGK3/KKDsdw==} engines: {node: '>= 6'} @@ -2342,32 +2338,28 @@ packages: resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/config-helpers@0.3.0': - resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==} + '@eslint/config-helpers@0.3.1': + resolution: {integrity: sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/core@0.14.0': - resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - - '@eslint/core@0.15.1': - resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==} + '@eslint/core@0.15.2': + resolution: {integrity: sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.3.1': resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.31.0': - resolution: {integrity: sha512-LOm5OVt7D4qiKCqoiPbA7LWmI+tbw1VbTUowBcUMgQSuM6poJufkFkYDcQpo5KfgD39TnNySV26QjOh7VFpSyw==} + '@eslint/js@9.33.0': + resolution: {integrity: sha512-5K1/mKhWaMfreBGJTwval43JJmkip0RmM+3+IuqupeSKNC/Th2Kc7ucaq5ovTSra/OOKB9c58CGSz3QMVbWt0A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.6': resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/plugin-kit@0.3.1': - resolution: {integrity: sha512-0J+zgWxHN+xXONWIyPWKFMgVuJoZuGiIFu8yxk7RJjxkzpGmyja5wRFqZIVtjDVOQpV+Rw0iOAjYPE2eQyjr0w==} + '@eslint/plugin-kit@0.3.5': + resolution: {integrity: sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@fastify/accept-negotiator@2.0.0': @@ -4633,6 +4625,9 @@ packages: '@types/node@22.17.0': resolution: {integrity: sha512-bbAKTCqX5aNVryi7qXVMi+OkB3w/OyblodicMbvE38blyAz7GxXf6XYhklokijuPwwVg9sDLKRxt0ZHXQwZVfQ==} + '@types/node@22.17.1': + resolution: {integrity: sha512-y3tBaz+rjspDTylNjAX37jEC3TETEFGNJL6uQDxwF9/8GLLIjW1rvVHlynyuUKMnMr1Roq8jOv3vkopBjC4/VA==} + '@types/nodemailer@6.4.17': resolution: {integrity: sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==} @@ -4822,6 +4817,14 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/eslint-plugin@8.39.0': + resolution: {integrity: sha512-bhEz6OZeUR+O/6yx9Jk6ohX6H9JSFTaiY0v9/PuKT3oGK0rn0jNplLmyFUGV+a9gfYnVNwGDwS/UkLIuXNb2Rw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.39.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/parser@8.34.0': resolution: {integrity: sha512-vxXJV1hVFx3IXz/oy2sICsJukaBrtDEQSBiV48/YIV5KWjX1dO+bcIr/kCPrW6weKXvsaGKFNlwH0v2eYdRRbA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4843,6 +4846,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/parser@8.39.0': + resolution: {integrity: sha512-g3WpVQHngx0aLXn6kfIYCZxM6rRJlWzEkVpqEFLT3SgEDsp9cpCbxxgwnE504q4H+ruSDh/VGS6nqZIDynP+vg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.34.0': resolution: {integrity: sha512-iEgDALRf970/B2YExmtPMPF54NenZUf4xpL3wsCRx/lgjz6ul/l13R81ozP/ZNuXfnLCS+oPmG7JIxfdNYKELw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4861,6 +4871,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/project-service@8.39.0': + resolution: {integrity: sha512-CTzJqaSq30V/Z2Og9jogzZt8lJRR5TKlAdXmWgdu4hgcC9Kww5flQ+xFvMxIBWVNdxJO7OifgdOK4PokMIWPew==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/scope-manager@8.34.0': resolution: {integrity: sha512-9Ac0X8WiLykl0aj1oYQNcLZjHgBojT6cW68yAgZ19letYu+Hxd0rE0veI1XznSSst1X5lwnxhPbVdwjDRIomRw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4873,6 +4889,10 @@ packages: resolution: {integrity: sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.39.0': + resolution: {integrity: sha512-8QOzff9UKxOh6npZQ/4FQu4mjdOCGSdO3p44ww0hk8Vu+IGbg0tB/H1LcTARRDzGCC8pDGbh2rissBuuoPgH8A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.34.0': resolution: {integrity: sha512-+W9VYHKFIzA5cBeooqQxqNriAP0QeQ7xTiDuIOr71hzgffm3EL2hxwWBIIj4GuofIbKxGNarpKqIq6Q6YrShOA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4891,6 +4911,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/tsconfig-utils@8.39.0': + resolution: {integrity: sha512-Fd3/QjmFV2sKmvv3Mrj8r6N8CryYiCS8Wdb/6/rgOXAWGcFuc+VkQuG28uk/4kVNVZBQuuDHEDUpo/pQ32zsIQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/type-utils@8.34.0': resolution: {integrity: sha512-n7zSmOcUVhcRYC75W2pnPpbO1iwhJY3NLoHEtbJwJSNlVAZuwqu05zY3f3s2SDWWDSo9FdN5szqc73DCtDObAg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4912,6 +4938,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/type-utils@8.39.0': + resolution: {integrity: sha512-6B3z0c1DXVT2vYA9+z9axjtc09rqKUPRmijD5m9iv8iQpHBRYRMBcgxSiKTZKm6FwWw1/cI4v6em35OsKCiN5Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/types@8.34.0': resolution: {integrity: sha512-9V24k/paICYPniajHfJ4cuAWETnt7Ssy+R0Rbcqo5sSFr3QEZ/8TSoUi9XeXVBGXCaLtwTOKSLGcInCAvyZeMA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4924,6 +4957,10 @@ packages: resolution: {integrity: sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.39.0': + resolution: {integrity: sha512-ArDdaOllnCj3yn/lzKn9s0pBQYmmyme/v1HbGIGB0GB/knFI3fWMHloC+oYTJW46tVbYnGKTMDK4ah1sC2v0Kg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.34.0': resolution: {integrity: sha512-rOi4KZxI7E0+BMqG7emPSK1bB4RICCpF7QD3KCLXn9ZvWoESsOMlHyZPAHyG04ujVplPaHbmEvs34m+wjgtVtg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4942,6 +4979,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/typescript-estree@8.39.0': + resolution: {integrity: sha512-ndWdiflRMvfIgQRpckQQLiB5qAKQ7w++V4LlCHwp62eym1HLB/kw7D9f2e8ytONls/jt89TEasgvb+VwnRprsw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/utils@8.34.0': resolution: {integrity: sha512-8L4tWatGchV9A1cKbjaavS6mwYwp39jql8xUmIIKJdm+qiaeHy5KMKlBrf30akXAWBzn2SqKsNOtSENWUwg7XQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4963,6 +5006,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <5.9.0' + '@typescript-eslint/utils@8.39.0': + resolution: {integrity: sha512-4GVSvNA0Vx1Ktwvf4sFE+exxJ3QGUorQG1/A5mRfRNZtkBT2xrA/BCO2H0eALx/PnvCS6/vmYwRdDA41EoffkQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/visitor-keys@8.34.0': resolution: {integrity: sha512-qHV7pW7E85A0x6qyrFn+O+q1k1p3tQCsqIZ1KZ5ESLXY57aTvUd3/a4rdPTeXisvhXn2VQG0VSKUqs8KHF2zcA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -4975,6 +5025,10 @@ packages: resolution: {integrity: sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.39.0': + resolution: {integrity: sha512-ldgiJ+VAhQCfIjeOgu8Kj5nSxds0ktPOSO9p4+0VDH2R2pLvQraaM5Oen2d7NxzMCm+Sn/vJT+mv2H5u6b/3fA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.2.0': resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} @@ -5465,6 +5519,9 @@ packages: axios@0.24.0: resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==} + axios@1.11.0: + resolution: {integrity: sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==} + axios@1.8.4: resolution: {integrity: sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==} @@ -6106,13 +6163,13 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - cypress@14.5.2: - resolution: {integrity: sha512-O4E4CEBqDHLDrJD/dfStHPcM+8qFgVVZ89Li7xDU0yL/JxO/V0PEcfF2I8aGa7uA2MGNLkNUAnghPM83UcHOJw==} + cypress@14.5.3: + resolution: {integrity: sha512-syLwKjDeMg77FRRx68bytLdlqHXDT4yBVh0/PPkcgesChYDjUZbwxLqMXuryYKzAyJsPsQHUDW1YU74/IYEUIA==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - cypress@14.5.3: - resolution: {integrity: sha512-syLwKjDeMg77FRRx68bytLdlqHXDT4yBVh0/PPkcgesChYDjUZbwxLqMXuryYKzAyJsPsQHUDW1YU74/IYEUIA==} + cypress@14.5.4: + resolution: {integrity: sha512-0Dhm4qc9VatOcI1GiFGVt8osgpPdqJLHzRwcAB5MSD/CAAts3oybvPUPawHyvJZUd8osADqZe/xzMsZ8sDTjXw==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true @@ -6608,8 +6665,8 @@ packages: resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.31.0: - resolution: {integrity: sha512-QldCVh/ztyKJJZLr4jXNUByx3gR+TDYZCRXEktiZoUR3PGy4qCmSbkxcIle8GEwGpb5JBZazlaJ/CxLidXdEbQ==} + eslint@9.33.0: + resolution: {integrity: sha512-TS9bTNIryDzStCpJN93aC5VRSW3uTx9sClUn4B87pwiCaJh220otoI0X8mJKr+VcPtniMdN8GKjlwgWGUv5ZKA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true peerDependencies: @@ -9075,8 +9132,8 @@ packages: resolution: {integrity: sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==} engines: {node: '>=10.13.0'} - pnpm@10.13.1: - resolution: {integrity: sha512-N+vxpcejDV+r4MXfRO6NpMllygxa89urKMOhaBtwolYhjQXIHJwNz3Z+9rhVHrW5YAQrntQwDFkkIzY3fgHPrQ==} + pnpm@10.14.0: + resolution: {integrity: sha512-rSenlkG0nD5IGhaoBbqnGBegS74Go40X5g4urug/ahRsamiBJfV5LkjdW6MOfaUqXNpMOZK5zPMz+c4iOvhHSA==} engines: {node: '>=18.12'} hasBin: true @@ -10123,6 +10180,11 @@ packages: engines: {node: '>=16'} hasBin: true + start-server-and-test@2.0.13: + resolution: {integrity: sha512-G42GCIUjBv/nDoK+QsO+nBdX2Cg3DSAKhSic2DN0GLlK4Q+63TkOeN1cV9PHZKnVOzDKGNVZGCREjpvAIAOdiQ==} + engines: {node: '>=16'} + hasBin: true + statuses@2.0.1: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} @@ -11039,6 +11101,11 @@ packages: engines: {node: '>=12.0.0'} hasBin: true + wait-on@8.0.4: + resolution: {integrity: sha512-8f9LugAGo4PSc0aLbpKVCVtzayd36sSCp4WLpVngkYq6PK87H79zt77/tlCU6eKCLqR46iFvcl0PU5f+DmtkwA==} + engines: {node: '>=12.0.0'} + hasBin: true + walker@1.0.8: resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} @@ -12125,27 +12192,6 @@ snapshots: '@csstools/css-tokenizer@3.0.3': {} - '@cypress/request@3.0.8': - dependencies: - aws-sign2: 0.7.0 - aws4: 1.12.0 - caseless: 0.12.0 - combined-stream: 1.0.8 - extend: 3.0.2 - forever-agent: 0.6.1 - form-data: 4.0.3 - http-signature: 1.4.0 - is-typedarray: 1.0.0 - isstream: 0.1.2 - json-stringify-safe: 5.0.1 - mime-types: 2.1.35 - performance-now: 2.1.0 - qs: 6.14.0 - safe-buffer: 5.2.1 - tough-cookie: 5.1.2 - tunnel-agent: 0.6.0 - uuid: 8.3.2 - '@cypress/request@3.0.9': dependencies: aws-sign2: 0.7.0 @@ -12352,9 +12398,9 @@ snapshots: '@esbuild/win32-x64@0.25.8': optional: true - '@eslint-community/eslint-utils@4.7.0(eslint@9.31.0)': + '@eslint-community/eslint-utils@4.7.0(eslint@9.33.0)': dependencies: - eslint: 9.31.0 + eslint: 9.33.0 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -12369,13 +12415,9 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/config-helpers@0.3.0': {} + '@eslint/config-helpers@0.3.1': {} - '@eslint/core@0.14.0': - dependencies: - '@types/json-schema': 7.0.15 - - '@eslint/core@0.15.1': + '@eslint/core@0.15.2': dependencies: '@types/json-schema': 7.0.15 @@ -12393,13 +12435,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.31.0': {} + '@eslint/js@9.33.0': {} '@eslint/object-schema@2.1.6': {} - '@eslint/plugin-kit@0.3.1': + '@eslint/plugin-kit@0.3.5': dependencies: - '@eslint/core': 0.14.0 + '@eslint/core': 0.15.2 levn: 0.4.1 '@fastify/accept-negotiator@2.0.0': {} @@ -12787,7 +12829,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -12800,14 +12842,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 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@22.17.0) + jest-config: 29.7.0(@types/node@22.17.1) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -12836,7 +12878,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -12854,7 +12896,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.17.0 + '@types/node': 22.17.1 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -12876,7 +12918,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.29 - '@types/node': 22.17.0 + '@types/node': 22.17.1 chalk: 4.1.2 collect-v8-coverage: 1.0.1 exit: 0.1.2 @@ -12946,7 +12988,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.17.0 + '@types/node': 22.17.1 '@types/yargs': 17.0.33 chalk: 4.1.2 @@ -13051,14 +13093,14 @@ snapshots: '@misskey-dev/browser-image-resizer@2024.1.0': {} - '@misskey-dev/eslint-plugin@2.1.0(@eslint/compat@1.1.1)(@stylistic/eslint-plugin@2.13.0(eslint@9.31.0)(typescript@5.8.3))(@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3))(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0))(eslint@9.31.0)(globals@16.3.0)': + '@misskey-dev/eslint-plugin@2.1.0(@eslint/compat@1.1.1)(@stylistic/eslint-plugin@2.13.0(eslint@9.33.0)(typescript@5.9.2))(@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2))(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0))(eslint@9.33.0)(globals@16.3.0)': dependencies: '@eslint/compat': 1.1.1 - '@stylistic/eslint-plugin': 2.13.0(eslint@9.31.0)(typescript@5.8.3) - '@typescript-eslint/eslint-plugin': 8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3) - '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) - eslint: 9.31.0 - eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0) + '@stylistic/eslint-plugin': 2.13.0(eslint@9.33.0)(typescript@5.9.2) + '@typescript-eslint/eslint-plugin': 8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.39.0(eslint@9.33.0)(typescript@5.9.2) + eslint: 9.33.0 + eslint-plugin-import: 2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0) globals: 16.3.0 '@misskey-dev/sharp-read-bmp@1.2.0': @@ -14668,10 +14710,10 @@ snapshots: vue: 3.5.18(typescript@5.9.2) vue-component-type-helpers: 3.0.5 - '@stylistic/eslint-plugin@2.13.0(eslint@9.31.0)(typescript@5.8.3)': + '@stylistic/eslint-plugin@2.13.0(eslint@9.33.0)(typescript@5.9.2)': dependencies: - '@typescript-eslint/utils': 8.38.0(eslint@9.31.0)(typescript@5.8.3) - eslint: 9.31.0 + '@typescript-eslint/utils': 8.38.0(eslint@9.33.0)(typescript@5.9.2) + eslint: 9.33.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 estraverse: 5.3.0 @@ -14998,7 +15040,7 @@ snapshots: '@types/connect@3.4.36': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 '@types/content-disposition@0.5.9': {} @@ -15027,7 +15069,7 @@ snapshots: '@types/express-serve-static-core@4.17.33': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 '@types/qs': 6.9.7 '@types/range-parser': 1.2.4 @@ -15044,7 +15086,7 @@ snapshots: '@types/graceful-fs@4.1.6': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 '@types/hammerjs@2.0.46': {} @@ -15117,11 +15159,11 @@ snapshots: '@types/mysql@2.15.26': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 '@types/node-fetch@2.6.11': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 form-data: 4.0.3 '@types/node@20.19.9': @@ -15140,6 +15182,10 @@ snapshots: dependencies: undici-types: 6.21.0 + '@types/node@22.17.1': + dependencies: + undici-types: 6.21.0 + '@types/nodemailer@6.4.17': dependencies: '@types/node': 22.16.4 @@ -15175,7 +15221,7 @@ snapshots: '@types/pg@8.6.1': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 pg-protocol: 1.10.0 pg-types: 2.2.0 @@ -15205,7 +15251,7 @@ snapshots: '@types/readdir-glob@1.1.1': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 '@types/redis-info@3.0.3': {} @@ -15228,7 +15274,7 @@ snapshots: '@types/serve-static@1.15.1': dependencies: '@types/mime': 3.0.1 - '@types/node': 22.17.0 + '@types/node': 22.17.1 '@types/serviceworker@0.0.74': {} @@ -15254,7 +15300,7 @@ snapshots: dependencies: '@types/cookiejar': 2.1.5 '@types/methods': 1.1.4 - '@types/node': 22.17.0 + '@types/node': 22.17.1 form-data: 4.0.3 '@types/supertest@6.0.3': @@ -15264,7 +15310,7 @@ snapshots: '@types/tedious@4.0.14': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 '@types/throttle-debounce@5.0.2': {} @@ -15304,18 +15350,18 @@ snapshots: '@types/yauzl@2.10.0': dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 optional: true - '@typescript-eslint/eslint-plugin@8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.34.0(@typescript-eslint/parser@8.34.0(eslint@9.33.0)(typescript@5.8.3))(eslint@9.33.0)(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.34.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.34.0(eslint@9.33.0)(typescript@5.8.3) '@typescript-eslint/scope-manager': 8.34.0 - '@typescript-eslint/type-utils': 8.34.0(eslint@9.31.0)(typescript@5.8.3) - '@typescript-eslint/utils': 8.34.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/type-utils': 8.34.0(eslint@9.33.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.34.0(eslint@9.33.0)(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.34.0 - eslint: 9.31.0 + eslint: 9.33.0 graphemer: 1.4.0 ignore: 7.0.4 natural-compare: 1.4.0 @@ -15324,15 +15370,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.37.0(@typescript-eslint/parser@8.37.0(eslint@9.33.0)(typescript@5.8.3))(eslint@9.33.0)(typescript@5.8.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.37.0(eslint@9.33.0)(typescript@5.8.3) '@typescript-eslint/scope-manager': 8.37.0 - '@typescript-eslint/type-utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) - '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/type-utils': 8.37.0(eslint@9.33.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.33.0)(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.37.0 - eslint: 9.31.0 + eslint: 9.33.0 graphemer: 1.4.0 ignore: 7.0.4 natural-compare: 1.4.0 @@ -15341,15 +15387,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(typescript@5.9.2)': + '@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.38.0(eslint@9.31.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.38.0(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/scope-manager': 8.38.0 - '@typescript-eslint/type-utils': 8.38.0(eslint@9.31.0)(typescript@5.9.2) - '@typescript-eslint/utils': 8.38.0(eslint@9.31.0)(typescript@5.9.2) + '@typescript-eslint/type-utils': 8.38.0(eslint@9.33.0)(typescript@5.9.2) + '@typescript-eslint/utils': 8.38.0(eslint@9.33.0)(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.38.0 - eslint: 9.31.0 + eslint: 9.33.0 graphemer: 1.4.0 ignore: 7.0.4 natural-compare: 1.4.0 @@ -15358,38 +15404,67 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.34.0(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/eslint-plugin@8.39.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(typescript@5.9.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.39.0(eslint@9.33.0)(typescript@5.9.2) + '@typescript-eslint/scope-manager': 8.39.0 + '@typescript-eslint/type-utils': 8.39.0(eslint@9.33.0)(typescript@5.9.2) + '@typescript-eslint/utils': 8.39.0(eslint@9.33.0)(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.39.0 + eslint: 9.33.0 + graphemer: 1.4.0 + ignore: 7.0.4 + natural-compare: 1.4.0 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.34.0(eslint@9.33.0)(typescript@5.8.3)': dependencies: '@typescript-eslint/scope-manager': 8.34.0 '@typescript-eslint/types': 8.34.0 '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.34.0 debug: 4.4.1(supports-color@10.0.0) - eslint: 9.31.0 + eslint: 9.33.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/parser@8.37.0(eslint@9.33.0)(typescript@5.8.3)': dependencies: '@typescript-eslint/scope-manager': 8.37.0 '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.37.0 debug: 4.4.1(supports-color@10.0.0) - eslint: 9.31.0 + eslint: 9.33.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2)': + '@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2)': dependencies: '@typescript-eslint/scope-manager': 8.38.0 '@typescript-eslint/types': 8.38.0 '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2) '@typescript-eslint/visitor-keys': 8.38.0 debug: 4.4.1(supports-color@10.0.0) - eslint: 9.31.0 + eslint: 9.33.0 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.39.0 + '@typescript-eslint/types': 8.39.0 + '@typescript-eslint/typescript-estree': 8.39.0(typescript@5.9.2) + '@typescript-eslint/visitor-keys': 8.39.0 + debug: 4.4.1(supports-color@10.0.0) + eslint: 9.33.0 typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -15412,15 +15487,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/project-service@8.38.0(typescript@5.8.3)': - dependencies: - '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.8.3) - '@typescript-eslint/types': 8.38.0 - debug: 4.4.1(supports-color@10.0.0) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/project-service@8.38.0(typescript@5.9.2)': dependencies: '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.9.2) @@ -15430,6 +15496,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.39.0(typescript@5.9.2)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.39.0(typescript@5.9.2) + '@typescript-eslint/types': 8.39.0 + debug: 4.4.1(supports-color@10.0.0) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@8.34.0': dependencies: '@typescript-eslint/types': 8.34.0 @@ -15445,6 +15520,11 @@ snapshots: '@typescript-eslint/types': 8.38.0 '@typescript-eslint/visitor-keys': 8.38.0 + '@typescript-eslint/scope-manager@8.39.0': + dependencies: + '@typescript-eslint/types': 8.39.0 + '@typescript-eslint/visitor-keys': 8.39.0 + '@typescript-eslint/tsconfig-utils@8.34.0(typescript@5.8.3)': dependencies: typescript: 5.8.3 @@ -15461,36 +15541,52 @@ snapshots: dependencies: typescript: 5.9.2 - '@typescript-eslint/type-utils@8.34.0(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/tsconfig-utils@8.39.0(typescript@5.9.2)': + dependencies: + typescript: 5.9.2 + + '@typescript-eslint/type-utils@8.34.0(eslint@9.33.0)(typescript@5.8.3)': dependencies: '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.8.3) - '@typescript-eslint/utils': 8.34.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.34.0(eslint@9.33.0)(typescript@5.8.3) debug: 4.4.1(supports-color@10.0.0) - eslint: 9.31.0 + eslint: 9.33.0 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@8.37.0(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/type-utils@8.37.0(eslint@9.33.0)(typescript@5.8.3)': dependencies: '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) - '@typescript-eslint/utils': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/utils': 8.37.0(eslint@9.33.0)(typescript@5.8.3) debug: 4.4.1(supports-color@10.0.0) - eslint: 9.31.0 + eslint: 9.33.0 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@8.38.0(eslint@9.31.0)(typescript@5.9.2)': + '@typescript-eslint/type-utils@8.38.0(eslint@9.33.0)(typescript@5.9.2)': dependencies: '@typescript-eslint/types': 8.38.0 '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2) - '@typescript-eslint/utils': 8.38.0(eslint@9.31.0)(typescript@5.9.2) + '@typescript-eslint/utils': 8.38.0(eslint@9.33.0)(typescript@5.9.2) debug: 4.4.1(supports-color@10.0.0) - eslint: 9.31.0 + eslint: 9.33.0 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/type-utils@8.39.0(eslint@9.33.0)(typescript@5.9.2)': + dependencies: + '@typescript-eslint/types': 8.39.0 + '@typescript-eslint/typescript-estree': 8.39.0(typescript@5.9.2) + '@typescript-eslint/utils': 8.39.0(eslint@9.33.0)(typescript@5.9.2) + debug: 4.4.1(supports-color@10.0.0) + eslint: 9.33.0 ts-api-utils: 2.1.0(typescript@5.9.2) typescript: 5.9.2 transitivePeerDependencies: @@ -15502,6 +15598,8 @@ snapshots: '@typescript-eslint/types@8.38.0': {} + '@typescript-eslint/types@8.39.0': {} + '@typescript-eslint/typescript-estree@8.34.0(typescript@5.8.3)': dependencies: '@typescript-eslint/project-service': 8.34.0(typescript@5.8.3) @@ -15534,22 +15632,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@8.38.0(typescript@5.8.3)': - dependencies: - '@typescript-eslint/project-service': 8.38.0(typescript@5.8.3) - '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.8.3) - '@typescript-eslint/types': 8.38.0 - '@typescript-eslint/visitor-keys': 8.38.0 - debug: 4.4.1(supports-color@10.0.0) - fast-glob: 3.3.3 - is-glob: 4.0.3 - minimatch: 9.0.5 - semver: 7.7.2 - ts-api-utils: 2.1.0(typescript@5.8.3) - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - '@typescript-eslint/typescript-estree@8.38.0(typescript@5.9.2)': dependencies: '@typescript-eslint/project-service': 8.38.0(typescript@5.9.2) @@ -15566,46 +15648,62 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.34.0(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/typescript-estree@8.39.0(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + '@typescript-eslint/project-service': 8.39.0(typescript@5.9.2) + '@typescript-eslint/tsconfig-utils': 8.39.0(typescript@5.9.2) + '@typescript-eslint/types': 8.39.0 + '@typescript-eslint/visitor-keys': 8.39.0 + debug: 4.4.1(supports-color@10.0.0) + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.2 + ts-api-utils: 2.1.0(typescript@5.9.2) + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.34.0(eslint@9.33.0)(typescript@5.8.3)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0) '@typescript-eslint/scope-manager': 8.34.0 '@typescript-eslint/types': 8.34.0 '@typescript-eslint/typescript-estree': 8.34.0(typescript@5.8.3) - eslint: 9.31.0 + eslint: 9.33.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.37.0(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/utils@8.37.0(eslint@9.33.0)(typescript@5.8.3)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0) '@typescript-eslint/scope-manager': 8.37.0 '@typescript-eslint/types': 8.37.0 '@typescript-eslint/typescript-estree': 8.37.0(typescript@5.8.3) - eslint: 9.31.0 + eslint: 9.33.0 typescript: 5.8.3 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.38.0(eslint@9.31.0)(typescript@5.8.3)': + '@typescript-eslint/utils@8.38.0(eslint@9.33.0)(typescript@5.9.2)': dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) - '@typescript-eslint/scope-manager': 8.38.0 - '@typescript-eslint/types': 8.38.0 - '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.8.3) - eslint: 9.31.0 - typescript: 5.8.3 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@8.38.0(eslint@9.31.0)(typescript@5.9.2)': - dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0) '@typescript-eslint/scope-manager': 8.38.0 '@typescript-eslint/types': 8.38.0 '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2) - eslint: 9.31.0 + eslint: 9.33.0 + typescript: 5.9.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@8.39.0(eslint@9.33.0)(typescript@5.9.2)': + dependencies: + '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0) + '@typescript-eslint/scope-manager': 8.39.0 + '@typescript-eslint/types': 8.39.0 + '@typescript-eslint/typescript-estree': 8.39.0(typescript@5.9.2) + eslint: 9.33.0 typescript: 5.9.2 transitivePeerDependencies: - supports-color @@ -15625,6 +15723,11 @@ snapshots: '@typescript-eslint/types': 8.38.0 eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.39.0': + dependencies: + '@typescript-eslint/types': 8.39.0 + eslint-visitor-keys: 4.2.1 + '@ungap/structured-clone@1.2.0': {} '@vitejs/plugin-vue@6.0.1(vite@7.0.6(@types/node@22.17.0)(sass@1.89.2)(terser@5.43.1)(tsx@4.20.3))(vue@3.5.18(typescript@5.9.2))': @@ -16281,6 +16384,14 @@ snapshots: transitivePeerDependencies: - debug + axios@1.11.0(debug@4.4.1): + dependencies: + follow-redirects: 1.15.9(debug@4.4.1) + form-data: 4.0.4 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + axios@1.8.4(debug@4.4.1): dependencies: follow-redirects: 1.15.9(debug@4.4.1) @@ -17018,9 +17129,9 @@ snapshots: csstype@3.1.3: {} - cypress@14.5.2: + cypress@14.5.3: dependencies: - '@cypress/request': 3.0.8 + '@cypress/request': 3.0.9 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) '@types/sinonjs__fake-timers': 8.1.1 '@types/sizzle': 2.3.3 @@ -17065,7 +17176,7 @@ snapshots: untildify: 4.0.0 yauzl: 2.10.0 - cypress@14.5.3: + cypress@14.5.4: dependencies: '@cypress/request': 3.0.9 '@cypress/xvfb': 1.2.4(supports-color@8.1.1) @@ -17642,37 +17753,37 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.34.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.31.0): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.34.0(eslint@9.33.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.33.0): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: - '@typescript-eslint/parser': 8.34.0(eslint@9.31.0)(typescript@5.8.3) - eslint: 9.31.0 + '@typescript-eslint/parser': 8.34.0(eslint@9.33.0)(typescript@5.8.3) + eslint: 9.33.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.31.0): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.33.0): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: - '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) - eslint: 9.31.0 + '@typescript-eslint/parser': 8.38.0(eslint@9.33.0)(typescript@5.9.2) + eslint: 9.33.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-module-utils@2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.31.0): + eslint-module-utils@2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.33.0): dependencies: debug: 3.2.7(supports-color@8.1.1) optionalDependencies: - '@typescript-eslint/parser': 8.38.0(eslint@9.31.0)(typescript@5.9.2) - eslint: 9.31.0 + '@typescript-eslint/parser': 8.39.0(eslint@9.33.0)(typescript@5.9.2) + eslint: 9.33.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0): + eslint-plugin-import@2.31.0(@typescript-eslint/parser@8.34.0(eslint@9.33.0)(typescript@5.8.3))(eslint@9.33.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -17681,9 +17792,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 - eslint: 9.31.0 + eslint: 9.33.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.34.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.31.0) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.34.0(eslint@9.33.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.33.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -17695,13 +17806,13 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.34.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.34.0(eslint@9.33.0)(typescript@5.8.3) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint@9.31.0): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -17710,9 +17821,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 - eslint: 9.31.0 + eslint: 9.33.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.37.0(eslint@9.31.0)(typescript@5.8.3))(eslint-import-resolver-node@0.3.9)(eslint@9.31.0) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.33.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -17724,13 +17835,13 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.37.0(eslint@9.31.0)(typescript@5.8.3) + '@typescript-eslint/parser': 8.38.0(eslint@9.33.0)(typescript@5.9.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0): + eslint-plugin-import@2.32.0(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0): dependencies: '@rtsao/scc': 1.1.0 array-includes: 3.1.9 @@ -17739,9 +17850,9 @@ snapshots: array.prototype.flatmap: 1.3.3 debug: 3.2.7(supports-color@8.1.1) doctrine: 2.1.0 - eslint: 9.31.0 + eslint: 9.33.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.31.0) + eslint-module-utils: 2.12.1(@typescript-eslint/parser@8.39.0(eslint@9.33.0)(typescript@5.9.2))(eslint-import-resolver-node@0.3.9)(eslint@9.33.0) hasown: 2.0.2 is-core-module: 2.16.1 is-glob: 4.0.3 @@ -17753,24 +17864,24 @@ snapshots: string.prototype.trimend: 1.0.9 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 8.38.0(eslint@9.31.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.39.0(eslint@9.33.0)(typescript@5.9.2) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-vue@10.4.0(@typescript-eslint/parser@8.38.0(eslint@9.31.0)(typescript@5.9.2))(eslint@9.31.0)(vue-eslint-parser@10.2.0(eslint@9.31.0)): + eslint-plugin-vue@10.4.0(@typescript-eslint/parser@8.38.0(eslint@9.33.0)(typescript@5.9.2))(eslint@9.33.0)(vue-eslint-parser@10.2.0(eslint@9.33.0)): dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) - eslint: 9.31.0 + '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0) + eslint: 9.33.0 natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 semver: 7.7.2 - vue-eslint-parser: 10.2.0(eslint@9.31.0) + vue-eslint-parser: 10.2.0(eslint@9.33.0) xml-name-validator: 4.0.0 optionalDependencies: - '@typescript-eslint/parser': 8.38.0(eslint@9.31.0)(typescript@5.9.2) + '@typescript-eslint/parser': 8.38.0(eslint@9.33.0)(typescript@5.9.2) eslint-rule-docs@1.1.235: {} @@ -17783,16 +17894,16 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.31.0: + eslint@9.33.0: dependencies: - '@eslint-community/eslint-utils': 4.7.0(eslint@9.31.0) + '@eslint-community/eslint-utils': 4.7.0(eslint@9.33.0) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 - '@eslint/config-helpers': 0.3.0 - '@eslint/core': 0.15.1 + '@eslint/config-helpers': 0.3.1 + '@eslint/core': 0.15.2 '@eslint/eslintrc': 3.3.1 - '@eslint/js': 9.31.0 - '@eslint/plugin-kit': 0.3.1 + '@eslint/js': 9.33.0 + '@eslint/plugin-kit': 0.3.5 '@humanfs/node': 0.16.6 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.4.2 @@ -19050,7 +19161,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 chalk: 4.1.2 co: 4.6.0 dedent: 1.6.0 @@ -19119,7 +19230,7 @@ snapshots: - babel-plugin-macros - supports-color - jest-config@29.7.0(@types/node@22.17.0): + jest-config@29.7.0(@types/node@22.17.1): dependencies: '@babel/core': 7.24.7 '@jest/test-sequencer': 29.7.0 @@ -19144,7 +19255,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -19173,7 +19284,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -19183,7 +19294,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.6 - '@types/node': 22.17.0 + '@types/node': 22.17.1 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -19257,7 +19368,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -19285,7 +19396,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 chalk: 4.1.2 cjs-module-lexer: 1.2.2 collect-v8-coverage: 1.0.1 @@ -19331,7 +19442,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 chalk: 4.1.2 ci-info: 3.7.1 graceful-fs: 4.2.11 @@ -19350,7 +19461,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.17.0 + '@types/node': 22.17.1 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -19359,7 +19470,7 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 22.17.0 + '@types/node': 22.17.1 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -20840,7 +20951,7 @@ snapshots: pngjs@5.0.0: {} - pnpm@10.13.1: {} + pnpm@10.14.0: {} polished@4.2.2: dependencies: @@ -22045,6 +22156,19 @@ snapshots: transitivePeerDependencies: - supports-color + start-server-and-test@2.0.13: + dependencies: + arg: 5.0.2 + bluebird: 3.7.2 + check-more-types: 2.24.0 + debug: 4.4.1(supports-color@10.0.0) + execa: 5.1.1 + lazy-ass: 1.6.0 + ps-tree: 1.2.0 + wait-on: 8.0.4(debug@4.4.1) + transitivePeerDependencies: + - supports-color + statuses@2.0.1: {} std-env@3.9.0: {} @@ -23006,10 +23130,10 @@ snapshots: vue: 3.5.18(typescript@5.9.2) vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.5.18(typescript@5.9.2)) - vue-eslint-parser@10.2.0(eslint@9.31.0): + vue-eslint-parser@10.2.0(eslint@9.33.0): dependencies: debug: 4.4.1(supports-color@10.0.0) - eslint: 9.31.0 + eslint: 9.33.0 eslint-scope: 8.4.0 eslint-visitor-keys: 4.2.1 espree: 10.4.0 @@ -23072,6 +23196,16 @@ snapshots: transitivePeerDependencies: - debug + wait-on@8.0.4(debug@4.4.1): + dependencies: + axios: 1.11.0(debug@4.4.1) + joi: 17.13.3 + lodash: 4.17.21 + minimist: 1.2.8 + rxjs: 7.8.2 + transitivePeerDependencies: + - debug + walker@1.0.8: dependencies: makeerror: 1.0.12 From 8bd84a0ec431cf0c520b578d60504df5a4794d16 Mon Sep 17 00:00:00 2001 From: anatawa12 Date: Sat, 9 Aug 2025 10:43:07 +0900 Subject: [PATCH 09/42] =?UTF-8?q?fix:=20=E3=82=AB=E3=83=A9=E3=83=A0?= =?UTF-8?q?=E3=81=AE=E5=90=8D=E5=89=8D=E3=81=8C=E6=AD=A3=E3=81=97=E3=81=8F?= =?UTF-8?q?=E3=83=AA=E3=82=B9=E3=83=88/=E3=83=81=E3=83=A3=E3=83=B3?= =?UTF-8?q?=E3=83=8D=E3=83=AB=E3=81=AE=E5=90=8D=E5=89=8D=E3=81=AB=E3=81=AA?= =?UTF-8?q?=E3=82=89=E3=81=AA=E3=81=84=E5=95=8F=E9=A1=8C=20(#15987)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: カラムの名前が正しくリスト/チャンネルの名前にならない問題 * changelog Fix: カラムの名前が正しくリスト/チャンネルの名前にならない問題を修正 * reduce requests to retrieve timeline name --- CHANGELOG.md | 1 + packages/frontend/src/deck.ts | 2 ++ packages/frontend/src/ui/deck/antenna-column.vue | 13 +++++-------- packages/frontend/src/ui/deck/channel-column.vue | 12 ++++-------- packages/frontend/src/ui/deck/list-column.vue | 13 +++++-------- .../frontend/src/ui/deck/role-timeline-column.vue | 12 ++++-------- 6 files changed, 21 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6cb37162b..98ec6f2a85 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ - Fix: 一部の設定検索結果が存在しないパスになる問題を修正 (Cherry-picked from https://activitypub.software/TransFem-org/Sharkey/-/merge_requests/1171) - Fix: テーマエディタが動作しない問題を修正 +- Fix: カラムの名前が正しくリスト/チャンネルの名前にならない問題を修正 ### Server - Enhance: ノートの削除処理の効率化 diff --git a/packages/frontend/src/deck.ts b/packages/frontend/src/deck.ts index 73a3cecd3b..208adae8fe 100644 --- a/packages/frontend/src/deck.ts +++ b/packages/frontend/src/deck.ts @@ -62,6 +62,8 @@ export type Column = { withSensitive?: boolean; onlyFiles?: boolean; soundSetting?: SoundStore; + // The cache for the name of the antenna, channel, list, or role + timelineNameCache?: string; }; const _currentProfile = prefer.s['deck.profiles'].find(p => p.name === prefer.s['deck.profile']); diff --git a/packages/frontend/src/ui/deck/antenna-column.vue b/packages/frontend/src/ui/deck/antenna-column.vue index 8de894ee88..0042882728 100644 --- a/packages/frontend/src/ui/deck/antenna-column.vue +++ b/packages/frontend/src/ui/deck/antenna-column.vue @@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only