Merge branch 'develop' into reimplement-rate-limit

This commit is contained in:
anatawa12 2024-06-22 13:39:48 +09:00 committed by GitHub
commit e77bcf5ff7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
73 changed files with 378 additions and 387 deletions

View File

@ -37,7 +37,7 @@ jobs:
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push by digest - name: Build and push by digest
id: build id: build
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
context: . context: .
push: true push: true

View File

@ -48,7 +48,7 @@ jobs:
password: ${{ secrets.DOCKER_PASSWORD }} password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and Push to Docker Hub - name: Build and Push to Docker Hub
id: build id: build
uses: docker/build-push-action@v5 uses: docker/build-push-action@v6
with: with:
context: . context: .
push: true push: true

View File

@ -13,10 +13,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
DOCKER_CONTENT_TRUST: 1 DOCKER_CONTENT_TRUST: 1
DOCKLE_VERSION: 0.4.14
steps: steps:
- uses: actions/checkout@v4.1.1 - uses: actions/checkout@v4.1.1
- run: | - name: Download and install dockle v${{ env.DOCKLE_VERSION }}
curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v0.4.10/dockle_0.4.10_Linux-64bit.deb" run: |
curl -L -o dockle.deb "https://github.com/goodwithtech/dockle/releases/download/v${DOCKLE_VERSION}/dockle_${DOCKLE_VERSION}_Linux-64bit.deb"
sudo dpkg -i dockle.deb sudo dpkg -i dockle.deb
- run: | - run: |
cp .config/docker_example.env .config/docker.env cp .config/docker_example.env .config/docker.env

View File

@ -5,12 +5,17 @@
- Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正 - Fix: 配信停止したインスタンス一覧が見れなくなる問題を修正
### Client ### Client
- `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正 - Fix: `/about#federation` ページなどで各インスタンスのチャートが表示されなくなっていた問題を修正
- Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968) - Fix: ユーザーページの追加情報のラベルを投稿者のサーバーの絵文字で表示する (#13968)
- Fix: リバーシの対局を正しく共有できないことがある問題を修正
### Server ### Server
- チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正 - チャート生成時にinstance.suspentionStateに置き換えられたinstance.isSuspendedが参照されてしまう問題を修正
- Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949) - Feat: レートリミット制限に引っかかったときに`Retry-After`ヘッダーを返すように (#13949)
- Fix: ユーザーのフィードページのMFMをHTMLに展開するように (#14006)
- Fix: アンテナ・クリップ・リスト・ウェブフックがロールポリシーの上限より一つ多く作れてしまうのを修正 (#14036)
- Fix: notRespondingSinceが実装される前に不通になったインスタンスが自動的に配信停止にならない (#14059)
- Fix: FTT有効時、タイムライン用エンドポイントで`sinceId`にキャッシュ内最古のものより古いものを指定した場合に正しく結果が返ってこない問題を修正
## 2024.5.0 ## 2024.5.0

View File

@ -56,7 +56,7 @@
"postcss": "8.4.38", "postcss": "8.4.38",
"tar": "6.2.1", "tar": "6.2.1",
"terser": "5.30.3", "terser": "5.30.3",
"typescript": "5.4.5", "typescript": "5.5.2",
"esbuild": "0.20.2", "esbuild": "0.20.2",
"glob": "10.3.12" "glob": "10.3.12"
}, },

View File

@ -177,7 +177,7 @@
"tsc-alias": "1.8.8", "tsc-alias": "1.8.8",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",
"typeorm": "0.3.20", "typeorm": "0.3.20",
"typescript": "5.4.5", "typescript": "5.5.2",
"ulid": "2.3.0", "ulid": "2.3.0",
"vary": "1.1.2", "vary": "1.1.2",
"web-push": "3.6.7", "web-push": "3.6.7",

View File

@ -10,7 +10,6 @@ import sanitizeHtml from 'sanitize-html';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { GlobalEvents, GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEvents, GlobalEventService } from '@/core/GlobalEventService.js';
import { isNotNull } from '@/misc/is-not-null.js';
import type { import type {
AbuseReportNotificationRecipientRepository, AbuseReportNotificationRecipientRepository,
MiAbuseReportNotificationRecipient, MiAbuseReportNotificationRecipient,
@ -91,7 +90,7 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
const recipientEMailAddresses = await this.fetchEMailRecipients().then(it => it const recipientEMailAddresses = await this.fetchEMailRecipients().then(it => it
.filter(it => it.isActive && it.userProfile?.emailVerified) .filter(it => it.isActive && it.userProfile?.emailVerified)
.map(it => it.userProfile?.email) .map(it => it.userProfile?.email)
.filter(isNotNull), .filter(x => x != null),
); );
// 送信先の鮮度を保つため、毎回取得する // 送信先の鮮度を保つため、毎回取得する
@ -138,7 +137,7 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
.then(it => it .then(it => it
.filter(it => it.isActive && it.systemWebhookId && it.method === 'webhook') .filter(it => it.isActive && it.systemWebhookId && it.method === 'webhook')
.map(it => it.systemWebhookId) .map(it => it.systemWebhookId)
.filter(isNotNull)); .filter(x => x != null));
for (const webhookId of recipientWebhookIds) { for (const webhookId of recipientWebhookIds) {
await Promise.all( await Promise.all(
abuseReports.map(it => { abuseReports.map(it => {
@ -340,7 +339,7 @@ export class AbuseReportNotificationService implements OnApplicationShutdown {
@bindThis @bindThis
private async removeUnauthorizedRecipientUsers(recipients: MiAbuseReportNotificationRecipient[]): Promise<MiAbuseReportNotificationRecipient[]> { private async removeUnauthorizedRecipientUsers(recipients: MiAbuseReportNotificationRecipient[]): Promise<MiAbuseReportNotificationRecipient[]> {
const userRecipients = recipients.filter(it => it.userId !== null); const userRecipients = recipients.filter(it => it.userId !== null);
const recipientUserIds = new Set(userRecipients.map(it => it.userId).filter(isNotNull)); const recipientUserIds = new Set(userRecipients.map(it => it.userId).filter(x => x != null));
if (recipientUserIds.size <= 0) { if (recipientUserIds.size <= 0) {
// ユーザが通知先として設定されていない場合、この関数での処理を行うべきレコードが無い // ユーザが通知先として設定されていない場合、この関数での処理を行うべきレコードが無い
return recipients; return recipients;

View File

@ -41,7 +41,7 @@ export class ClipService {
const currentCount = await this.clipsRepository.countBy({ const currentCount = await this.clipsRepository.countBy({
userId: me.id, userId: me.id,
}); });
if (currentCount > (await this.roleService.getUserPolicies(me.id)).clipLimit) { if (currentCount >= (await this.roleService.getUserPolicies(me.id)).clipLimit) {
throw new ClipService.TooManyClipsError(); throw new ClipService.TooManyClipsError();
} }
@ -102,7 +102,7 @@ export class ClipService {
const currentCount = await this.clipNotesRepository.countBy({ const currentCount = await this.clipNotesRepository.countBy({
clipId: clip.id, clipId: clip.id,
}); });
if (currentCount > (await this.roleService.getUserPolicies(me.id)).noteEachClipsLimit) { if (currentCount >= (await this.roleService.getUserPolicies(me.id)).noteEachClipsLimit) {
throw new ClipService.TooManyClipNotesError(); throw new ClipService.TooManyClipNotesError();
} }

View File

@ -55,9 +55,6 @@ export class FanoutTimelineEndpointService {
@bindThis @bindThis
private async getMiNotes(ps: TimelineOptions): Promise<MiNote[]> { private async getMiNotes(ps: TimelineOptions): Promise<MiNote[]> {
let noteIds: string[];
let shouldFallbackToDb = false;
// 呼び出し元と以下の処理をシンプルにするためにdbFallbackを置き換える // 呼び出し元と以下の処理をシンプルにするためにdbFallbackを置き換える
if (!ps.useDbFallback) ps.dbFallback = () => Promise.resolve([]); if (!ps.useDbFallback) ps.dbFallback = () => Promise.resolve([]);
@ -67,12 +64,11 @@ export class FanoutTimelineEndpointService {
const redisResult = await this.fanoutTimelineService.getMulti(ps.redisTimelines, ps.untilId, ps.sinceId); const redisResult = await this.fanoutTimelineService.getMulti(ps.redisTimelines, ps.untilId, ps.sinceId);
// TODO: いい感じにgetMulti内でソート済だからuniqするときにredisResultが全てソート済なのを利用して再ソートを避けたい // TODO: いい感じにgetMulti内でソート済だからuniqするときにredisResultが全てソート済なのを利用して再ソートを避けたい
const redisResultIds = Array.from(new Set(redisResult.flat(1))); const redisResultIds = Array.from(new Set(redisResult.flat(1))).sort(idCompare);
redisResultIds.sort(idCompare); let noteIds = redisResultIds.slice(0, ps.limit);
noteIds = redisResultIds.slice(0, ps.limit); const oldestNoteId = ascending ? redisResultIds[0] : redisResultIds[redisResultIds.length - 1];
const shouldFallbackToDb = noteIds.length === 0 || ps.sinceId != null && ps.sinceId < oldestNoteId;
shouldFallbackToDb = shouldFallbackToDb || (noteIds.length === 0);
if (!shouldFallbackToDb) { if (!shouldFallbackToDb) {
let filter = ps.noteFilter ?? (_note => true); let filter = ps.noteFilter ?? (_note => true);

View File

@ -59,7 +59,6 @@ import { UtilityService } from '@/core/UtilityService.js';
import { UserBlockingService } from '@/core/UserBlockingService.js'; import { UserBlockingService } from '@/core/UserBlockingService.js';
import { isReply } from '@/misc/is-reply.js'; import { isReply } from '@/misc/is-reply.js';
import { trackPromise } from '@/misc/promise-tracker.js'; import { trackPromise } from '@/misc/promise-tracker.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { IdentifiableError } from '@/misc/identifiable-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js';
type NotificationType = 'reply' | 'renote' | 'quote' | 'mention'; type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
@ -839,7 +838,7 @@ export class NoteCreateService implements OnApplicationShutdown {
const mentions = extractMentions(tokens); const mentions = extractMentions(tokens);
let mentionedUsers = (await Promise.all(mentions.map(m => let mentionedUsers = (await Promise.all(mentions.map(m =>
this.remoteUserResolveService.resolveUser(m.username, m.host ?? user.host).catch(() => null), this.remoteUserResolveService.resolveUser(m.username, m.host ?? user.host).catch(() => null),
))).filter(isNotNull); ))).filter(x => x != null);
// Drop duplicate users // Drop duplicate users
mentionedUsers = mentionedUsers.filter((u, i, self) => mentionedUsers = mentionedUsers.filter((u, i, self) =>

View File

@ -95,7 +95,7 @@ export class UserListService implements OnApplicationShutdown, OnModuleInit {
const currentCount = await this.userListMembershipsRepository.countBy({ const currentCount = await this.userListMembershipsRepository.countBy({
userListId: list.id, userListId: list.id,
}); });
if (currentCount > (await this.roleService.getUserPolicies(me.id)).userEachUserListsLimit) { if (currentCount >= (await this.roleService.getUserPolicies(me.id)).userEachUserListsLimit) {
throw new UserListService.TooManyUsersError(); throw new UserListService.TooManyUsersError();
} }

View File

@ -8,7 +8,6 @@ import promiseLimit from 'promise-limit';
import type { MiRemoteUser, MiUser } from '@/models/User.js'; import type { MiRemoteUser, MiUser } from '@/models/User.js';
import { concat, unique } from '@/misc/prelude/array.js'; import { concat, unique } from '@/misc/prelude/array.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { getApIds } from './type.js'; import { getApIds } from './type.js';
import { ApPersonService } from './models/ApPersonService.js'; import { ApPersonService } from './models/ApPersonService.js';
import type { ApObject } from './type.js'; import type { ApObject } from './type.js';
@ -41,7 +40,7 @@ export class ApAudienceService {
const limit = promiseLimit<MiUser | null>(2); const limit = promiseLimit<MiUser | null>(2);
const mentionedUsers = (await Promise.all( const mentionedUsers = (await Promise.all(
others.map(id => limit(() => this.apPersonService.resolvePerson(id, resolver).catch(() => null))), others.map(id => limit(() => this.apPersonService.resolvePerson(id, resolver).catch(() => null))),
)).filter(isNotNull); )).filter(x => x != null);
if (toGroups.public.length > 0) { if (toGroups.public.length > 0) {
return { return {

View File

@ -27,7 +27,6 @@ import { QueueService } from '@/core/QueueService.js';
import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/_.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, AbuseUserReportsRepository, FollowRequestsRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import type { MiRemoteUser } from '@/models/User.js'; import type { MiRemoteUser } from '@/models/User.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { GlobalEventService } from '@/core/GlobalEventService.js'; import { GlobalEventService } from '@/core/GlobalEventService.js';
import { AbuseReportService } from '@/core/AbuseReportService.js'; import { AbuseReportService } from '@/core/AbuseReportService.js';
import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js'; import { getApHrefNullable, getApId, getApIds, getApType, isAccept, isActor, isAdd, isAnnounce, isBlock, isCollection, isCollectionOrOrderedCollection, isCreate, isDelete, isFlag, isFollow, isLike, isMove, isPost, isReject, isRemove, isTombstone, isUndo, isUpdate, validActor, validPost } from './type.js';
@ -538,7 +537,7 @@ export class ApInboxService {
const userIds = uris const userIds = uris
.filter(uri => uri.startsWith(this.config.url + '/users/')) .filter(uri => uri.startsWith(this.config.url + '/users/'))
.map(uri => uri.split('/').at(-1)) .map(uri => uri.split('/').at(-1))
.filter(isNotNull); .filter(x => x != null);
const users = await this.usersRepository.findBy({ const users = await this.usersRepository.findBy({
id: In(userIds), id: In(userIds),
}); });

View File

@ -26,7 +26,6 @@ import type { MiUserKeypair } from '@/models/UserKeypair.js';
import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, PollsRepository } from '@/models/_.js'; import type { UsersRepository, UserProfilesRepository, NotesRepository, DriveFilesRepository, PollsRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { CustomEmojiService } from '@/core/CustomEmojiService.js'; import { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { JsonLdService } from './JsonLdService.js'; import { JsonLdService } from './JsonLdService.js';
import { ApMfmService } from './ApMfmService.js'; import { ApMfmService } from './ApMfmService.js';
@ -317,7 +316,7 @@ export class ApRendererService {
const getPromisedFiles = async (ids: string[]): Promise<MiDriveFile[]> => { const getPromisedFiles = async (ids: string[]): Promise<MiDriveFile[]> => {
if (ids.length === 0) return []; if (ids.length === 0) return [];
const items = await this.driveFilesRepository.findBy({ id: In(ids) }); const items = await this.driveFilesRepository.findBy({ id: In(ids) });
return ids.map(id => items.find(item => item.id === id)).filter(isNotNull); return ids.map(id => items.find(item => item.id === id)).filter(x => x != null);
}; };
let inReplyTo; let inReplyTo;
@ -686,7 +685,7 @@ export class ApRendererService {
if (names.length === 0) return []; if (names.length === 0) return [];
const allEmojis = await this.customEmojiService.localEmojisCache.fetch(); const allEmojis = await this.customEmojiService.localEmojisCache.fetch();
const emojis = names.map(name => allEmojis.get(name)).filter(isNotNull); const emojis = names.map(name => allEmojis.get(name)).filter(x => x != null);
return emojis; return emojis;
} }

View File

@ -8,7 +8,6 @@ import promiseLimit from 'promise-limit';
import type { MiUser } from '@/models/_.js'; import type { MiUser } from '@/models/_.js';
import { toArray, unique } from '@/misc/prelude/array.js'; import { toArray, unique } from '@/misc/prelude/array.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { isMention } from '../type.js'; import { isMention } from '../type.js';
import { Resolver } from '../ApResolverService.js'; import { Resolver } from '../ApResolverService.js';
import { ApPersonService } from './ApPersonService.js'; import { ApPersonService } from './ApPersonService.js';
@ -28,7 +27,7 @@ export class ApMentionService {
const limit = promiseLimit<MiUser | null>(2); const limit = promiseLimit<MiUser | null>(2);
const mentionedUsers = (await Promise.all( const mentionedUsers = (await Promise.all(
hrefs.map(x => limit(() => this.apPersonService.resolvePerson(x, resolver).catch(() => null))), hrefs.map(x => limit(() => this.apPersonService.resolvePerson(x, resolver).catch(() => null))),
)).filter(isNotNull); )).filter(x => x != null);
return mentionedUsers; return mentionedUsers;
} }

View File

@ -24,7 +24,6 @@ import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { checkHttps } from '@/misc/check-https.js'; import { checkHttps } from '@/misc/check-https.js';
import { IdentifiableError } from '@/misc/identifiable-error.js'; import { IdentifiableError } from '@/misc/identifiable-error.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { getOneApId, getApId, getOneApHrefNullable, validPost, isEmoji, getApType } from '../type.js'; import { getOneApId, getApId, getOneApHrefNullable, validPost, isEmoji, getApType } from '../type.js';
import { ApLoggerService } from '../ApLoggerService.js'; import { ApLoggerService } from '../ApLoggerService.js';
import { ApMfmService } from '../ApMfmService.js'; import { ApMfmService } from '../ApMfmService.js';
@ -253,7 +252,7 @@ export class ApNoteService {
} }
}; };
const uris = unique([note._misskey_quote, note.quoteUrl].filter(isNotNull)); const uris = unique([note._misskey_quote, note.quoteUrl].filter(x => x != null));
const results = await Promise.all(uris.map(tryResolveNote)); const results = await Promise.all(uris.map(tryResolveNote));
quote = results.filter((x): x is { status: 'ok', res: MiNote } => x.status === 'ok').map(x => x.res).at(0); quote = results.filter((x): x is { status: 'ok', res: MiNote } => x.status === 'ok').map(x => x.res).at(0);

View File

@ -38,7 +38,6 @@ import { MetaService } from '@/core/MetaService.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import type { AccountMoveService } from '@/core/AccountMoveService.js'; import type { AccountMoveService } from '@/core/AccountMoveService.js';
import { checkHttps } from '@/misc/check-https.js'; import { checkHttps } from '@/misc/check-https.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { getApId, getApType, getOneApHrefNullable, isActor, isCollection, isCollectionOrOrderedCollection, isPropertyValue } from '../type.js'; import { getApId, getApType, getOneApHrefNullable, isActor, isCollection, isCollectionOrOrderedCollection, isPropertyValue } from '../type.js';
import { extractApHashtags } from './tag.js'; import { extractApHashtags } from './tag.js';
import type { OnModuleInit } from '@nestjs/common'; import type { OnModuleInit } from '@nestjs/common';
@ -637,7 +636,7 @@ export class ApPersonService implements OnModuleInit {
// とりあえずidを別の時間で生成して順番を維持 // とりあえずidを別の時間で生成して順番を維持
let td = 0; let td = 0;
for (const note of featuredNotes.filter(isNotNull)) { for (const note of featuredNotes.filter(x => x != null)) {
td -= 1000; td -= 1000;
transactionalEntityManager.insert(MiUserNotePining, { transactionalEntityManager.insert(MiUserNotePining, {
id: this.idService.gen(Date.now() + td), id: this.idService.gen(Date.now() + td),

View File

@ -10,7 +10,6 @@ import type { Config } from '@/config.js';
import type { IPoll } from '@/models/Poll.js'; import type { IPoll } from '@/models/Poll.js';
import type Logger from '@/logger.js'; import type Logger from '@/logger.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { isQuestion } from '../type.js'; import { isQuestion } from '../type.js';
import { ApLoggerService } from '../ApLoggerService.js'; import { ApLoggerService } from '../ApLoggerService.js';
import { ApResolverService } from '../ApResolverService.js'; import { ApResolverService } from '../ApResolverService.js';
@ -52,7 +51,7 @@ export class ApQuestionService {
const choices = question[multiple ? 'anyOf' : 'oneOf'] const choices = question[multiple ? 'anyOf' : 'oneOf']
?.map((x) => x.name) ?.map((x) => x.name)
.filter(isNotNull) .filter(x => x != null)
?? []; ?? [];
const votes = question[multiple ? 'anyOf' : 'oneOf']?.map((x) => x.replies?.totalItems ?? x._misskey_votes ?? 0); const votes = question[multiple ? 'anyOf' : 'oneOf']?.map((x) => x.replies?.totalItems ?? x._misskey_votes ?? 0);

View File

@ -4,7 +4,6 @@
*/ */
import { toArray } from '@/misc/prelude/array.js'; import { toArray } from '@/misc/prelude/array.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { isHashtag } from '../type.js'; import { isHashtag } from '../type.js';
import type { IObject, IApHashtag } from '../type.js'; import type { IObject, IApHashtag } from '../type.js';
@ -16,7 +15,7 @@ export function extractApHashtags(tags: IObject | IObject[] | null | undefined):
return hashtags.map(tag => { return hashtags.map(tag => {
const m = tag.name.match(/^#(.+)/); const m = tag.name.match(/^#(.+)/);
return m ? m[1] : null; return m ? m[1] : null;
}).filter(isNotNull); }).filter(x => x != null);
} }
export function extractApHashtagObjects(tags: IObject | IObject[] | null | undefined): IApHashtag[] { export function extractApHashtagObjects(tags: IObject | IObject[] | null | undefined): IApHashtag[] {

View File

@ -11,7 +11,6 @@ import { bindThis } from '@/decorators.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { Packed } from '@/misc/json-schema.js'; import { Packed } from '@/misc/json-schema.js';
import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js'; import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js';
import { isNotNull } from '@/misc/is-not-null.js';
@Injectable() @Injectable()
export class AbuseReportNotificationRecipientEntityService { export class AbuseReportNotificationRecipientEntityService {
@ -66,13 +65,13 @@ export class AbuseReportNotificationRecipientEntityService {
); );
} }
const userIds = objs.map(it => it.userId).filter(isNotNull); const userIds = objs.map(it => it.userId).filter(x => x != null);
const users: Map<string, Packed<'UserLite'>> = (userIds.length > 0) const users: Map<string, Packed<'UserLite'>> = (userIds.length > 0)
? await this.userEntityService.packMany(userIds) ? await this.userEntityService.packMany(userIds)
.then(it => new Map(it.map(it => [it.id, it]))) .then(it => new Map(it.map(it => [it.id, it])))
: new Map(); : new Map();
const systemWebhookIds = objs.map(it => it.systemWebhookId).filter(isNotNull); const systemWebhookIds = objs.map(it => it.systemWebhookId).filter(x => x != null);
const systemWebhooks: Map<string, Packed<'SystemWebhook'>> = (systemWebhookIds.length > 0) const systemWebhooks: Map<string, Packed<'SystemWebhook'>> = (systemWebhookIds.length > 0)
? await this.systemWebhookEntityService.packMany(systemWebhookIds) ? await this.systemWebhookEntityService.packMany(systemWebhookIds)
.then(it => new Map(it.map(it => [it.id, it]))) .then(it => new Map(it.map(it => [it.id, it])))

View File

@ -10,7 +10,6 @@ import { awaitAll } from '@/misc/prelude/await-all.js';
import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import type { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { isNotNull } from '@/misc/is-not-null.js';
import type { Packed } from '@/misc/json-schema.js'; import type { Packed } from '@/misc/json-schema.js';
import { UserEntityService } from './UserEntityService.js'; import { UserEntityService } from './UserEntityService.js';
@ -63,7 +62,7 @@ export class AbuseUserReportEntityService {
) { ) {
const _reporters = reports.map(({ reporter, reporterId }) => reporter ?? reporterId); const _reporters = reports.map(({ reporter, reporterId }) => reporter ?? reporterId);
const _targetUsers = reports.map(({ targetUser, targetUserId }) => targetUser ?? targetUserId); const _targetUsers = reports.map(({ targetUser, targetUserId }) => targetUser ?? targetUserId);
const _assignees = reports.map(({ assignee, assigneeId }) => assignee ?? assigneeId).filter(isNotNull); const _assignees = reports.map(({ assignee, assigneeId }) => assignee ?? assigneeId).filter(x => x != null);
const _userMap = await this.userEntityService.packMany( const _userMap = await this.userEntityService.packMany(
[..._reporters, ..._targetUsers, ..._assignees], [..._reporters, ..._targetUsers, ..._assignees],
null, null,

View File

@ -16,7 +16,6 @@ import { appendQuery, query } from '@/misc/prelude/url.js';
import { deepClone } from '@/misc/clone.js'; import { deepClone } from '@/misc/clone.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isMimeImage } from '@/misc/is-mime-image.js'; import { isMimeImage } from '@/misc/is-mime-image.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { UtilityService } from '../UtilityService.js'; import { UtilityService } from '../UtilityService.js';
import { VideoProcessingService } from '../VideoProcessingService.js'; import { VideoProcessingService } from '../VideoProcessingService.js';
@ -261,11 +260,11 @@ export class DriveFileEntityService {
files: MiDriveFile[], files: MiDriveFile[],
options?: PackOptions, options?: PackOptions,
): Promise<Packed<'DriveFile'>[]> { ): Promise<Packed<'DriveFile'>[]> {
const _user = files.map(({ user, userId }) => user ?? userId).filter(isNotNull); const _user = files.map(({ user, userId }) => user ?? userId).filter(x => x != null);
const _userMap = await this.userEntityService.packMany(_user) const _userMap = await this.userEntityService.packMany(_user)
.then(users => new Map(users.map(user => [user.id, user]))); .then(users => new Map(users.map(user => [user.id, user])));
const items = await Promise.all(files.map(f => this.packNullable(f, options, f.userId ? { packedUser: _userMap.get(f.userId) } : {}))); const items = await Promise.all(files.map(f => this.packNullable(f, options, f.userId ? { packedUser: _userMap.get(f.userId) } : {})));
return items.filter(isNotNull); return items.filter(x => x != null);
} }
@bindThis @bindThis
@ -290,6 +289,6 @@ export class DriveFileEntityService {
): Promise<Packed<'DriveFile'>[]> { ): Promise<Packed<'DriveFile'>[]> {
if (fileIds.length === 0) return []; if (fileIds.length === 0) return [];
const filesMap = await this.packManyByIdsMap(fileIds, options); const filesMap = await this.packManyByIdsMap(fileIds, options);
return fileIds.map(id => filesMap.get(id)).filter(isNotNull); return fileIds.map(id => filesMap.get(id)).filter(x => x != null);
} }
} }

View File

@ -12,7 +12,6 @@ import type { MiUser } from '@/models/User.js';
import type { MiRegistrationTicket } from '@/models/RegistrationTicket.js'; import type { MiRegistrationTicket } from '@/models/RegistrationTicket.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { UserEntityService } from './UserEntityService.js'; import { UserEntityService } from './UserEntityService.js';
@Injectable() @Injectable()
@ -59,8 +58,8 @@ export class InviteCodeEntityService {
tickets: MiRegistrationTicket[], tickets: MiRegistrationTicket[],
me: { id: MiUser['id'] }, me: { id: MiUser['id'] },
) { ) {
const _createdBys = tickets.map(({ createdBy, createdById }) => createdBy ?? createdById).filter(isNotNull); const _createdBys = tickets.map(({ createdBy, createdById }) => createdBy ?? createdById).filter(x => x != null);
const _usedBys = tickets.map(({ usedBy, usedById }) => usedBy ?? usedById).filter(isNotNull); const _usedBys = tickets.map(({ usedBy, usedById }) => usedBy ?? usedById).filter(x => x != null);
const _userMap = await this.userEntityService.packMany([..._createdBys, ..._usedBys], me) const _userMap = await this.userEntityService.packMany([..._createdBys, ..._usedBys], me)
.then(users => new Map(users.map(u => [u.id, u]))); .then(users => new Map(users.map(u => [u.id, u])));
return Promise.all( return Promise.all(

View File

@ -14,7 +14,6 @@ import type { MiNote } from '@/models/Note.js';
import type { MiNoteReaction } from '@/models/NoteReaction.js'; import type { MiNoteReaction } from '@/models/NoteReaction.js';
import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository } from '@/models/_.js'; import type { UsersRepository, NotesRepository, FollowingsRepository, PollsRepository, PollVotesRepository, NoteReactionsRepository, ChannelsRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { DebounceLoader } from '@/misc/loader.js'; import { DebounceLoader } from '@/misc/loader.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import type { OnModuleInit } from '@nestjs/common'; import type { OnModuleInit } from '@nestjs/common';
@ -276,7 +275,7 @@ export class NoteEntityService implements OnModuleInit {
packedFiles.set(k, v); packedFiles.set(k, v);
} }
} }
return fileIds.map(id => packedFiles.get(id)).filter(isNotNull); return fileIds.map(id => packedFiles.get(id)).filter(x => x != null);
} }
@bindThis @bindThis
@ -449,12 +448,12 @@ export class NoteEntityService implements OnModuleInit {
await this.customEmojiService.prefetchEmojis(this.aggregateNoteEmojis(notes)); await this.customEmojiService.prefetchEmojis(this.aggregateNoteEmojis(notes));
// TODO: 本当は renote とか reply がないのに renoteId とか replyId があったらここで解決しておく // TODO: 本当は renote とか reply がないのに renoteId とか replyId があったらここで解決しておく
const fileIds = notes.map(n => [n.fileIds, n.renote?.fileIds, n.reply?.fileIds]).flat(2).filter(isNotNull); const fileIds = notes.map(n => [n.fileIds, n.renote?.fileIds, n.reply?.fileIds]).flat(2).filter(x => x != null);
const packedFiles = fileIds.length > 0 ? await this.driveFileEntityService.packManyByIdsMap(fileIds) : new Map(); const packedFiles = fileIds.length > 0 ? await this.driveFileEntityService.packManyByIdsMap(fileIds) : new Map();
const users = [ const users = [
...notes.map(({ user, userId }) => user ?? userId), ...notes.map(({ user, userId }) => user ?? userId),
...notes.map(({ replyUserId }) => replyUserId).filter(isNotNull), ...notes.map(({ replyUserId }) => replyUserId).filter(x => x != null),
...notes.map(({ renoteUserId }) => renoteUserId).filter(isNotNull), ...notes.map(({ renoteUserId }) => renoteUserId).filter(x => x != null),
]; ];
const packedUsers = await this.userEntityService.packMany(users, me) const packedUsers = await this.userEntityService.packMany(users, me)
.then(users => new Map(users.map(u => [u.id, u]))); .then(users => new Map(users.map(u => [u.id, u])));

View File

@ -13,7 +13,6 @@ import type { MiGroupedNotification, MiNotification } from '@/models/Notificatio
import type { MiNote } from '@/models/Note.js'; import type { MiNote } from '@/models/Note.js';
import type { Packed } from '@/misc/json-schema.js'; import type { Packed } from '@/misc/json-schema.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { FilterUnionByProperty, groupedNotificationTypes } from '@/types.js'; import { FilterUnionByProperty, groupedNotificationTypes } from '@/types.js';
import { CacheService } from '@/core/CacheService.js'; import { CacheService } from '@/core/CacheService.js';
import { RoleEntityService } from './RoleEntityService.js'; import { RoleEntityService } from './RoleEntityService.js';
@ -103,7 +102,7 @@ export class NotificationEntityService implements OnModuleInit {
user, user,
reaction: reaction.reaction, reaction: reaction.reaction,
}; };
}))).filter(r => isNotNull(r.user)); }))).filter(r => r.user != null);
// if all users have been deleted, don't show this notification // if all users have been deleted, don't show this notification
if (reactions.length === 0) { if (reactions.length === 0) {
return null; return null;
@ -124,7 +123,7 @@ export class NotificationEntityService implements OnModuleInit {
} }
return this.userEntityService.pack(userId, { id: meId }); return this.userEntityService.pack(userId, { id: meId });
}))).filter(isNotNull); }))).filter(x => x != null);
// if all users have been deleted, don't show this notification // if all users have been deleted, don't show this notification
if (users.length === 0) { if (users.length === 0) {
return null; return null;
@ -181,7 +180,7 @@ export class NotificationEntityService implements OnModuleInit {
validNotifications = await this.#filterValidNotifier(validNotifications, meId); validNotifications = await this.#filterValidNotifier(validNotifications, meId);
const noteIds = validNotifications.map(x => 'noteId' in x ? x.noteId : null).filter(isNotNull); const noteIds = validNotifications.map(x => 'noteId' in x ? x.noteId : null).filter(x => x != null);
const notes = noteIds.length > 0 ? await this.notesRepository.find({ const notes = noteIds.length > 0 ? await this.notesRepository.find({
where: { id: In(noteIds) }, where: { id: In(noteIds) },
relations: ['user', 'reply', 'reply.user', 'renote', 'renote.user'], relations: ['user', 'reply', 'reply.user', 'renote', 'renote.user'],
@ -223,7 +222,7 @@ export class NotificationEntityService implements OnModuleInit {
); );
}); });
return (await Promise.all(packPromises)).filter(isNotNull); return (await Promise.all(packPromises)).filter(x => x != null);
} }
@bindThis @bindThis
@ -305,7 +304,7 @@ export class NotificationEntityService implements OnModuleInit {
this.cacheService.userProfileCache.fetch(meId).then(p => new Set(p.mutedInstances)), this.cacheService.userProfileCache.fetch(meId).then(p => new Set(p.mutedInstances)),
]); ]);
const notifierIds = notifications.map(notification => 'notifierId' in notification ? notification.notifierId : null).filter(isNotNull); const notifierIds = notifications.map(notification => 'notifierId' in notification ? notification.notifierId : null).filter(x => x != null);
const notifiers = notifierIds.length > 0 ? await this.usersRepository.find({ const notifiers = notifierIds.length > 0 ? await this.usersRepository.find({
where: { id: In(notifierIds) }, where: { id: In(notifierIds) },
}) : []; }) : [];
@ -313,7 +312,7 @@ export class NotificationEntityService implements OnModuleInit {
const filteredNotifications = ((await Promise.all(notifications.map(async (notification) => { const filteredNotifications = ((await Promise.all(notifications.map(async (notification) => {
const isValid = this.#validateNotifier(notification, userIdsWhoMeMuting, userMutedInstances, notifiers); const isValid = this.#validateNotifier(notification, userIdsWhoMeMuting, userMutedInstances, notifiers);
return isValid ? notification : null; return isValid ? notification : null;
}))) as [T | null] ).filter(isNotNull); }))) as [T | null] ).filter(x => x != null);
return filteredNotifications; return filteredNotifications;
} }

View File

@ -14,7 +14,6 @@ import type { MiPage } from '@/models/Page.js';
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { isNotNull } from '@/misc/is-not-null.js';
import { UserEntityService } from './UserEntityService.js'; import { UserEntityService } from './UserEntityService.js';
import { DriveFileEntityService } from './DriveFileEntityService.js'; import { DriveFileEntityService } from './DriveFileEntityService.js';
@ -106,7 +105,7 @@ export class PageEntityService {
script: page.script, script: page.script,
eyeCatchingImageId: page.eyeCatchingImageId, eyeCatchingImageId: page.eyeCatchingImageId,
eyeCatchingImage: page.eyeCatchingImageId ? await this.driveFileEntityService.pack(page.eyeCatchingImageId) : null, eyeCatchingImage: page.eyeCatchingImageId ? await this.driveFileEntityService.pack(page.eyeCatchingImageId) : null,
attachedFiles: this.driveFileEntityService.packMany((await Promise.all(attachedFiles)).filter(isNotNull)), attachedFiles: this.driveFileEntityService.packMany((await Promise.all(attachedFiles)).filter(x => x != null)),
likedCount: page.likedCount, likedCount: page.likedCount,
isLiked: meId ? await this.pageLikesRepository.exists({ where: { pageId: page.id, userId: meId } }) : undefined, isLiked: meId ? await this.pageLikesRepository.exists({ where: { pageId: page.id, userId: meId } }) : undefined,
}); });

View File

@ -47,7 +47,6 @@ import { IdService } from '@/core/IdService.js';
import type { AnnouncementService } from '@/core/AnnouncementService.js'; import type { AnnouncementService } from '@/core/AnnouncementService.js';
import type { CustomEmojiService } from '@/core/CustomEmojiService.js'; import type { CustomEmojiService } from '@/core/CustomEmojiService.js';
import { AvatarDecorationService } from '@/core/AvatarDecorationService.js'; import { AvatarDecorationService } from '@/core/AvatarDecorationService.js';
import { isNotNull } from '@/misc/is-not-null.js';
import type { OnModuleInit } from '@nestjs/common'; import type { OnModuleInit } from '@nestjs/common';
import type { NoteEntityService } from './NoteEntityService.js'; import type { NoteEntityService } from './NoteEntityService.js';
import type { DriveFileEntityService } from './DriveFileEntityService.js'; import type { DriveFileEntityService } from './DriveFileEntityService.js';
@ -514,7 +513,7 @@ export class UserEntityService implements OnModuleInit {
movedTo: user.movedToUri ? this.apPersonService.resolvePerson(user.movedToUri).then(user => user.id).catch(() => null) : null, movedTo: user.movedToUri ? this.apPersonService.resolvePerson(user.movedToUri).then(user => user.id).catch(() => null) : null,
alsoKnownAs: user.alsoKnownAs alsoKnownAs: user.alsoKnownAs
? Promise.all(user.alsoKnownAs.map(uri => this.apPersonService.fetchPerson(uri).then(user => user?.id).catch(() => null))) ? Promise.all(user.alsoKnownAs.map(uri => this.apPersonService.fetchPerson(uri).then(user => user?.id).catch(() => null)))
.then(xs => xs.length === 0 ? null : xs.filter(isNotNull)) .then(xs => xs.length === 0 ? null : xs.filter(x => x != null))
: null, : null,
createdAt: this.idService.parse(user.id).date.toISOString(), createdAt: this.idService.parse(user.id).date.toISOString(),
updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null, updatedAt: user.updatedAt ? user.updatedAt.toISOString() : null,

View File

@ -1,8 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export function isNotNull<T extends NonNullable<unknown>>(input: T | undefined | null): input is T {
return input != null;
}

View File

@ -1,8 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export function gcd(a: number, b: number): number {
return b === 0 ? a : gcd(b, a % b);
}

View File

@ -1,25 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export interface IMaybe<T> {
isJust(): this is IJust<T>;
}
export interface IJust<T> extends IMaybe<T> {
get(): T;
}
export function just<T>(value: T): IJust<T> {
return {
isJust: () => true,
get: () => value,
};
}
export function nothing<T>(): IMaybe<T> {
return {
isJust: () => false,
};
}

View File

@ -1,20 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export function concat(xs: string[]): string {
return xs.join('');
}
export function capitalize(s: string): string {
return toUpperCase(s.charAt(0)) + toLowerCase(s.slice(1));
}
export function toUpperCase(s: string): string {
return s.toUpperCase();
}
export function toLowerCase(s: string): string {
return s.toLowerCase();
}

View File

@ -1,6 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
export const fallback = Symbol('fallback');

View File

@ -109,6 +109,12 @@ export class DeliverProcessorService {
suspensionState: 'autoSuspendedForNotResponding', suspensionState: 'autoSuspendedForNotResponding',
}); });
} }
} else {
// isNotRespondingがtrueでnotRespondingSinceがnullの場合はnotRespondingSinceをセット
// notRespondingSinceは新たな機能なので、それ以前のデータにはnotRespondingSinceがない場合がある
this.federatedInstanceService.update(i.id, {
notRespondingSince: new Date(),
});
} }
this.apRequestChart.deliverFail(); this.apRequestChart.deliverFail();

View File

@ -93,7 +93,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const currentAntennasCount = await this.antennasRepository.countBy({ const currentAntennasCount = await this.antennasRepository.countBy({
userId: me.id, userId: me.id,
}); });
if (currentAntennasCount > (await this.roleService.getUserPolicies(me.id)).antennaLimit) { if (currentAntennasCount >= (await this.roleService.getUserPolicies(me.id)).antennaLimit) {
throw new ApiError(meta.errors.tooManyAntennas); throw new ApiError(meta.errors.tooManyAntennas);
} }

View File

@ -95,15 +95,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
// Check if the circular reference will occur // Check if the circular reference will occur
const checkCircle = async (folderId: string): Promise<boolean> => { const checkCircle = async (folderId: string): Promise<boolean> => {
// Fetch folder const folder2 = await this.driveFoldersRepository.findOneByOrFail({
const folder2 = await this.driveFoldersRepository.findOneBy({
id: folderId, id: folderId,
}); });
if (folder2!.id === folder!.id) { if (folder2.id === folder.id) {
return true; return true;
} else if (folder2!.parentId) { } else if (folder2.parentId) {
return await checkCircle(folder2!.parentId); return await checkCircle(folder2.parentId);
} else { } else {
return false; return false;
} }

View File

@ -12,7 +12,6 @@ import type { MiDriveFile } from '@/models/DriveFile.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { isNotNull } from '@/misc/is-not-null.js';
export const meta = { export const meta = {
tags: ['gallery'], tags: ['gallery'],
@ -70,7 +69,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
id: fileId, id: fileId,
userId: me.id, userId: me.id,
}), }),
))).filter(isNotNull); ))).filter(x => x != null);
if (files.length === 0) { if (files.length === 0) {
throw new Error(); throw new Error();

View File

@ -10,7 +10,6 @@ import type { DriveFilesRepository, GalleryPostsRepository } from '@/models/_.js
import type { MiDriveFile } from '@/models/DriveFile.js'; import type { MiDriveFile } from '@/models/DriveFile.js';
import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js'; import { GalleryPostEntityService } from '@/core/entities/GalleryPostEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { isNotNull } from '@/misc/is-not-null.js';
export const meta = { export const meta = {
tags: ['gallery'], tags: ['gallery'],
@ -68,7 +67,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
id: fileId, id: fileId,
userId: me.id, userId: me.id,
}), }),
))).filter(isNotNull); ))).filter(x => x != null);
if (files.length === 0) { if (files.length === 0) {
throw new Error(); throw new Error();

View File

@ -78,7 +78,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
if (file.size === 0) throw new ApiError(meta.errors.emptyFile); if (file.size === 0) throw new ApiError(meta.errors.emptyFile);
const antennas: (_Antenna & { userListAccts: string[] | null })[] = JSON.parse(await this.downloadService.downloadTextFile(file.url)); const antennas: (_Antenna & { userListAccts: string[] | null })[] = JSON.parse(await this.downloadService.downloadTextFile(file.url));
const currentAntennasCount = await this.antennasRepository.countBy({ userId: me.id }); const currentAntennasCount = await this.antennasRepository.countBy({ userId: me.id });
if (currentAntennasCount + antennas.length > (await this.roleService.getUserPolicies(me.id)).antennaLimit) { if (currentAntennasCount + antennas.length >= (await this.roleService.getUserPolicies(me.id)).antennaLimit) {
throw new ApiError(meta.errors.tooManyAntennas); throw new ApiError(meta.errors.tooManyAntennas);
} }
this.queueService.createImportAntennasJob(me, antennas); this.queueService.createImportAntennasJob(me, antennas);

View File

@ -85,7 +85,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const currentWebhooksCount = await this.webhooksRepository.countBy({ const currentWebhooksCount = await this.webhooksRepository.countBy({
userId: me.id, userId: me.id,
}); });
if (currentWebhooksCount > (await this.roleService.getUserPolicies(me.id)).webhookLimit) { if (currentWebhooksCount >= (await this.roleService.getUserPolicies(me.id)).webhookLimit) {
throw new ApiError(meta.errors.tooManyWebhooks); throw new ApiError(meta.errors.tooManyWebhooks);
} }

View File

@ -12,7 +12,6 @@ import { Endpoint } from '@/server/api/endpoint-base.js';
import { MetaService } from '@/core/MetaService.js'; import { MetaService } from '@/core/MetaService.js';
import { UserEntityService } from '@/core/entities/UserEntityService.js'; import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { DI } from '@/di-symbols.js'; import { DI } from '@/di-symbols.js';
import { isNotNull } from '@/misc/is-not-null.js';
export const meta = { export const meta = {
tags: ['users'], tags: ['users'],
@ -53,7 +52,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
host: acct.host ?? IsNull(), host: acct.host ?? IsNull(),
}))); })));
return await this.userEntityService.packMany(users.filter(isNotNull), me, { schema: 'UserDetailed' }); return await this.userEntityService.packMany(users.filter(x => x != null), me, { schema: 'UserDetailed' });
}); });
} }
} }

View File

@ -100,7 +100,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const currentCount = await this.userListsRepository.countBy({ const currentCount = await this.userListsRepository.countBy({
userId: me.id, userId: me.id,
}); });
if (currentCount > (await this.roleService.getUserPolicies(me.id)).userListLimit) { if (currentCount >= (await this.roleService.getUserPolicies(me.id)).userListLimit) {
throw new ApiError(meta.errors.tooManyUserLists); throw new ApiError(meta.errors.tooManyUserLists);
} }

View File

@ -61,7 +61,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const currentCount = await this.userListsRepository.countBy({ const currentCount = await this.userListsRepository.countBy({
userId: me.id, userId: me.id,
}); });
if (currentCount > (await this.roleService.getUserPolicies(me.id)).userListLimit) { if (currentCount >= (await this.roleService.getUserPolicies(me.id)).userListLimit) {
throw new ApiError(meta.errors.tooManyUserLists); throw new ApiError(meta.errors.tooManyUserLists);
} }

View File

@ -14,6 +14,8 @@ import { UserEntityService } from '@/core/entities/UserEntityService.js';
import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js'; import { DriveFileEntityService } from '@/core/entities/DriveFileEntityService.js';
import { bindThis } from '@/decorators.js'; import { bindThis } from '@/decorators.js';
import { IdService } from '@/core/IdService.js'; import { IdService } from '@/core/IdService.js';
import { MfmService } from "@/core/MfmService.js";
import { parse as mfmParse } from 'mfm-js';
@Injectable() @Injectable()
export class FeedService { export class FeedService {
@ -33,6 +35,7 @@ export class FeedService {
private userEntityService: UserEntityService, private userEntityService: UserEntityService,
private driveFileEntityService: DriveFileEntityService, private driveFileEntityService: DriveFileEntityService,
private idService: IdService, private idService: IdService,
private mfmService: MfmService,
) { ) {
} }
@ -76,13 +79,14 @@ export class FeedService {
id: In(note.fileIds), id: In(note.fileIds),
}) : []; }) : [];
const file = files.find(file => file.type.startsWith('image/')); const file = files.find(file => file.type.startsWith('image/'));
const text = note.text;
feed.addItem({ feed.addItem({
title: `New note by ${author.name}`, title: `New note by ${author.name}`,
link: `${this.config.url}/notes/${note.id}`, link: `${this.config.url}/notes/${note.id}`,
date: this.idService.parse(note.id).date, date: this.idService.parse(note.id).date,
description: note.cw ?? undefined, description: note.cw ?? undefined,
content: note.text ?? undefined, content: text ? this.mfmService.toHtml(mfmParse(text), JSON.parse(note.mentionedRemoteUsers)) ?? undefined : undefined,
image: file ? this.driveFileEntityService.getPublicUrl(file) : undefined, image: file ? this.driveFileEntityService.getPublicUrl(file) : undefined,
}); });
} }

View File

@ -163,8 +163,7 @@ describe('アンテナ', () => {
}); });
test('が上限いっぱいまで作成できること', async () => { test('が上限いっぱいまで作成できること', async () => {
// antennaLimit + 1まで作れるのがキモ const response = await Promise.all([...Array(DEFAULT_POLICIES.antennaLimit)].map(() => successfulApiCall({
const response = await Promise.all([...Array(DEFAULT_POLICIES.antennaLimit + 1)].map(() => successfulApiCall({
endpoint: 'antennas/create', endpoint: 'antennas/create',
parameters: { ...defaultParam }, parameters: { ...defaultParam },
user: alice, user: alice,

View File

@ -153,8 +153,7 @@ describe('クリップ', () => {
}); });
test('の作成はポリシーで定められた数以上はできない。', async () => { test('の作成はポリシーで定められた数以上はできない。', async () => {
// ポリシー + 1まで作れるという所がミソ const clipLimit = DEFAULT_POLICIES.clipLimit;
const clipLimit = DEFAULT_POLICIES.clipLimit + 1;
for (let i = 0; i < clipLimit; i++) { for (let i = 0; i < clipLimit; i++) {
await create(); await create();
} }
@ -327,7 +326,7 @@ describe('クリップ', () => {
}); });
test('の一覧(clips/list)が取得できる(上限いっぱい)', async () => { test('の一覧(clips/list)が取得できる(上限いっぱい)', async () => {
const clipLimit = DEFAULT_POLICIES.clipLimit + 1; const clipLimit = DEFAULT_POLICIES.clipLimit;
const clips = await createMany({}, clipLimit); const clips = await createMany({}, clipLimit);
const res = await list({ const res = await list({
parameters: { limit: 1 }, // FIXME: 無視されて11全部返ってくる parameters: { limit: 1 }, // FIXME: 無視されて11全部返ってくる
@ -705,7 +704,7 @@ describe('クリップ', () => {
// TODO: 17000msくらいかかる... // TODO: 17000msくらいかかる...
test('をポリシーで定められた上限いっぱい(200)を超えて追加はできない。', async () => { test('をポリシーで定められた上限いっぱい(200)を超えて追加はできない。', async () => {
const noteLimit = DEFAULT_POLICIES.noteEachClipsLimit + 1; const noteLimit = DEFAULT_POLICIES.noteEachClipsLimit;
const noteList = await Promise.all([...Array(noteLimit)].map((_, i) => post(alice, { const noteList = await Promise.all([...Array(noteLimit)].map((_, i) => post(alice, {
text: `test ${i}`, text: `test ${i}`,
}) as unknown)) as Misskey.entities.Note[]; }) as unknown)) as Misskey.entities.Note[];

View File

@ -153,6 +153,23 @@ describe('Webリソース', () => {
path: path('nonexisting'), path: path('nonexisting'),
status: 404, status: 404,
})); }));
describe(' has entry such ', () => {
beforeEach(() => {
post(alice, { text: "**a**" })
});
test('MFMを含まない。', async () => {
const content = await simpleGet(path(alice.username), "*/*", undefined, res => res.text());
const _body: unknown = content.body;
// JSONフィードのときは改めて文字列化する
const body: string = typeof (_body) === "object" ? JSON.stringify(_body) : _body as string;
if (body.includes("**a**")) {
throw new Error("MFM shouldn't be included");
}
});
})
}); });
describe.each([{ path: '/api/foo' }])('$path', ({ path }) => { describe.each([{ path: '/api/foo' }])('$path', ({ path }) => {

View File

@ -7,6 +7,8 @@
// pnpm jest -- e2e/timelines.ts // pnpm jest -- e2e/timelines.ts
import * as assert from 'assert'; import * as assert from 'assert';
import { Redis } from 'ioredis';
import { loadConfig } from '@/config.js';
import { api, post, randomString, sendEnvUpdateRequest, signup, sleep, uploadUrl } from '../utils.js'; import { api, post, randomString, sendEnvUpdateRequest, signup, sleep, uploadUrl } from '../utils.js';
function genHost() { function genHost() {
@ -17,7 +19,13 @@ function waitForPushToTl() {
return sleep(500); return sleep(500);
} }
let redisForTimelines: Redis;
describe('Timelines', () => { describe('Timelines', () => {
beforeAll(() => {
redisForTimelines = new Redis(loadConfig().redisForTimelines);
});
describe('Home TL', () => { describe('Home TL', () => {
test.concurrent('自分の visibility: followers なノートが含まれる', async () => { test.concurrent('自分の visibility: followers なノートが含まれる', async () => {
const [alice] = await Promise.all([signup()]); const [alice] = await Promise.all([signup()]);
@ -1272,6 +1280,33 @@ describe('Timelines', () => {
assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false); assert.strictEqual(res.body.some((note: any) => note.id === bobNote.id), false);
}); });
/** @see https://github.com/misskey-dev/misskey/issues/14000 */
test.concurrent('FTT: sinceId にキャッシュより古いートを指定しても、sinceId による絞り込みが正しく動作する', async () => {
const alice = await signup();
const noteSince = await post(alice, { text: 'Note where id will be `sinceId`.' });
const note1 = await post(alice, { text: '1' });
const note2 = await post(alice, { text: '2' });
await redisForTimelines.del('list:userTimeline:' + alice.id);
const note3 = await post(alice, { text: '3' });
const res = await api('users/notes', { userId: alice.id, sinceId: noteSince.id });
assert.deepStrictEqual(res.body, [note1, note2, note3]);
});
test.concurrent('FTT: sinceId にキャッシュより古いートを指定しても、sinceId と untilId による絞り込みが正しく動作する', async () => {
const alice = await signup();
const noteSince = await post(alice, { text: 'Note where id will be `sinceId`.' });
const note1 = await post(alice, { text: '1' });
const note2 = await post(alice, { text: '2' });
await redisForTimelines.del('list:userTimeline:' + alice.id);
const note3 = await post(alice, { text: '3' });
const noteUntil = await post(alice, { text: 'Note where id will be `untilId`.' });
await post(alice, { text: '4' });
const res = await api('users/notes', { userId: alice.id, sinceId: noteSince.id, untilId: noteUntil.id });
assert.deepStrictEqual(res.body, [note3, note2, note1]);
});
}); });
// TODO: リノートミュート済みユーザーのテスト // TODO: リノートミュート済みユーザーのテスト

View File

@ -1,23 +0,0 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import * as assert from 'assert';
import { just, nothing } from '../../src/misc/prelude/maybe.js';
describe('just', () => {
test('has a value', () => {
assert.deepStrictEqual(just(3).isJust(), true);
});
test('has the inverse called get', () => {
assert.deepStrictEqual(just(3).get(), 3);
});
});
describe('nothing', () => {
test('has no value', () => {
assert.deepStrictEqual(nothing().isJust(), false);
});
});

View File

@ -17,6 +17,7 @@ import { validateContentTypeSetAsActivityPub } from '@/core/activitypub/misc/val
import { entities } from '../src/postgres.js'; import { entities } from '../src/postgres.js';
import { loadConfig } from '../src/config.js'; import { loadConfig } from '../src/config.js';
import type * as misskey from 'misskey-js'; import type * as misskey from 'misskey-js';
import { type Response } from 'node-fetch';
export { server as startServer, jobQueue as startJobQueue } from '@/boot/common.js'; export { server as startServer, jobQueue as startJobQueue } from '@/boot/common.js';
@ -454,7 +455,7 @@ export type SimpleGetResponse = {
type: string | null, type: string | null,
location: string | null location: string | null
}; };
export const simpleGet = async (path: string, accept = '*/*', cookie: any = undefined): Promise<SimpleGetResponse> => { export const simpleGet = async (path: string, accept = '*/*', cookie: any = undefined, bodyExtractor: (res: Response) => Promise<string | null> = _ => Promise.resolve(null)): Promise<SimpleGetResponse> => {
const res = await relativeFetch(path, { const res = await relativeFetch(path, {
headers: { headers: {
Accept: accept, Accept: accept,
@ -482,7 +483,7 @@ export const simpleGet = async (path: string, accept = '*/*', cookie: any = unde
const body = const body =
jsonTypes.includes(res.headers.get('content-type') ?? '') ? await res.json() : jsonTypes.includes(res.headers.get('content-type') ?? '') ? await res.json() :
htmlTypes.includes(res.headers.get('content-type') ?? '') ? new JSDOM(await res.text()) : htmlTypes.includes(res.headers.get('content-type') ?? '') ? new JSDOM(await res.text()) :
null; await bodyExtractor(res);
return { return {
status: res.status, status: res.status,

View File

@ -56,7 +56,7 @@ module.exports = {
'vue/no-dupe-keys': 'warn', 'vue/no-dupe-keys': 'warn',
'vue/valid-v-for': 'warn', 'vue/valid-v-for': 'warn',
'vue/return-in-computed-property': 'warn', 'vue/return-in-computed-property': 'warn',
'vue/no-setup-props-destructure': 'warn', 'vue/no-setup-props-reactivity-loss': 'warn',
'vue/max-attributes-per-line': 'off', 'vue/max-attributes-per-line': 'off',
'vue/html-self-closing': 'off', 'vue/html-self-closing': 'off',
'vue/singleline-html-element-content-newline': 'off', 'vue/singleline-html-element-content-newline': 'off',

View File

@ -0,0 +1,48 @@
/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
import { DefaultBodyType, HttpResponse, HttpResponseResolver, JsonBodyType, PathParams, http } from 'msw';
import seedrandom from 'seedrandom';
import { action } from '@storybook/addon-actions';
function getChartArray(seed: string, limit: number, option?: { accumulate?: boolean, mul?: number }): number[] {
const rng = seedrandom(seed);
const max = Math.floor(option?.mul ?? 250 * rng());
let accumulation = 0;
const array: number[] = [];
for (let i = 0; i < limit; i++) {
const num = Math.floor((max + 1) * rng());
if (option?.accumulate) {
accumulation += num;
array.unshift(accumulation);
} else {
array.push(num);
}
}
return array;
}
export function getChartResolver(fields: string[], option?: { accumulate?: boolean, mulMap?: Record<string, number> }): HttpResponseResolver<PathParams, DefaultBodyType, JsonBodyType> {
return ({ request }) => {
action(`GET ${request.url}`)();
const limitParam = new URL(request.url).searchParams.get('limit');
const limit = limitParam ? parseInt(limitParam) : 30;
const res = {};
for (const field of fields) {
const layers = field.split('.');
let current = res;
while (layers.length > 1) {
const currentKey = layers.shift()!;
if (current[currentKey] == null) current[currentKey] = {};
current = current[currentKey];
}
current[layers[0]] = getChartArray(field, limit, {
accumulate: option?.accumulate,
mul: option?.mulMap != null && field in option.mulMap ? option.mulMap[field] : undefined,
});
}
return HttpResponse.json(res);
};
}

View File

@ -68,7 +68,7 @@
"tinycolor2": "1.6.0", "tinycolor2": "1.6.0",
"tsc-alias": "1.8.8", "tsc-alias": "1.8.8",
"tsconfig-paths": "4.2.0", "tsconfig-paths": "4.2.0",
"typescript": "5.4.5", "typescript": "5.5.2",
"uuid": "9.0.1", "uuid": "9.0.1",
"v-code-diff": "1.11.0", "v-code-diff": "1.11.0",
"vite": "5.2.11", "vite": "5.2.11",

View File

@ -120,7 +120,7 @@ function fetchAccount(token: string, id?: string, forceShowDialog?: boolean): Pr
res.json().then(done2, fail2); res.json().then(done2, fail2);
})) }))
.then(async res => { .then(async res => {
if (res.error) { if ('error' in res) {
if (res.error.id === 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370') { if (res.error.id === 'a8c724b3-6e9c-4b46-b1a8-bc3ed6258370') {
// SUSPENDED // SUSPENDED
if (forceShowDialog || $i && (token === $i.token || id === $i.id)) { if (forceShowDialog || $i && (token === $i.token || id === $i.id)) {

View File

@ -6,52 +6,11 @@
/* eslint-disable @typescript-eslint/explicit-function-return-type */ /* eslint-disable @typescript-eslint/explicit-function-return-type */
/* eslint-disable import/no-default-export */ /* eslint-disable import/no-default-export */
import { StoryObj } from '@storybook/vue3'; import { StoryObj } from '@storybook/vue3';
import { DefaultBodyType, HttpResponse, HttpResponseResolver, JsonBodyType, PathParams, http } from 'msw'; import { http } from 'msw';
import seedrandom from 'seedrandom';
import { action } from '@storybook/addon-actions';
import { commonHandlers } from '../../.storybook/mocks.js'; import { commonHandlers } from '../../.storybook/mocks.js';
import { getChartResolver } from '../../.storybook/charts.js';
import MkChart from './MkChart.vue'; import MkChart from './MkChart.vue';
function getChartArray(seed: string, limit: number, option?: { accumulate?: boolean, mul?: number }): number[] {
const rng = seedrandom(seed);
const max = Math.floor(option?.mul ?? 250 * rng());
let accumulation = 0;
const array: number[] = [];
for (let i = 0; i < limit; i++) {
const num = Math.floor((max + 1) * rng());
if (option?.accumulate) {
accumulation += num;
array.unshift(accumulation);
} else {
array.push(num);
}
}
return array;
}
export function getChartResolver(fields: string[], option?: { accumulate?: boolean, mulMap?: Record<string, number> }): HttpResponseResolver<PathParams, DefaultBodyType, JsonBodyType> {
return ({ request }) => {
action(`GET ${request.url}`)();
const limitParam = new URL(request.url).searchParams.get('limit');
const limit = limitParam ? parseInt(limitParam) : 30;
const res = {};
for (const field of fields) {
const layers = field.split('.');
let current = res;
while (layers.length > 1) {
const currentKey = layers.shift()!;
if (current[currentKey] == null) current[currentKey] = {};
current = current[currentKey];
}
current[layers[0]] = getChartArray(field, limit, {
accumulate: option?.accumulate,
mul: option?.mulMap != null && field in option.mulMap ? option.mulMap[field] : undefined,
});
}
return HttpResponse.json(res);
};
}
const Base = { const Base = {
render(args) { render(args) {
return { return {
@ -76,6 +35,7 @@ const Base = {
args: { args: {
src: 'federation', src: 'federation',
span: 'hour', span: 'hour',
nowForChromatic: 1716263640000,
}, },
parameters: { parameters: {
layout: 'centered', layout: 'centered',
@ -100,18 +60,21 @@ const Base = {
export const FederationChart = { export const FederationChart = {
...Base, ...Base,
args: { args: {
...Base.args,
src: 'federation', src: 'federation',
}, },
} satisfies StoryObj<typeof MkChart>; } satisfies StoryObj<typeof MkChart>;
export const NotesTotalChart = { export const NotesTotalChart = {
...Base, ...Base,
args: { args: {
...Base.args,
src: 'notes-total', src: 'notes-total',
}, },
} satisfies StoryObj<typeof MkChart>; } satisfies StoryObj<typeof MkChart>;
export const DriveChart = { export const DriveChart = {
...Base, ...Base,
args: { args: {
...Base.args,
src: 'drive', src: 'drive',
}, },
} satisfies StoryObj<typeof MkChart>; } satisfies StoryObj<typeof MkChart>;

View File

@ -77,6 +77,7 @@ const props = withDefaults(defineProps<{
stacked?: boolean; stacked?: boolean;
bar?: boolean; bar?: boolean;
aspectRatio?: number | null; aspectRatio?: number | null;
nowForChromatic?: number;
}>(), { }>(), {
args: undefined, args: undefined,
limit: 90, limit: 90,
@ -84,6 +85,13 @@ const props = withDefaults(defineProps<{
stacked: false, stacked: false,
bar: false, bar: false,
aspectRatio: null, aspectRatio: null,
/**
* @desc Overwrites current date to fix background lines of chart.
* @ignore Only used for Chromatic. Don't use this for production.
* @see https://github.com/misskey-dev/misskey/pull/13830#issuecomment-2155886151
*/
nowForChromatic: undefined,
}); });
const legendEl = shallowRef<InstanceType<typeof MkChartLegend>>(); const legendEl = shallowRef<InstanceType<typeof MkChartLegend>>();
@ -106,7 +114,8 @@ const getColor = (i) => {
return colorSets[i % colorSets.length]; return colorSets[i % colorSets.length];
}; };
const now = new Date(); // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const now = props.nowForChromatic != null ? new Date(props.nowForChromatic) : new Date();
let chartInstance: Chart | null = null; let chartInstance: Chart | null = null;
let chartData: { let chartData: {
series: { series: {

View File

@ -130,7 +130,7 @@ export default defineComponent({
el.style.left = ''; el.style.left = '';
} }
// eslint-disable-next-line vue/no-setup-props-destructure // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const classes = { const classes = {
[$style['date-separated-list']]: true, [$style['date-separated-list']]: true,
[$style['date-separated-list-nogap']]: props.noGap, [$style['date-separated-list-nogap']]: props.noGap,

View File

@ -8,8 +8,9 @@ import { StoryObj } from '@storybook/vue3';
import { HttpResponse, http } from 'msw'; import { HttpResponse, http } from 'msw';
import { federationInstance } from '../../.storybook/fakes.js'; import { federationInstance } from '../../.storybook/fakes.js';
import { commonHandlers } from '../../.storybook/mocks.js'; import { commonHandlers } from '../../.storybook/mocks.js';
import { getChartResolver } from '../../.storybook/charts.js';
import MkInstanceCardMini from './MkInstanceCardMini.vue'; import MkInstanceCardMini from './MkInstanceCardMini.vue';
import { getChartResolver } from './MkChart.stories.impl.js';
export const Default = { export const Default = {
render(args) { render(args) {
return { return {

View File

@ -126,7 +126,7 @@ function hasFocus() {
const playerEl = shallowRef<HTMLDivElement>(); const playerEl = shallowRef<HTMLDivElement>();
const audioEl = shallowRef<HTMLAudioElement>(); const audioEl = shallowRef<HTMLAudioElement>();
// eslint-disable-next-line vue/no-setup-props-destructure // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const hide = ref((defaultStore.state.nsfw === 'force' || defaultStore.state.dataSaver.media) ? true : (props.audio.isSensitive && defaultStore.state.nsfw !== 'ignore')); const hide = ref((defaultStore.state.nsfw === 'force' || defaultStore.state.dataSaver.media) ? true : (props.audio.isSensitive && defaultStore.state.nsfw !== 'ignore'));
// Menu // Menu

View File

@ -160,7 +160,7 @@ function hasFocus() {
return playerEl.value === document.activeElement || playerEl.value.contains(document.activeElement); return playerEl.value === document.activeElement || playerEl.value.contains(document.activeElement);
} }
// eslint-disable-next-line vue/no-setup-props-destructure // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const hide = ref((defaultStore.state.nsfw === 'force' || defaultStore.state.dataSaver.media) ? true : (props.video.isSensitive && defaultStore.state.nsfw !== 'ignore')); const hide = ref((defaultStore.state.nsfw === 'force' || defaultStore.state.dataSaver.media) ? true : (props.video.isSensitive && defaultStore.state.nsfw !== 'ignore'));
// Menu // Menu

View File

@ -6,14 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only
<template> <template>
<div :class="$style.root"> <div :class="$style.root">
<div :class="$style.head"> <div :class="$style.head">
<MkAvatar v-if="['pollEnded', 'note'].includes(notification.type) && notification.note" :class="$style.icon" :user="notification.note.user" link preview/> <MkAvatar v-if="['pollEnded', 'note'].includes(notification.type) && 'note' in notification" :class="$style.icon" :user="notification.note.user" link preview/>
<MkAvatar v-else-if="['roleAssigned', 'achievementEarned'].includes(notification.type)" :class="$style.icon" :user="$i" link preview/> <MkAvatar v-else-if="['roleAssigned', 'achievementEarned'].includes(notification.type)" :class="$style.icon" :user="$i" link preview/>
<div v-else-if="notification.type === 'reaction:grouped' && notification.note.reactionAcceptance === 'likeOnly'" :class="[$style.icon, $style.icon_reactionGroupHeart]"><i class="ti ti-heart" style="line-height: 1;"></i></div> <div v-else-if="notification.type === 'reaction:grouped' && notification.note.reactionAcceptance === 'likeOnly'" :class="[$style.icon, $style.icon_reactionGroupHeart]"><i class="ti ti-heart" style="line-height: 1;"></i></div>
<div v-else-if="notification.type === 'reaction:grouped'" :class="[$style.icon, $style.icon_reactionGroup]"><i class="ti ti-plus" style="line-height: 1;"></i></div> <div v-else-if="notification.type === 'reaction:grouped'" :class="[$style.icon, $style.icon_reactionGroup]"><i class="ti ti-plus" style="line-height: 1;"></i></div>
<div v-else-if="notification.type === 'renote:grouped'" :class="[$style.icon, $style.icon_renoteGroup]"><i class="ti ti-repeat" style="line-height: 1;"></i></div> <div v-else-if="notification.type === 'renote:grouped'" :class="[$style.icon, $style.icon_renoteGroup]"><i class="ti ti-repeat" style="line-height: 1;"></i></div>
<img v-else-if="notification.type === 'test'" :class="$style.icon" :src="infoImageUrl"/> <img v-else-if="notification.type === 'test'" :class="$style.icon" :src="infoImageUrl"/>
<MkAvatar v-else-if="notification.user" :class="$style.icon" :user="notification.user" link preview/> <MkAvatar v-else-if="'user' in notification" :class="$style.icon" :user="notification.user" link preview/>
<img v-else-if="notification.icon" :class="[$style.icon, $style.icon_app]" :src="notification.icon" alt=""/> <img v-else-if="'icon' in notification" :class="[$style.icon, $style.icon_app]" :src="notification.icon" alt=""/>
<div <div
:class="[$style.subIcon, { :class="[$style.subIcon, {
[$style.t_follow]: notification.type === 'follow', [$style.t_follow]: notification.type === 'follow',
@ -164,13 +164,13 @@ const props = withDefaults(defineProps<{
const followRequestDone = ref(false); const followRequestDone = ref(false);
const acceptFollowRequest = () => { const acceptFollowRequest = () => {
if (props.notification.user == null) return; if (!('user' in props.notification)) return;
followRequestDone.value = true; followRequestDone.value = true;
misskeyApi('following/requests/accept', { userId: props.notification.user.id }); misskeyApi('following/requests/accept', { userId: props.notification.user.id });
}; };
const rejectFollowRequest = () => { const rejectFollowRequest = () => {
if (props.notification.user == null) return; if (!('user' in props.notification)) return;
followRequestDone.value = true; followRequestDone.value = true;
misskeyApi('following/requests/reject', { userId: props.notification.user.id }); misskeyApi('following/requests/reject', { userId: props.notification.user.id });
}; };

View File

@ -172,7 +172,7 @@ const emit = defineEmits<{
const dialog = shallowRef<InstanceType<typeof MkModalWindow>>(); const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
// eslint-disable-next-line vue/no-setup-props-destructure // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const page = ref(props.initialPage ?? 0); const page = ref(props.initialPage ?? 0);
watch(page, (to) => { watch(page, (to) => {

View File

@ -148,7 +148,7 @@ const emit = defineEmits<{
const dialog = shallowRef<InstanceType<typeof MkModalWindow>>(); const dialog = shallowRef<InstanceType<typeof MkModalWindow>>();
// eslint-disable-next-line vue/no-setup-props-destructure // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const page = ref(defaultStore.state.accountSetupWizard); const page = ref(defaultStore.state.accountSetupWizard);
watch(page, () => { watch(page, () => {

View File

@ -41,12 +41,12 @@ function getDateSafe(n: Date | string | number) {
} }
} }
// eslint-disable-next-line vue/no-setup-props-destructure // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const _time = props.time == null ? NaN : getDateSafe(props.time).getTime(); const _time = props.time == null ? NaN : getDateSafe(props.time).getTime();
const invalid = Number.isNaN(_time); const invalid = Number.isNaN(_time);
const absolute = !invalid ? dateTimeFormat.format(_time) : i18n.ts._ago.invalid; const absolute = !invalid ? dateTimeFormat.format(_time) : i18n.ts._ago.invalid;
// eslint-disable-next-line vue/no-setup-props-destructure // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const now = ref(props.origin?.getTime() ?? Date.now()); const now = ref(props.origin?.getTime() ?? Date.now());
const ago = computed(() => (now.value - _time) / 1000/*ms*/); const ago = computed(() => (now.value - _time) / 1000/*ms*/);

View File

@ -109,6 +109,15 @@ definePageMetadata(() => ({
</script> </script>
<style lang="scss" module> <style lang="scss" module>
.fadeEnterActive,
.fadeLeaveActive {
transition: opacity 0.125s ease;
}
.fadeEnterFrom,
.fadeLeaveTo {
opacity: 0;
}
.announcement { .announcement {
padding: 16px; padding: 16px;
} }

View File

@ -169,7 +169,7 @@ const props = defineProps<{
const showBoardLabels = ref<boolean>(false); const showBoardLabels = ref<boolean>(false);
const useAvatarAsStone = ref<boolean>(true); const useAvatarAsStone = ref<boolean>(true);
const autoplaying = ref<boolean>(false); const autoplaying = ref<boolean>(false);
// eslint-disable-next-line vue/no-setup-props-destructure // eslint-disable-next-line vue/no-setup-props-reactivity-loss
const game = ref<Misskey.entities.ReversiGameDetailed & { logs: Reversi.Serializer.SerializedLog[] }>(deepClone(props.game)); const game = ref<Misskey.entities.ReversiGameDetailed & { logs: Reversi.Serializer.SerializedLog[] }>(deepClone(props.game));
const logPos = ref<number>(game.value.logs.length); const logPos = ref<number>(game.value.logs.length);
const engine = shallowRef<Reversi.Game>(Reversi.Serializer.restoreGame({ const engine = shallowRef<Reversi.Game>(Reversi.Serializer.restoreGame({

View File

@ -20,6 +20,7 @@ import { useStream } from '@/stream.js';
import { signinRequired } from '@/account.js'; import { signinRequired } from '@/account.js';
import { useRouter } from '@/router/supplier.js'; import { useRouter } from '@/router/supplier.js';
import * as os from '@/os.js'; import * as os from '@/os.js';
import { url } from '@/config.js';
import { i18n } from '@/i18n.js'; import { i18n } from '@/i18n.js';
import { useInterval } from '@/scripts/use-interval.js'; import { useInterval } from '@/scripts/use-interval.js';
@ -44,7 +45,7 @@ function start(_game: Misskey.entities.ReversiGameDetailed) {
if (shareWhenStart.value) { if (shareWhenStart.value) {
misskeyApi('notes/create', { misskeyApi('notes/create', {
text: i18n.ts._reversi.iStartedAGame + '\n' + location.href, text: `${i18n.ts._reversi.iStartedAGame}\n${url}/reversi/g/${props.gameId}`,
visibility: 'home', visibility: 'home',
}); });
} }

View File

@ -392,11 +392,12 @@ onUnmounted(() => {
> .name { > .name {
display: block; display: block;
margin: 0; margin: -10px;
padding: 10px;
line-height: 32px; line-height: 32px;
font-weight: bold; font-weight: bold;
font-size: 1.8em; font-size: 1.8em;
text-shadow: 0 0 8px #000; filter: drop-shadow(0 0 4px #000);
} }
> .bottom { > .bottom {

View File

@ -81,16 +81,19 @@ defineExpose<WidgetComponentExpose>({
.body { .body {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: clip; overflow: clip;
margin-left: -10px;
padding: 10px;
} }
.name { .name {
color: #fff; color: #fff;
filter: drop-shadow(0 0 4px #000); filter: drop-shadow(0 0 4px #000) drop-shadow(0 0 0.1px rgba(0, 0, 0, 0.5));
font-weight: bold; font-weight: bold;
} }
.host { .host {
color: #fff; color: #fff;
filter: drop-shadow(0 0 4px #000); filter: drop-shadow(0 0 4px #000) drop-shadow(0 0 0.1px rgba(0, 0, 0, 0.5));
} }
</style> </style>

View File

@ -82,16 +82,19 @@ defineExpose<WidgetComponentExpose>({
.body { .body {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: clip; overflow: clip;
margin-left: -10px;
padding: 10px;
} }
.name { .name {
color: #fff; color: #fff;
filter: drop-shadow(0 0 4px #000); filter: drop-shadow(0 0 4px #000) drop-shadow(0 0 0.1px rgba(0, 0, 0, 0.5));
font-weight: bold; font-weight: bold;
} }
.username { .username {
color: #fff; color: #fff;
filter: drop-shadow(0 0 4px #000); filter: drop-shadow(0 0 4px #000) drop-shadow(0 0 0.1px rgba(0, 0, 0, 0.5));
font-weight: normal;
} }
</style> </style>

View File

@ -37,7 +37,8 @@
], ],
"lib": [ "lib": [
"esnext", "esnext",
"dom" "dom",
"dom.iterable"
], ],
"jsx": "preserve" "jsx": "preserve"
}, },

View File

@ -51,7 +51,7 @@
"nodemon": "3.1.0", "nodemon": "3.1.0",
"execa": "8.0.1", "execa": "8.0.1",
"tsd": "0.30.7", "tsd": "0.30.7",
"typescript": "5.4.5", "typescript": "5.5.2",
"esbuild": "0.19.11", "esbuild": "0.19.11",
"glob": "10.3.12" "glob": "10.3.12"
}, },

View File

@ -20,7 +20,7 @@
"eslint": "8.57.0", "eslint": "8.57.0",
"eslint-plugin-import": "2.29.1", "eslint-plugin-import": "2.29.1",
"nodemon": "3.1.0", "nodemon": "3.1.0",
"typescript": "5.4.5" "typescript": "5.5.2"
}, },
"type": "module" "type": "module"
} }

View File

@ -43,8 +43,8 @@ importers:
specifier: 5.30.3 specifier: 5.30.3
version: 5.30.3 version: 5.30.3
typescript: typescript:
specifier: 5.4.5 specifier: 5.5.2
version: 5.4.5 version: 5.5.2
optionalDependencies: optionalDependencies:
'@tensorflow/tfjs-core': '@tensorflow/tfjs-core':
specifier: 4.4.0 specifier: 4.4.0
@ -55,10 +55,10 @@ importers:
version: 20.12.7 version: 20.12.7
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(eslint@8.57.0)(typescript@5.5.2)
cross-env: cross-env:
specifier: 7.0.3 specifier: 7.0.3
version: 7.0.3 version: 7.0.3
@ -414,8 +414,8 @@ importers:
specifier: 0.3.20 specifier: 0.3.20
version: 0.3.20(ioredis@5.4.1)(pg@8.11.5) version: 0.3.20(ioredis@5.4.1)(pg@8.11.5)
typescript: typescript:
specifier: 5.4.5 specifier: 5.5.2
version: 5.4.5 version: 5.5.2
ulid: ulid:
specifier: 2.3.0 specifier: 2.3.0
version: 2.3.0 version: 2.3.0
@ -525,7 +525,7 @@ importers:
version: 29.7.0 version: 29.7.0
'@misskey-dev/eslint-plugin': '@misskey-dev/eslint-plugin':
specifier: 1.0.0 specifier: 1.0.0
version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0) version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0)
'@nestjs/platform-express': '@nestjs/platform-express':
specifier: 10.3.8 specifier: 10.3.8
version: 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8) version: 10.3.8(@nestjs/common@10.3.8(reflect-metadata@0.2.2)(rxjs@7.8.1))(@nestjs/core@10.3.8)
@ -651,10 +651,10 @@ importers:
version: 8.5.10 version: 8.5.10
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(eslint@8.57.0)(typescript@5.5.2)
aws-sdk-client-mock: aws-sdk-client-mock:
specifier: 3.0.1 specifier: 3.0.1
version: 3.0.1 version: 3.0.1
@ -666,7 +666,7 @@ importers:
version: 8.57.0 version: 8.57.0
eslint-plugin-import: eslint-plugin-import:
specifier: 2.29.1 specifier: 2.29.1
version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)
execa: execa:
specifier: 8.0.1 specifier: 8.0.1
version: 8.0.1 version: 8.0.1
@ -723,7 +723,7 @@ importers:
version: 15.1.1 version: 15.1.1
'@vitejs/plugin-vue': '@vitejs/plugin-vue':
specifier: 5.0.4 specifier: 5.0.4
version: 5.0.4(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.4.5)) version: 5.0.4(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.5.2))
'@vue/compiler-sfc': '@vue/compiler-sfc':
specifier: 3.4.26 specifier: 3.4.26
version: 3.4.26 version: 3.4.26
@ -845,27 +845,27 @@ importers:
specifier: 4.2.0 specifier: 4.2.0
version: 4.2.0 version: 4.2.0
typescript: typescript:
specifier: 5.4.5 specifier: 5.5.2
version: 5.4.5 version: 5.5.2
uuid: uuid:
specifier: 9.0.1 specifier: 9.0.1
version: 9.0.1 version: 9.0.1
v-code-diff: v-code-diff:
specifier: 1.11.0 specifier: 1.11.0
version: 1.11.0(vue@3.4.26(typescript@5.4.5)) version: 1.11.0(vue@3.4.26(typescript@5.5.2))
vite: vite:
specifier: 5.2.11 specifier: 5.2.11
version: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) version: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)
vue: vue:
specifier: 3.4.26 specifier: 3.4.26
version: 3.4.26(typescript@5.4.5) version: 3.4.26(typescript@5.5.2)
vuedraggable: vuedraggable:
specifier: next specifier: next
version: 4.1.0(vue@3.4.26(typescript@5.4.5)) version: 4.1.0(vue@3.4.26(typescript@5.5.2))
devDependencies: devDependencies:
'@misskey-dev/eslint-plugin': '@misskey-dev/eslint-plugin':
specifier: 1.0.0 specifier: 1.0.0
version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0) version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0)
'@misskey-dev/summaly': '@misskey-dev/summaly':
specifier: 5.1.0 specifier: 5.1.0
version: 5.1.0 version: 5.1.0
@ -904,10 +904,10 @@ importers:
version: 8.0.9 version: 8.0.9
'@storybook/react': '@storybook/react':
specifier: 8.0.9 specifier: 8.0.9
version: 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) version: 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.2)
'@storybook/react-vite': '@storybook/react-vite':
specifier: 8.0.9 specifier: 8.0.9
version: 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.17.2)(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)) version: 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.17.2)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))
'@storybook/test': '@storybook/test':
specifier: 8.0.9 specifier: 8.0.9
version: 8.0.9(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)) version: 8.0.9(@jest/globals@29.7.0)(@types/jest@29.5.12)(jest@29.7.0(@types/node@20.12.7))(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3))
@ -919,13 +919,13 @@ importers:
version: 8.0.9 version: 8.0.9
'@storybook/vue3': '@storybook/vue3':
specifier: 8.0.9 specifier: 8.0.9
version: 8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.4.5)) version: 8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.5.2))
'@storybook/vue3-vite': '@storybook/vue3-vite':
specifier: 8.0.9 specifier: 8.0.9
version: 8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.4.5)) version: 8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.5.2))
'@testing-library/vue': '@testing-library/vue':
specifier: 8.0.3 specifier: 8.0.3
version: 8.0.3(@vue/compiler-sfc@3.4.26)(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.4.5)))(vue@3.4.26(typescript@5.4.5)) version: 8.0.3(@vue/compiler-sfc@3.4.26)(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2)))(vue@3.4.26(typescript@5.5.2))
'@types/escape-regexp': '@types/escape-regexp':
specifier: 0.0.3 specifier: 0.0.3
version: 0.0.3 version: 0.0.3
@ -964,10 +964,10 @@ importers:
version: 8.5.10 version: 8.5.10
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(eslint@8.57.0)(typescript@5.5.2)
'@vitest/coverage-v8': '@vitest/coverage-v8':
specifier: 0.34.6 specifier: 0.34.6
version: 0.34.6(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3)) version: 0.34.6(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3))
@ -988,7 +988,7 @@ importers:
version: 8.57.0 version: 8.57.0
eslint-plugin-import: eslint-plugin-import:
specifier: 2.29.1 specifier: 2.29.1
version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)
eslint-plugin-vue: eslint-plugin-vue:
specifier: 9.25.0 specifier: 9.25.0
version: 9.25.0(eslint@8.57.0) version: 9.25.0(eslint@8.57.0)
@ -1006,10 +1006,10 @@ importers:
version: 4.0.5 version: 4.0.5
msw: msw:
specifier: 2.2.14 specifier: 2.2.14
version: 2.2.14(typescript@5.4.5) version: 2.2.14(typescript@5.5.2)
msw-storybook-addon: msw-storybook-addon:
specifier: 2.0.1 specifier: 2.0.1
version: 2.0.1(msw@2.2.14(typescript@5.4.5)) version: 2.0.1(msw@2.2.14(typescript@5.5.2))
nodemon: nodemon:
specifier: 3.1.0 specifier: 3.1.0
version: 3.1.0 version: 3.1.0
@ -1051,7 +1051,7 @@ importers:
version: 9.4.2(eslint@8.57.0) version: 9.4.2(eslint@8.57.0)
vue-tsc: vue-tsc:
specifier: 2.0.16 specifier: 2.0.16
version: 2.0.16(typescript@5.4.5) version: 2.0.16(typescript@5.5.2)
packages/misskey-bubble-game: packages/misskey-bubble-game:
dependencies: dependencies:
@ -1116,7 +1116,7 @@ importers:
version: 7.43.1(@types/node@20.12.7) version: 7.43.1(@types/node@20.12.7)
'@misskey-dev/eslint-plugin': '@misskey-dev/eslint-plugin':
specifier: 1.0.0 specifier: 1.0.0
version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0) version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0)
'@swc/jest': '@swc/jest':
specifier: 0.2.36 specifier: 0.2.36
version: 0.2.36(@swc/core@1.4.17) version: 0.2.36(@swc/core@1.4.17)
@ -1128,10 +1128,10 @@ importers:
version: 20.12.7 version: 20.12.7
'@typescript-eslint/eslint-plugin': '@typescript-eslint/eslint-plugin':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(eslint@8.57.0)(typescript@5.5.2)
esbuild: esbuild:
specifier: 0.19.11 specifier: 0.19.11
version: 0.19.11 version: 0.19.11
@ -1166,8 +1166,8 @@ importers:
specifier: 0.30.7 specifier: 0.30.7
version: 0.30.7 version: 0.30.7
typescript: typescript:
specifier: 5.4.5 specifier: 5.5.2
version: 5.4.5 version: 5.5.2
packages/misskey-js/generator: packages/misskey-js/generator:
devDependencies: devDependencies:
@ -1256,10 +1256,10 @@ importers:
devDependencies: devDependencies:
'@misskey-dev/eslint-plugin': '@misskey-dev/eslint-plugin':
specifier: 1.0.0 specifier: 1.0.0
version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0) version: 1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0)
'@typescript-eslint/parser': '@typescript-eslint/parser':
specifier: 7.7.1 specifier: 7.7.1
version: 7.7.1(eslint@8.57.0)(typescript@5.4.5) version: 7.7.1(eslint@8.57.0)(typescript@5.5.2)
'@typescript/lib-webworker': '@typescript/lib-webworker':
specifier: npm:@types/serviceworker@0.0.67 specifier: npm:@types/serviceworker@0.0.67
version: '@types/serviceworker@0.0.67' version: '@types/serviceworker@0.0.67'
@ -1268,13 +1268,13 @@ importers:
version: 8.57.0 version: 8.57.0
eslint-plugin-import: eslint-plugin-import:
specifier: 2.29.1 specifier: 2.29.1
version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) version: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)
nodemon: nodemon:
specifier: 3.1.0 specifier: 3.1.0
version: 3.1.0 version: 3.1.0
typescript: typescript:
specifier: 5.4.5 specifier: 5.5.2
version: 5.4.5 version: 5.5.2
packages: packages:
@ -10836,8 +10836,8 @@ packages:
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
typescript@5.4.5: typescript@5.5.2:
resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} resolution: {integrity: sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==}
engines: {node: '>=14.17'} engines: {node: '>=14.17'}
hasBin: true hasBin: true
@ -13662,15 +13662,15 @@ snapshots:
'@types/yargs': 17.0.19 '@types/yargs': 17.0.19
chalk: 4.1.2 chalk: 4.1.2
'@joshwooding/vite-plugin-react-docgen-typescript@0.3.0(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))': '@joshwooding/vite-plugin-react-docgen-typescript@0.3.0(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))':
dependencies: dependencies:
glob: 7.2.3 glob: 7.2.3
glob-promise: 4.2.2(glob@7.2.3) glob-promise: 4.2.2(glob@7.2.3)
magic-string: 0.27.0 magic-string: 0.27.0
react-docgen-typescript: 2.2.2(typescript@5.4.5) react-docgen-typescript: 2.2.2(typescript@5.5.2)
vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
'@jridgewell/gen-mapping@0.3.2': '@jridgewell/gen-mapping@0.3.2':
dependencies: dependencies:
@ -13785,12 +13785,12 @@ snapshots:
eslint: 8.57.0 eslint: 8.57.0
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.1.0(eslint@8.57.0)(typescript@5.3.3))(eslint@8.57.0)
'@misskey-dev/eslint-plugin@1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0))(eslint@8.57.0)': '@misskey-dev/eslint-plugin@1.0.0(@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2))(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0))(eslint@8.57.0)':
dependencies: dependencies:
'@typescript-eslint/eslint-plugin': 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/eslint-plugin': 7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.2)
eslint: 8.57.0 eslint: 8.57.0
eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0) eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)
'@misskey-dev/sharp-read-bmp@1.2.0': '@misskey-dev/sharp-read-bmp@1.2.0':
dependencies: dependencies:
@ -15020,7 +15020,7 @@ snapshots:
- encoding - encoding
- supports-color - supports-color
'@storybook/builder-vite@8.0.9(encoding@0.1.13)(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))': '@storybook/builder-vite@8.0.9(encoding@0.1.13)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))':
dependencies: dependencies:
'@storybook/channels': 8.0.9 '@storybook/channels': 8.0.9
'@storybook/client-logger': 8.0.9 '@storybook/client-logger': 8.0.9
@ -15041,7 +15041,7 @@ snapshots:
ts-dedent: 2.2.0 ts-dedent: 2.2.0
vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
- supports-color - supports-color
@ -15339,13 +15339,13 @@ snapshots:
react: 18.3.1 react: 18.3.1
react-dom: 18.3.1(react@18.3.1) react-dom: 18.3.1(react@18.3.1)
'@storybook/react-vite@8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.17.2)(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))': '@storybook/react-vite@8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(rollup@4.17.2)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))':
dependencies: dependencies:
'@joshwooding/vite-plugin-react-docgen-typescript': 0.3.0(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)) '@joshwooding/vite-plugin-react-docgen-typescript': 0.3.0(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))
'@rollup/pluginutils': 5.1.0(rollup@4.17.2) '@rollup/pluginutils': 5.1.0(rollup@4.17.2)
'@storybook/builder-vite': 8.0.9(encoding@0.1.13)(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)) '@storybook/builder-vite': 8.0.9(encoding@0.1.13)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))
'@storybook/node-logger': 8.0.9 '@storybook/node-logger': 8.0.9
'@storybook/react': 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5) '@storybook/react': 8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.2)
find-up: 5.0.0 find-up: 5.0.0
magic-string: 0.30.7 magic-string: 0.30.7
react: 18.3.1 react: 18.3.1
@ -15362,7 +15362,7 @@ snapshots:
- typescript - typescript
- vite-plugin-glimmerx - vite-plugin-glimmerx
'@storybook/react@8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.4.5)': '@storybook/react@8.0.9(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.5.2)':
dependencies: dependencies:
'@storybook/client-logger': 8.0.9 '@storybook/client-logger': 8.0.9
'@storybook/docs-tools': 8.0.9(encoding@0.1.13) '@storybook/docs-tools': 8.0.9(encoding@0.1.13)
@ -15388,7 +15388,7 @@ snapshots:
type-fest: 2.19.0 type-fest: 2.19.0
util-deprecate: 1.0.2 util-deprecate: 1.0.2
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
- supports-color - supports-color
@ -15456,17 +15456,17 @@ snapshots:
'@types/express': 4.17.17 '@types/express': 4.17.17
file-system-cache: 2.3.0 file-system-cache: 2.3.0
'@storybook/vue3-vite@8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.4.5))': '@storybook/vue3-vite@8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.5.2))':
dependencies: dependencies:
'@storybook/builder-vite': 8.0.9(encoding@0.1.13)(typescript@5.4.5)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)) '@storybook/builder-vite': 8.0.9(encoding@0.1.13)(typescript@5.5.2)(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))
'@storybook/core-server': 8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3) '@storybook/core-server': 8.0.9(bufferutil@4.0.7)(encoding@0.1.13)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(utf-8-validate@6.0.3)
'@storybook/vue3': 8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.4.5)) '@storybook/vue3': 8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.5.2))
find-package-json: 1.2.0 find-package-json: 1.2.0
magic-string: 0.30.7 magic-string: 0.30.7
typescript: 5.4.5 typescript: 5.5.2
vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)
vue-component-meta: 2.0.16(typescript@5.4.5) vue-component-meta: 2.0.16(typescript@5.5.2)
vue-docgen-api: 4.75.1(vue@3.4.26(typescript@5.4.5)) vue-docgen-api: 4.75.1(vue@3.4.26(typescript@5.5.2))
transitivePeerDependencies: transitivePeerDependencies:
- '@preact/preset-vite' - '@preact/preset-vite'
- bufferutil - bufferutil
@ -15478,7 +15478,7 @@ snapshots:
- vite-plugin-glimmerx - vite-plugin-glimmerx
- vue - vue
'@storybook/vue3@8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.4.5))': '@storybook/vue3@8.0.9(encoding@0.1.13)(vue@3.4.26(typescript@5.5.2))':
dependencies: dependencies:
'@storybook/docs-tools': 8.0.9(encoding@0.1.13) '@storybook/docs-tools': 8.0.9(encoding@0.1.13)
'@storybook/global': 5.0.0 '@storybook/global': 5.0.0
@ -15488,7 +15488,7 @@ snapshots:
lodash: 4.17.21 lodash: 4.17.21
ts-dedent: 2.2.0 ts-dedent: 2.2.0
type-fest: 2.19.0 type-fest: 2.19.0
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
vue-component-type-helpers: 2.0.21 vue-component-type-helpers: 2.0.21
transitivePeerDependencies: transitivePeerDependencies:
- encoding - encoding
@ -15750,12 +15750,12 @@ snapshots:
dependencies: dependencies:
'@testing-library/dom': 9.3.4 '@testing-library/dom': 9.3.4
'@testing-library/vue@8.0.3(@vue/compiler-sfc@3.4.26)(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.4.5)))(vue@3.4.26(typescript@5.4.5))': '@testing-library/vue@8.0.3(@vue/compiler-sfc@3.4.26)(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2)))(vue@3.4.26(typescript@5.5.2))':
dependencies: dependencies:
'@babel/runtime': 7.23.4 '@babel/runtime': 7.23.4
'@testing-library/dom': 9.3.3 '@testing-library/dom': 9.3.3
'@vue/test-utils': 2.4.1(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.4.5)))(vue@3.4.26(typescript@5.4.5)) '@vue/test-utils': 2.4.1(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2)))(vue@3.4.26(typescript@5.5.2))
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
optionalDependencies: optionalDependencies:
'@vue/compiler-sfc': 3.4.26 '@vue/compiler-sfc': 3.4.26
transitivePeerDependencies: transitivePeerDependencies:
@ -16236,13 +16236,13 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)': '@typescript-eslint/eslint-plugin@7.7.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0)(typescript@5.5.2)':
dependencies: dependencies:
'@eslint-community/regexpp': 4.10.0 '@eslint-community/regexpp': 4.10.0
'@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/scope-manager': 7.7.1 '@typescript-eslint/scope-manager': 7.7.1
'@typescript-eslint/type-utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/type-utils': 7.7.1(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.5.2)
'@typescript-eslint/visitor-keys': 7.7.1 '@typescript-eslint/visitor-keys': 7.7.1
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.57.0 eslint: 8.57.0
@ -16250,9 +16250,9 @@ snapshots:
ignore: 5.3.1 ignore: 5.3.1
natural-compare: 1.4.0 natural-compare: 1.4.0
semver: 7.6.0 semver: 7.6.0
ts-api-utils: 1.3.0(typescript@5.4.5) ts-api-utils: 1.3.0(typescript@5.5.2)
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -16282,16 +16282,16 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5)': '@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2)':
dependencies: dependencies:
'@typescript-eslint/scope-manager': 7.7.1 '@typescript-eslint/scope-manager': 7.7.1
'@typescript-eslint/types': 7.7.1 '@typescript-eslint/types': 7.7.1
'@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.5.2)
'@typescript-eslint/visitor-keys': 7.7.1 '@typescript-eslint/visitor-keys': 7.7.1
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.57.0 eslint: 8.57.0
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -16334,15 +16334,15 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/type-utils@7.7.1(eslint@8.57.0)(typescript@5.4.5)': '@typescript-eslint/type-utils@7.7.1(eslint@8.57.0)(typescript@5.5.2)':
dependencies: dependencies:
'@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.5.2)
'@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/utils': 7.7.1(eslint@8.57.0)(typescript@5.5.2)
debug: 4.3.4(supports-color@8.1.1) debug: 4.3.4(supports-color@8.1.1)
eslint: 8.57.0 eslint: 8.57.0
ts-api-utils: 1.3.0(typescript@5.4.5) ts-api-utils: 1.3.0(typescript@5.5.2)
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -16381,7 +16381,7 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
'@typescript-eslint/typescript-estree@7.7.1(typescript@5.4.5)': '@typescript-eslint/typescript-estree@7.7.1(typescript@5.5.2)':
dependencies: dependencies:
'@typescript-eslint/types': 7.7.1 '@typescript-eslint/types': 7.7.1
'@typescript-eslint/visitor-keys': 7.7.1 '@typescript-eslint/visitor-keys': 7.7.1
@ -16390,9 +16390,9 @@ snapshots:
is-glob: 4.0.3 is-glob: 4.0.3
minimatch: 9.0.4 minimatch: 9.0.4
semver: 7.6.0 semver: 7.6.0
ts-api-utils: 1.3.0(typescript@5.4.5) ts-api-utils: 1.3.0(typescript@5.5.2)
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
@ -16424,14 +16424,14 @@ snapshots:
- supports-color - supports-color
- typescript - typescript
'@typescript-eslint/utils@7.7.1(eslint@8.57.0)(typescript@5.4.5)': '@typescript-eslint/utils@7.7.1(eslint@8.57.0)(typescript@5.5.2)':
dependencies: dependencies:
'@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
'@types/json-schema': 7.0.15 '@types/json-schema': 7.0.15
'@types/semver': 7.5.8 '@types/semver': 7.5.8
'@typescript-eslint/scope-manager': 7.7.1 '@typescript-eslint/scope-manager': 7.7.1
'@typescript-eslint/types': 7.7.1 '@typescript-eslint/types': 7.7.1
'@typescript-eslint/typescript-estree': 7.7.1(typescript@5.4.5) '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.5.2)
eslint: 8.57.0 eslint: 8.57.0
semver: 7.6.0 semver: 7.6.0
transitivePeerDependencies: transitivePeerDependencies:
@ -16455,10 +16455,10 @@ snapshots:
'@ungap/structured-clone@1.2.0': {} '@ungap/structured-clone@1.2.0': {}
'@vitejs/plugin-vue@5.0.4(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.4.5))': '@vitejs/plugin-vue@5.0.4(vite@5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3))(vue@3.4.26(typescript@5.5.2))':
dependencies: dependencies:
vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3) vite: 5.2.11(@types/node@20.12.7)(sass@1.76.0)(terser@5.30.3)
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
'@vitest/coverage-v8@0.34.6(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3))': '@vitest/coverage-v8@0.34.6(vitest@0.34.6(happy-dom@10.0.3)(jsdom@24.0.0(bufferutil@4.0.7)(utf-8-validate@6.0.3))(sass@1.76.0)(terser@5.30.3))':
dependencies: dependencies:
@ -16604,7 +16604,7 @@ snapshots:
'@vue/devtools-api@6.6.1': {} '@vue/devtools-api@6.6.1': {}
'@vue/language-core@2.0.16(typescript@5.4.5)': '@vue/language-core@2.0.16(typescript@5.5.2)':
dependencies: dependencies:
'@volar/language-core': 2.2.0 '@volar/language-core': 2.2.0
'@vue/compiler-dom': 3.4.25 '@vue/compiler-dom': 3.4.25
@ -16614,7 +16614,7 @@ snapshots:
path-browserify: 1.0.1 path-browserify: 1.0.1
vue-template-compiler: 2.7.14 vue-template-compiler: 2.7.14
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
'@vue/reactivity@3.4.26': '@vue/reactivity@3.4.26':
dependencies: dependencies:
@ -16631,11 +16631,11 @@ snapshots:
'@vue/shared': 3.4.26 '@vue/shared': 3.4.26
csstype: 3.1.3 csstype: 3.1.3
'@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.4.5))': '@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2))':
dependencies: dependencies:
'@vue/compiler-ssr': 3.4.26 '@vue/compiler-ssr': 3.4.26
'@vue/shared': 3.4.26 '@vue/shared': 3.4.26
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
'@vue/shared@3.4.21': {} '@vue/shared@3.4.21': {}
@ -16643,13 +16643,13 @@ snapshots:
'@vue/shared@3.4.26': {} '@vue/shared@3.4.26': {}
'@vue/test-utils@2.4.1(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.4.5)))(vue@3.4.26(typescript@5.4.5))': '@vue/test-utils@2.4.1(@vue/server-renderer@3.4.26(vue@3.4.26(typescript@5.5.2)))(vue@3.4.26(typescript@5.5.2))':
dependencies: dependencies:
js-beautify: 1.14.9 js-beautify: 1.14.9
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
vue-component-type-helpers: 1.8.4 vue-component-type-helpers: 1.8.4
optionalDependencies: optionalDependencies:
'@vue/server-renderer': 3.4.26(vue@3.4.26(typescript@5.4.5)) '@vue/server-renderer': 3.4.26(vue@3.4.26(typescript@5.5.2))
'@webgpu/types@0.1.30': {} '@webgpu/types@0.1.30': {}
@ -18423,11 +18423,11 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
eslint-module-utils@2.8.0(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0): eslint-module-utils@2.8.0(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0):
dependencies: dependencies:
debug: 3.2.7(supports-color@8.1.1) debug: 3.2.7(supports-color@8.1.1)
optionalDependencies: optionalDependencies:
'@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.2)
eslint: 8.57.0 eslint: 8.57.0
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
transitivePeerDependencies: transitivePeerDependencies:
@ -18487,7 +18487,7 @@ snapshots:
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
- supports-color - supports-color
eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0): eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint@8.57.0):
dependencies: dependencies:
array-includes: 3.1.7 array-includes: 3.1.7
array.prototype.findlastindex: 1.2.3 array.prototype.findlastindex: 1.2.3
@ -18497,7 +18497,7 @@ snapshots:
doctrine: 2.1.0 doctrine: 2.1.0
eslint: 8.57.0 eslint: 8.57.0
eslint-import-resolver-node: 0.3.9 eslint-import-resolver-node: 0.3.9
eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0) eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.7.1(eslint@8.57.0)(typescript@5.5.2))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0)
hasown: 2.0.0 hasown: 2.0.0
is-core-module: 2.13.1 is-core-module: 2.13.1
is-glob: 4.0.3 is-glob: 4.0.3
@ -18508,7 +18508,7 @@ snapshots:
semver: 6.3.1 semver: 6.3.1
tsconfig-paths: 3.15.0 tsconfig-paths: 3.15.0
optionalDependencies: optionalDependencies:
'@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/parser': 7.7.1(eslint@8.57.0)(typescript@5.5.2)
transitivePeerDependencies: transitivePeerDependencies:
- eslint-import-resolver-typescript - eslint-import-resolver-typescript
- eslint-import-resolver-webpack - eslint-import-resolver-webpack
@ -21148,12 +21148,12 @@ snapshots:
optionalDependencies: optionalDependencies:
msgpackr-extract: 3.0.2 msgpackr-extract: 3.0.2
msw-storybook-addon@2.0.1(msw@2.2.14(typescript@5.4.5)): msw-storybook-addon@2.0.1(msw@2.2.14(typescript@5.5.2)):
dependencies: dependencies:
is-node-process: 1.2.0 is-node-process: 1.2.0
msw: 2.2.14(typescript@5.4.5) msw: 2.2.14(typescript@5.5.2)
msw@2.2.14(typescript@5.4.5): msw@2.2.14(typescript@5.5.2):
dependencies: dependencies:
'@bundled-es-modules/cookie': 2.0.0 '@bundled-es-modules/cookie': 2.0.0
'@bundled-es-modules/statuses': 1.0.1 '@bundled-es-modules/statuses': 1.0.1
@ -21173,7 +21173,7 @@ snapshots:
type-fest: 4.9.0 type-fest: 4.9.0
yargs: 17.7.2 yargs: 17.7.2
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
muggle-string@0.4.1: {} muggle-string@0.4.1: {}
@ -22284,9 +22284,9 @@ snapshots:
react: 18.3.1 react: 18.3.1
react-dom: 18.3.1(react@18.3.1) react-dom: 18.3.1(react@18.3.1)
react-docgen-typescript@2.2.2(typescript@5.4.5): react-docgen-typescript@2.2.2(typescript@5.5.2):
dependencies: dependencies:
typescript: 5.4.5 typescript: 5.5.2
react-docgen@7.0.1: react-docgen@7.0.1:
dependencies: dependencies:
@ -23405,9 +23405,9 @@ snapshots:
dependencies: dependencies:
typescript: 5.3.3 typescript: 5.3.3
ts-api-utils@1.3.0(typescript@5.4.5): ts-api-utils@1.3.0(typescript@5.5.2):
dependencies: dependencies:
typescript: 5.4.5 typescript: 5.5.2
ts-case-convert@2.0.2: {} ts-case-convert@2.0.2: {}
@ -23547,7 +23547,7 @@ snapshots:
typescript@5.4.2: {} typescript@5.4.2: {}
typescript@5.4.5: {} typescript@5.5.2: {}
ufo@1.3.2: {} ufo@1.3.2: {}
@ -23694,14 +23694,14 @@ snapshots:
uuid@9.0.1: {} uuid@9.0.1: {}
v-code-diff@1.11.0(vue@3.4.26(typescript@5.4.5)): v-code-diff@1.11.0(vue@3.4.26(typescript@5.5.2)):
dependencies: dependencies:
diff: 5.1.0 diff: 5.1.0
diff-match-patch: 1.0.5 diff-match-patch: 1.0.5
highlight.js: 11.9.0 highlight.js: 11.9.0
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
vue-demi: 0.14.7(vue@3.4.26(typescript@5.4.5)) vue-demi: 0.14.7(vue@3.4.26(typescript@5.5.2))
vue-i18n: 9.13.1(vue@3.4.26(typescript@5.4.5)) vue-i18n: 9.13.1(vue@3.4.26(typescript@5.5.2))
v8-to-istanbul@9.2.0: v8-to-istanbul@9.2.0:
dependencies: dependencies:
@ -23834,14 +23834,14 @@ snapshots:
dependencies: dependencies:
vscode-languageserver-protocol: 3.17.5 vscode-languageserver-protocol: 3.17.5
vue-component-meta@2.0.16(typescript@5.4.5): vue-component-meta@2.0.16(typescript@5.5.2):
dependencies: dependencies:
'@volar/typescript': 2.2.0 '@volar/typescript': 2.2.0
'@vue/language-core': 2.0.16(typescript@5.4.5) '@vue/language-core': 2.0.16(typescript@5.5.2)
path-browserify: 1.0.1 path-browserify: 1.0.1
vue-component-type-helpers: 2.0.16 vue-component-type-helpers: 2.0.16
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
vue-component-type-helpers@1.8.4: {} vue-component-type-helpers@1.8.4: {}
@ -23849,11 +23849,11 @@ snapshots:
vue-component-type-helpers@2.0.21: {} vue-component-type-helpers@2.0.21: {}
vue-demi@0.14.7(vue@3.4.26(typescript@5.4.5)): vue-demi@0.14.7(vue@3.4.26(typescript@5.5.2)):
dependencies: dependencies:
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
vue-docgen-api@4.75.1(vue@3.4.26(typescript@5.4.5)): vue-docgen-api@4.75.1(vue@3.4.26(typescript@5.5.2)):
dependencies: dependencies:
'@babel/parser': 7.24.0 '@babel/parser': 7.24.0
'@babel/types': 7.24.0 '@babel/types': 7.24.0
@ -23865,8 +23865,8 @@ snapshots:
pug: 3.0.2 pug: 3.0.2
recast: 0.23.4 recast: 0.23.4
ts-map: 1.0.3 ts-map: 1.0.3
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.4.26(typescript@5.4.5)) vue-inbrowser-compiler-independent-utils: 4.71.1(vue@3.4.26(typescript@5.5.2))
vue-eslint-parser@9.4.2(eslint@8.57.0): vue-eslint-parser@9.4.2(eslint@8.57.0):
dependencies: dependencies:
@ -23881,43 +23881,43 @@ snapshots:
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
vue-i18n@9.13.1(vue@3.4.26(typescript@5.4.5)): vue-i18n@9.13.1(vue@3.4.26(typescript@5.5.2)):
dependencies: dependencies:
'@intlify/core-base': 9.13.1 '@intlify/core-base': 9.13.1
'@intlify/shared': 9.13.1 '@intlify/shared': 9.13.1
'@vue/devtools-api': 6.6.1 '@vue/devtools-api': 6.6.1
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.4.26(typescript@5.4.5)): vue-inbrowser-compiler-independent-utils@4.71.1(vue@3.4.26(typescript@5.5.2)):
dependencies: dependencies:
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
vue-template-compiler@2.7.14: vue-template-compiler@2.7.14:
dependencies: dependencies:
de-indent: 1.0.2 de-indent: 1.0.2
he: 1.2.0 he: 1.2.0
vue-tsc@2.0.16(typescript@5.4.5): vue-tsc@2.0.16(typescript@5.5.2):
dependencies: dependencies:
'@volar/typescript': 2.2.0 '@volar/typescript': 2.2.0
'@vue/language-core': 2.0.16(typescript@5.4.5) '@vue/language-core': 2.0.16(typescript@5.5.2)
semver: 7.6.0 semver: 7.6.0
typescript: 5.4.5 typescript: 5.5.2
vue@3.4.26(typescript@5.4.5): vue@3.4.26(typescript@5.5.2):
dependencies: dependencies:
'@vue/compiler-dom': 3.4.26 '@vue/compiler-dom': 3.4.26
'@vue/compiler-sfc': 3.4.26 '@vue/compiler-sfc': 3.4.26
'@vue/runtime-dom': 3.4.26 '@vue/runtime-dom': 3.4.26
'@vue/server-renderer': 3.4.26(vue@3.4.26(typescript@5.4.5)) '@vue/server-renderer': 3.4.26(vue@3.4.26(typescript@5.5.2))
'@vue/shared': 3.4.26 '@vue/shared': 3.4.26
optionalDependencies: optionalDependencies:
typescript: 5.4.5 typescript: 5.5.2
vuedraggable@4.1.0(vue@3.4.26(typescript@5.4.5)): vuedraggable@4.1.0(vue@3.4.26(typescript@5.5.2)):
dependencies: dependencies:
sortablejs: 1.14.0 sortablejs: 1.14.0
vue: 3.4.26(typescript@5.4.5) vue: 3.4.26(typescript@5.5.2)
w3c-xmlserializer@5.0.0: w3c-xmlserializer@5.0.0:
dependencies: dependencies: