summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.github/workflows/docker-develop.yml2
-rw-r--r--.github/workflows/test.yml6
-rw-r--r--.node-version2
-rw-r--r--CHANGELOG.md13
-rw-r--r--Dockerfile19
-rw-r--r--locales/uk-UA.yml16
-rw-r--r--package.json4
-rw-r--r--packages/backend/package.json16
-rw-r--r--packages/backend/src/core/CustomEmojiService.ts146
-rw-r--r--packages/backend/src/core/ImageProcessingService.ts32
-rw-r--r--packages/backend/src/core/entities/NoteEntityService.ts8
-rw-r--r--packages/backend/src/core/entities/NotificationEntityService.ts2
-rw-r--r--packages/backend/src/core/entities/UserEntityService.ts1
-rw-r--r--packages/backend/src/logger.ts1
-rw-r--r--packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts9
-rw-r--r--packages/backend/src/server/FileServerService.ts386
-rw-r--r--packages/backend/src/server/MediaProxyServerService.ts177
-rw-r--r--packages/backend/src/server/ServerModule.ts2
-rw-r--r--packages/backend/src/server/ServerService.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/users/reactions.ts2
-rw-r--r--packages/frontend/package.json8
-rw-r--r--packages/frontend/src/components/MkAutocomplete.vue4
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.section.vue3
-rw-r--r--packages/frontend/src/components/MkEmojiPicker.vue8
-rw-r--r--packages/frontend/src/components/MkNote.vue4
-rw-r--r--packages/frontend/src/components/MkNoteDetailed.vue4
-rw-r--r--packages/frontend/src/components/MkNoteSimple.vue2
-rw-r--r--packages/frontend/src/components/MkNotification.vue14
-rw-r--r--packages/frontend/src/components/MkNotifications.vue2
-rw-r--r--packages/frontend/src/components/MkReactionIcon.vue4
-rw-r--r--packages/frontend/src/components/MkReactionsViewer.reaction.vue2
-rw-r--r--packages/frontend/src/components/MkSubNoteContent.vue2
-rw-r--r--packages/frontend/src/components/global/MkCustomEmoji.vue61
-rw-r--r--packages/frontend/src/components/global/MkEmoji.vue58
-rw-r--r--packages/frontend/src/components/global/MkUserName.vue2
-rw-r--r--packages/frontend/src/components/index.ts3
-rw-r--r--packages/frontend/src/components/mfm.ts34
-rw-r--r--packages/frontend/src/custom-emojis.ts15
-rw-r--r--packages/frontend/src/pages/about-misskey.vue5
-rw-r--r--packages/frontend/src/pages/admin/overview.stats.vue2
-rw-r--r--packages/frontend/src/pages/settings/index.vue5
-rw-r--r--packages/frontend/src/pages/settings/reaction.vue3
-rw-r--r--packages/frontend/src/scripts/device-kind.ts2
-rw-r--r--packages/frontend/src/scripts/use-note-capture.ts7
-rw-r--r--packages/frontend/src/store.ts6
-rw-r--r--packages/frontend/src/ui/_common_/notification.vue2
-rw-r--r--packages/sw/package.json12
-rw-r--r--pnpm-lock.yaml1376
48 files changed, 1359 insertions, 1140 deletions
diff --git a/.github/workflows/docker-develop.yml b/.github/workflows/docker-develop.yml
index d2cf4bf629..63dc940e24 100644
--- a/.github/workflows/docker-develop.yml
+++ b/.github/workflows/docker-develop.yml
@@ -31,3 +31,5 @@ jobs:
push: true
tags: misskey/misskey:develop
labels: develop
+ cache-from: type=gha
+ cache-to: type=gha,mode=max
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 48e2b19d6a..9135b4f60a 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -109,8 +109,12 @@ jobs:
# https://github.com/cypress-io/cypress/issues/4351#issuecomment-559489091
- name: ALSA Env
run: echo -e 'pcm.!default {\n type hw\n card 0\n}\n\nctl.!default {\n type hw\n card 0\n}' > ~/.asoundrc
+ # XXX: This tries reinstalling Cypress if the binary is not cached
+ # Remove this when the cache issue is fixed
+ - name: Cypress install
+ run: pnpm exec cypress install
- name: Cypress run
- uses: cypress-io/github-action@v4
+ uses: cypress-io/github-action@v5
with:
install: false
start: pnpm start:test
diff --git a/.node-version b/.node-version
index e44a38e080..0e9dc6b586 100644
--- a/.node-version
+++ b/.node-version
@@ -1 +1 @@
-v18.12.1
+v18.13.0
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b0dbb6e240..e767c15df4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,19 @@
You should also include the user name that made the change.
-->
+## 13.2.4 (2023/01/27)
+### Improvements
+- リモートカスタム絵文字表示時のパフォーマンスを改善
+- Default to `animation: false` when prefers-reduced-motion is set
+- リアクション履歴が公開なら、ログインしていなくても表示できるように
+- tweak blur setting
+- tweak custom emoji cache
+
+### Bugfixes
+- fix aggregation of retention
+- ダッシュボードでオンラインユーザー数が表示されない問題を修正
+- フォロー申請・フォローのボタンが、通知から消えている問題を修正
+
## 13.2.3 (2023/01/26)
### Improvements
- カスタム絵文字の更新をリアルタイムで反映するように
diff --git a/Dockerfile b/Dockerfile
index 47fe31bca7..3876b5f6ce 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,8 +2,12 @@ ARG NODE_VERSION=18.13.0-bullseye
FROM node:${NODE_VERSION} AS builder
-RUN apt-get update \
- && apt-get install -y --no-install-recommends \
+RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
+ --mount=type=cache,target=/var/lib/apt,sharing=locked \
+ rm -f /etc/apt/apt.conf.d/docker-clean \
+ ; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache \
+ && apt-get update \
+ && apt-get install -yqq --no-install-recommends \
build-essential
RUN corepack enable
@@ -16,7 +20,8 @@ COPY ["packages/backend/package.json", "./packages/backend/"]
COPY ["packages/frontend/package.json", "./packages/frontend/"]
COPY ["packages/sw/package.json", "./packages/sw/"]
-RUN pnpm i --frozen-lockfile
+RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
+ pnpm i --frozen-lockfile --aggregate-output
COPY . ./
@@ -30,11 +35,13 @@ FROM node:${NODE_VERSION}-slim AS runner
ARG UID="991"
ARG GID="991"
-RUN apt-get update \
+RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
+ --mount=type=cache,target=/var/lib/apt,sharing=locked \
+ rm -f /etc/apt/apt.conf.d/docker-clean \
+ ; echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache \
+ && apt-get update \
&& apt-get install -y --no-install-recommends \
ffmpeg tini \
- && apt-get -y clean \
- && rm -rf /var/lib/apt/lists/* \
&& corepack enable \
&& groupadd -g "${GID}" misskey \
&& useradd -l -u "${UID}" -g "${GID}" -m -d /misskey misskey
diff --git a/locales/uk-UA.yml b/locales/uk-UA.yml
index a852339969..a6ba27e4fe 100644
--- a/locales/uk-UA.yml
+++ b/locales/uk-UA.yml
@@ -688,7 +688,7 @@ pageLikesCount: "Кількість отриманих вподобань сто
pageLikedCount: "Кількість вподобаних сторінок"
contact: "Контакт"
useSystemFont: "Використовувати стандартний шрифт системи"
-clips: "Добірка"
+clips: "Добірки"
experimentalFeatures: "Експериментальні функції"
developer: "Розробник"
makeExplorable: "Зробіть обліковий запис видимим у розділі \"Огляд\""
@@ -1003,9 +1003,19 @@ _achievements:
title: "Майстер нотаток III"
description: "1000 днів користування загально"
flavor: "Дякуємо, що користуєтеся Misskey!"
+ _noteClipped1:
+ title: "Не можна не зберегти"
+ description: "Перша нотатка у добірці"
+ _noteFavorited1:
+ title: "Дивитися на зірки"
_myNoteFavorited1:
title: "У пошуках зірок"
+ _profileFilled:
+ title: "Повна готовність"
+ description: "Профіль заповнено"
_markedAsCat:
+ title: "Я кіт"
+ description: "Позначено як акаунт кота"
flavor: "Я дам тобі ім'я пізніше"
_following1:
title: "Перша підписка"
@@ -1034,6 +1044,7 @@ _achievements:
_followers300:
description: "Кількість підписників досягла 300"
_followers500:
+ title: "Радіовежа"
description: "Кількість підписників досягла 500"
_followers1000:
title: "Інфлюенсер"
@@ -1047,6 +1058,8 @@ _achievements:
description: "Минуло 3 роки з моменту створення акаунта"
_loggedInOnBirthday:
title: "З Днем народження!"
+ _loggedInOnNewYearsDay:
+ description: "Увійшли в перший день року"
_brainDiver:
title: "Brain Diver"
flavor: "Misskey-Misskey La-Tu-Ma"
@@ -1586,6 +1599,7 @@ _notification:
youReceivedFollowRequest: "Ви отримали запит на підписку"
yourFollowRequestAccepted: "Запит на підписку прийнято"
youWereInvitedToGroup: "Запрошення до групи"
+ achievementEarned: "Досягнення відкрито"
_types:
all: "Все"
follow: "Підписки"
diff --git a/package.json b/package.json
index c5a556aead..06ec191b5c 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "misskey",
- "version": "13.2.3",
+ "version": "13.2.4",
"codename": "nasubi",
"repository": {
"type": "git",
@@ -57,7 +57,7 @@
"@typescript-eslint/eslint-plugin": "5.49.0",
"@typescript-eslint/parser": "5.49.0",
"cross-env": "7.0.3",
- "cypress": "12.3.0",
+ "cypress": "12.4.0",
"eslint": "^8.32.0",
"start-server-and-test": "1.15.3"
},
diff --git a/packages/backend/package.json b/packages/backend/package.json
index c3b45f6bf4..f68fde8b4c 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -32,8 +32,8 @@
"@fastify/cors": "8.2.0",
"@fastify/http-proxy": "^8.4.0",
"@fastify/multipart": "7.4.0",
- "@fastify/static": "6.6.1",
- "@fastify/view": "7.4.0",
+ "@fastify/static": "6.7.0",
+ "@fastify/view": "7.4.1",
"@nestjs/common": "9.2.1",
"@nestjs/core": "9.2.1",
"@nestjs/testing": "9.2.1",
@@ -110,7 +110,7 @@
"stringz": "2.1.0",
"summaly": "2.7.0",
"syslog-pro": "git+https://github.com/misskey-dev/SyslogPro#0.2.9-misskey.2",
- "systeminformation": "5.17.3",
+ "systeminformation": "5.17.4",
"tinycolor2": "1.5.2",
"tmp": "0.2.1",
"tsc-alias": "1.8.2",
@@ -131,7 +131,7 @@
"devDependencies": {
"@redocly/openapi-core": "1.0.0-beta.120",
"@swc/cli": "^0.1.59",
- "@swc/core": "1.3.27",
+ "@swc/core": "1.3.29",
"@swc/jest": "0.2.24",
"@types/accepts": "1.3.5",
"@types/archiver": "5.3.1",
@@ -143,11 +143,11 @@
"@types/escape-regexp": "0.0.1",
"@types/fluent-ffmpeg": "2.1.20",
"@types/ioredis": "4.28.10",
- "@types/jest": "29.2.6",
+ "@types/jest": "29.4.0",
"@types/js-yaml": "4.0.5",
"@types/jsdom": "20.0.1",
"@types/jsonld": "1.5.8",
- "@types/jsrsasign": "10.5.4",
+ "@types/jsrsasign": "10.5.5",
"@types/mime-types": "2.1.1",
"@types/node": "18.11.18",
"@types/node-fetch": "3.0.3",
@@ -181,7 +181,7 @@
"eslint": "8.32.0",
"eslint-plugin-import": "2.27.5",
"execa": "6.1.0",
- "jest": "29.3.1",
- "jest-mock": "^29.3.1"
+ "jest": "29.4.1",
+ "jest-mock": "^29.4.1"
}
}
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index 1f0b214159..39814e1be6 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -6,22 +6,35 @@ import { EmojiEntityService } from '@/core/entities/EmojiEntityService.js';
import { GlobalEventService } from '@/core/GlobalEventService.js';
import type { DriveFile } from '@/models/entities/DriveFile.js';
import type { Emoji } from '@/models/entities/Emoji.js';
-import type { EmojisRepository } from '@/models/index.js';
+import type { EmojisRepository, Note } from '@/models/index.js';
import { bindThis } from '@/decorators.js';
+import { Cache } from '@/misc/cache.js';
+import { UtilityService } from '@/core/UtilityService.js';
+import type { Config } from '@/config.js';
+import { ReactionService } from '@/core/ReactionService.js';
+import { query } from '@/misc/prelude/url.js';
@Injectable()
export class CustomEmojiService {
+ private cache: Cache<Emoji | null>;
+
constructor(
+ @Inject(DI.config)
+ private config: Config,
+
@Inject(DI.db)
private db: DataSource,
@Inject(DI.emojisRepository)
private emojisRepository: EmojisRepository,
+ private utilityService: UtilityService,
private idService: IdService,
private emojiEntityService: EmojiEntityService,
private globalEventService: GlobalEventService,
+ private reactionService: ReactionService,
) {
+ this.cache = new Cache<Emoji | null>(1000 * 60 * 60 * 12);
}
@bindThis
@@ -44,12 +57,135 @@ export class CustomEmojiService {
type: data.driveFile.webpublicType ?? data.driveFile.type,
}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
- await this.db.queryResultCache!.remove(['meta_emojis']);
+ if (data.host == null) {
+ await this.db.queryResultCache!.remove(['meta_emojis']);
- this.globalEventService.publishBroadcastStream('emojiAdded', {
- emoji: await this.emojiEntityService.pack(emoji.id),
- });
+ this.globalEventService.publishBroadcastStream('emojiAdded', {
+ emoji: await this.emojiEntityService.pack(emoji.id),
+ });
+ }
return emoji;
}
+
+ @bindThis
+ private normalizeHost(src: string | undefined, noteUserHost: string | null): string | null {
+ // クエリに使うホスト
+ let host = src === '.' ? null // .はローカルホスト (ここがマッチするのはリアクションのみ)
+ : src === undefined ? noteUserHost // ノートなどでホスト省略表記の場合はローカルホスト (ここがリアクションにマッチすることはない)
+ : this.utilityService.isSelfHost(src) ? null // 自ホスト指定
+ : (src || noteUserHost); // 指定されたホスト || ノートなどの所有者のホスト (こっちがリアクションにマッチすることはない)
+
+ host = this.utilityService.toPunyNullable(host);
+
+ return host;
+ }
+
+ @bindThis
+ private parseEmojiStr(emojiName: string, noteUserHost: string | null) {
+ const match = emojiName.match(/^(\w+)(?:@([\w.-]+))?$/);
+ if (!match) return { name: null, host: null };
+
+ const name = match[1];
+
+ // ホスト正規化
+ const host = this.utilityService.toPunyNullable(this.normalizeHost(match[2], noteUserHost));
+
+ return { name, host };
+ }
+
+ /**
+ * 添付用(リモート)カスタム絵文字URLを解決する
+ * @param emojiName ノートやユーザープロフィールに添付された、またはリアクションのカスタム絵文字名 (:は含めない, リアクションでローカルホストの場合は@.を付ける (これはdecodeReactionで可能))
+ * @param noteUserHost ノートやユーザープロフィールの所有者のホスト
+ * @returns URL, nullは未マッチを意味する
+ */
+ @bindThis
+ public async populateEmoji(emojiName: string, noteUserHost: string | null): Promise<string | null> {
+ const { name, host } = this.parseEmojiStr(emojiName, noteUserHost);
+ if (name == null) return null;
+ if (host == null) return null;
+
+ const queryOrNull = async () => (await this.emojisRepository.findOneBy({
+ name,
+ host: host ?? IsNull(),
+ })) ?? null;
+
+ const emoji = await this.cache.fetch(`${name} ${host}`, queryOrNull);
+
+ if (emoji == null) return null;
+
+ const isLocal = emoji.host == null;
+ const emojiUrl = emoji.publicUrl || emoji.originalUrl; // || emoji.originalUrl してるのは後方互換性のため(publicUrlはstringなので??はだめ)
+ const url = isLocal
+ ? emojiUrl
+ : this.config.proxyRemoteFiles
+ ? `${this.config.url}/proxy/${encodeURIComponent((new URL(emojiUrl)).pathname)}?${query({ url: emojiUrl })}`
+ : emojiUrl;
+
+ return url;
+ }
+
+ /**
+ * 複数の添付用(リモート)カスタム絵文字URLを解決する (キャシュ付き, 存在しないものは結果から除外される)
+ */
+ @bindThis
+ public async populateEmojis(emojiNames: string[], noteUserHost: string | null): Promise<Record<string, string>> {
+ const emojis = await Promise.all(emojiNames.map(x => this.populateEmoji(x, noteUserHost)));
+ const res = {} as any;
+ for (let i = 0; i < emojiNames.length; i++) {
+ if (emojis[i] != null) {
+ res[emojiNames[i]] = emojis[i];
+ }
+ }
+ return res;
+ }
+
+ @bindThis
+ public aggregateNoteEmojis(notes: Note[]) {
+ let emojis: { name: string | null; host: string | null; }[] = [];
+ for (const note of notes) {
+ emojis = emojis.concat(note.emojis
+ .map(e => this.parseEmojiStr(e, note.userHost)));
+ if (note.renote) {
+ emojis = emojis.concat(note.renote.emojis
+ .map(e => this.parseEmojiStr(e, note.renote!.userHost)));
+ if (note.renote.user) {
+ emojis = emojis.concat(note.renote.user.emojis
+ .map(e => this.parseEmojiStr(e, note.renote!.userHost)));
+ }
+ }
+ const customReactions = Object.keys(note.reactions).map(x => this.reactionService.decodeReaction(x)).filter(x => x.name != null) as typeof emojis;
+ emojis = emojis.concat(customReactions);
+ if (note.user) {
+ emojis = emojis.concat(note.user.emojis
+ .map(e => this.parseEmojiStr(e, note.userHost)));
+ }
+ }
+ return emojis.filter(x => x.name != null && x.host != null) as { name: string; host: string; }[];
+ }
+
+ /**
+ * 与えられた絵文字のリストをデータベースから取得し、キャッシュに追加します
+ */
+ @bindThis
+ public async prefetchEmojis(emojis: { name: string; host: string | null; }[]): Promise<void> {
+ const notCachedEmojis = emojis.filter(emoji => this.cache.get(`${emoji.name} ${emoji.host}`) == null);
+ const emojisQuery: any[] = [];
+ const hosts = new Set(notCachedEmojis.map(e => e.host));
+ for (const host of hosts) {
+ if (host == null) continue;
+ emojisQuery.push({
+ name: In(notCachedEmojis.filter(e => e.host === host).map(e => e.name)),
+ host: host,
+ });
+ }
+ const _emojis = emojisQuery.length > 0 ? await this.emojisRepository.find({
+ where: emojisQuery,
+ select: ['name', 'host', 'originalUrl', 'publicUrl'],
+ }) : [];
+ for (const emoji of _emojis) {
+ this.cache.set(`${emoji.name} ${emoji.host}`, emoji);
+ }
+ }
}
diff --git a/packages/backend/src/core/ImageProcessingService.ts b/packages/backend/src/core/ImageProcessingService.ts
index 312189eea4..fbc02f504b 100644
--- a/packages/backend/src/core/ImageProcessingService.ts
+++ b/packages/backend/src/core/ImageProcessingService.ts
@@ -9,6 +9,14 @@ export type IImage = {
type: string;
};
+export type IImageStream = {
+ data: Readable;
+ ext: string | null;
+ type: string;
+};
+
+export type IImageStreamable = IImage | IImageStream;
+
export const webpDefault: sharp.WebpOptions = {
quality: 85,
alphaQuality: 95,
@@ -19,6 +27,7 @@ export const webpDefault: sharp.WebpOptions = {
};
import { bindThis } from '@/decorators.js';
+import { Readable } from 'node:stream';
@Injectable()
export class ImageProcessingService {
@@ -64,7 +73,7 @@ export class ImageProcessingService {
*/
@bindThis
public async convertToWebp(path: string, width: number, height: number, options: sharp.WebpOptions = webpDefault): Promise<IImage> {
- return this.convertSharpToWebp(await sharp(path), width, height, options);
+ return this.convertSharpToWebp(sharp(path), width, height, options);
}
@bindThis
@@ -85,6 +94,27 @@ export class ImageProcessingService {
};
}
+ @bindThis
+ public convertToWebpStream(path: string, width: number, height: number, options: sharp.WebpOptions = webpDefault): IImageStream {
+ return this.convertSharpToWebpStream(sharp(path), width, height, options);
+ }
+
+ @bindThis
+ public convertSharpToWebpStream(sharp: sharp.Sharp, width: number, height: number, options: sharp.WebpOptions = webpDefault): IImageStream {
+ const data = sharp
+ .resize(width, height, {
+ fit: 'inside',
+ withoutEnlargement: true,
+ })
+ .rotate()
+ .webp(options)
+
+ return {
+ data,
+ ext: 'webp',
+ type: 'image/webp',
+ };
+ }
/**
* Convert to PNG
* with resize, remove metadata, resolve orientation, stop animation
diff --git a/packages/backend/src/core/entities/NoteEntityService.ts b/packages/backend/src/core/entities/NoteEntityService.ts
index 2b179643f3..bd6971adb3 100644
--- a/packages/backend/src/core/entities/NoteEntityService.ts
+++ b/packages/backend/src/core/entities/NoteEntityService.ts
@@ -282,7 +282,9 @@ export class NoteEntityService implements OnModuleInit {
: await this.channelsRepository.findOneBy({ id: note.channelId })
: null;
- const reactionEmojiNames = Object.keys(note.reactions).filter(x => x.startsWith(':')).map(x => this.reactionService.decodeReaction(x).reaction).map(x => x.replace(/:/g, ''));
+ const reactionEmojiNames = Object.keys(note.reactions)
+ .filter(x => x.startsWith(':') && x.includes('@') && !x.includes('@.')) // リモートカスタム絵文字のみ
+ .map(x => this.reactionService.decodeReaction(x).reaction.replaceAll(':', ''));
const packed: Packed<'Note'> = await awaitAll({
id: note.id,
@@ -299,6 +301,8 @@ export class NoteEntityService implements OnModuleInit {
renoteCount: note.renoteCount,
repliesCount: note.repliesCount,
reactions: this.reactionService.convertLegacyReactions(note.reactions),
+ reactionEmojis: this.customEmojiService.populateEmojis(reactionEmojiNames, host),
+ emojis: host != null ? this.customEmojiService.populateEmojis(note.emojis, host) : undefined,
tags: note.tags.length > 0 ? note.tags : undefined,
fileIds: note.fileIds,
files: this.driveFileEntityService.packMany(note.fileIds),
@@ -384,6 +388,8 @@ export class NoteEntityService implements OnModuleInit {
}
}
+ await this.customEmojiService.prefetchEmojis(this.customEmojiService.aggregateNoteEmojis(notes));
+
return await Promise.all(notes.map(n => this.pack(n, me, {
...options,
_hint_: {
diff --git a/packages/backend/src/core/entities/NotificationEntityService.ts b/packages/backend/src/core/entities/NotificationEntityService.ts
index a8210eea02..ded1b512a1 100644
--- a/packages/backend/src/core/entities/NotificationEntityService.ts
+++ b/packages/backend/src/core/entities/NotificationEntityService.ts
@@ -146,6 +146,8 @@ export class NotificationEntityService implements OnModuleInit {
myReactionsMap.set(target, myReactions.find(reaction => reaction.noteId === target) ?? null);
}
+ await this.customEmojiService.prefetchEmojis(this.customEmojiService.aggregateNoteEmojis(notes));
+
return await Promise.all(notifications.map(x => this.pack(x, {
_hintForEachNotes_: {
myReactions: myReactionsMap,
diff --git a/packages/backend/src/core/entities/UserEntityService.ts b/packages/backend/src/core/entities/UserEntityService.ts
index f532b5bf6e..546e61a26e 100644
--- a/packages/backend/src/core/entities/UserEntityService.ts
+++ b/packages/backend/src/core/entities/UserEntityService.ts
@@ -413,6 +413,7 @@ export class UserEntityService implements OnModuleInit {
faviconUrl: instance.faviconUrl,
themeColor: instance.themeColor,
} : undefined) : undefined,
+ emojis: this.customEmojiService.populateEmojis(user.emojis, user.host),
onlineStatus: this.getOnlineStatus(user),
...(opts.detail ? {
diff --git a/packages/backend/src/logger.ts b/packages/backend/src/logger.ts
index e7d7051630..5d275bc7b2 100644
--- a/packages/backend/src/logger.ts
+++ b/packages/backend/src/logger.ts
@@ -68,6 +68,7 @@ export default class Logger {
if (envOption.withLogTime) log = chalk.gray(time) + ' ' + log;
console.log(important ? chalk.bold(log) : log);
+ if (level === 'error' && data) console.log(data);
if (store) {
if (this.syslogClient) {
diff --git a/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts b/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts
index 4650da76bb..da4ae88557 100644
--- a/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts
+++ b/packages/backend/src/queue/processors/AggregateRetentionProcessorService.ts
@@ -57,8 +57,15 @@ export class AggregateRetentionProcessorService {
usersCount: targetUserIds.length,
});
+ // 今日活動したユーザーを全て取得
+ const activeUsers = await this.usersRepository.findBy({
+ host: IsNull(),
+ lastActiveDate: MoreThan(new Date(Date.now() - (1000 * 60 * 60 * 24))),
+ });
+ const activeUsersIds = activeUsers.map(u => u.id);
+
for (const record of pastRecords) {
- const retention = record.userIds.filter(id => targetUserIds.includes(id)).length;
+ const retention = record.userIds.filter(id => activeUsersIds.includes(id)).length;
const data = deepClone(record.data);
data[dateKey] = retention;
diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts
index 134b3df327..40024270ae 100644
--- a/packages/backend/src/server/FileServerService.ts
+++ b/packages/backend/src/server/FileServerService.ts
@@ -5,14 +5,14 @@ import { Inject, Injectable } from '@nestjs/common';
import fastifyStatic from '@fastify/static';
import rename from 'rename';
import type { Config } from '@/config.js';
-import type { DriveFilesRepository } from '@/models/index.js';
+import type { DriveFile, DriveFilesRepository } from '@/models/index.js';
import { DI } from '@/di-symbols.js';
import { createTemp } from '@/misc/create-temp.js';
import { FILE_TYPE_BROWSERSAFE } from '@/const.js';
import { StatusError } from '@/misc/status-error.js';
import type Logger from '@/logger.js';
import { DownloadService } from '@/core/DownloadService.js';
-import { ImageProcessingService } from '@/core/ImageProcessingService.js';
+import { IImageStreamable, ImageProcessingService, webpDefault } from '@/core/ImageProcessingService.js';
import { VideoProcessingService } from '@/core/VideoProcessingService.js';
import { InternalStorageService } from '@/core/InternalStorageService.js';
import { contentDisposition } from '@/misc/content-disposition.js';
@@ -20,6 +20,8 @@ import { FileInfoService } from '@/core/FileInfoService.js';
import { LoggerService } from '@/core/LoggerService.js';
import { bindThis } from '@/decorators.js';
import type { FastifyInstance, FastifyRequest, FastifyReply, FastifyPluginOptions } from 'fastify';
+import { isMimeImage } from '@/misc/is-mime-image.js';
+import sharp from 'sharp';
const _filename = fileURLToPath(import.meta.url);
const _dirname = dirname(_filename);
@@ -57,7 +59,7 @@ export class FileServerService {
reply.header('Cache-Control', 'max-age=300');
};
}
-
+
@bindThis
public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
fastify.addHook('onRequest', (request, reply, done) => {
@@ -70,113 +72,351 @@ export class FileServerService {
serve: false,
});
- fastify.get('/app-default.jpg', (request, reply) => {
+ fastify.get('/files/app-default.jpg', (request, reply) => {
const file = fs.createReadStream(`${_dirname}/assets/dummy.png`);
reply.header('Content-Type', 'image/jpeg');
reply.header('Cache-Control', 'max-age=31536000, immutable');
return reply.send(file);
});
- fastify.get<{ Params: { key: string; } }>('/:key', async (request, reply) => await this.sendDriveFile(request, reply));
- fastify.get<{ Params: { key: string; } }>('/:key/*', async (request, reply) => await this.sendDriveFile(request, reply));
+ fastify.get<{ Params: { key: string; } }>('/files/:key', async (request, reply) => {
+ return await this.sendDriveFile(request, reply)
+ .catch(err => this.errorHandler(request, reply, err));
+ });
+ fastify.get<{ Params: { key: string; } }>('/files/:key/*', async (request, reply) => {
+ return await this.sendDriveFile(request, reply)
+ .catch(err => this.errorHandler(request, reply, err));
+ });
+
+ fastify.get<{
+ Params: { url: string; };
+ Querystring: { url?: string; };
+ }>('/proxy/:url*', async (request, reply) => {
+ return await this.proxyHandler(request, reply)
+ .catch(err => this.errorHandler(request, reply, err));
+ });
done();
}
@bindThis
- private async sendDriveFile(request: FastifyRequest<{ Params: { key: string; } }>, reply: FastifyReply) {
- const key = request.params.key;
+ private async errorHandler(request: FastifyRequest<{ Params?: { [x: string]: any }; Querystring?: { [x: string]: any }; }>, reply: FastifyReply, err?: any) {
+ this.logger.error(`${err}`);
- // Fetch drive file
- const file = await this.driveFilesRepository.createQueryBuilder('file')
- .where('file.accessKey = :accessKey', { accessKey: key })
- .orWhere('file.thumbnailAccessKey = :thumbnailAccessKey', { thumbnailAccessKey: key })
- .orWhere('file.webpublicAccessKey = :webpublicAccessKey', { webpublicAccessKey: key })
- .getOne();
+ reply.header('Cache-Control', 'max-age=300');
- if (file == null) {
- reply.code(404);
- reply.header('Cache-Control', 'max-age=86400');
+ if (request.query && 'fallback' in request.query) {
return reply.sendFile('/dummy.png', assets);
}
- const isThumbnail = file.thumbnailAccessKey === key;
- const isWebpublic = file.webpublicAccessKey === key;
+ if (err instanceof StatusError && (err.statusCode === 302 || err.isClientError)) {
+ reply.code(err.statusCode);
+ return;
+ }
- if (!file.storedInternal) {
- if (file.isLink && file.uri) { // 期限切れリモートファイル
- const [path, cleanup] = await createTemp();
+ reply.code(500);
+ return;
+ }
- try {
- await this.downloadService.downloadUrl(file.uri, path);
+ @bindThis
+ private async sendDriveFile(request: FastifyRequest<{ Params: { key: string; } }>, reply: FastifyReply) {
+ const key = request.params.key;
+ const file = await this.getFileFromKey(key).then();
- const { mime, ext } = await this.fileInfoService.detectType(path);
+ if (file === '404') {
+ reply.code(404);
+ reply.header('Cache-Control', 'max-age=86400');
+ return reply.sendFile('/dummy.png', assets);
+ }
- const convertFile = async () => {
- if (isThumbnail) {
- if (['image/jpeg', 'image/webp', 'image/avif', 'image/png', 'image/svg+xml'].includes(mime)) {
- return await this.imageProcessingService.convertToWebp(path, 498, 280);
- } else if (mime.startsWith('video/')) {
- return await this.videoProcessingService.generateVideoThumbnail(path);
- }
+ if (file === '204') {
+ reply.code(204);
+ reply.header('Cache-Control', 'max-age=86400');
+ return;
+ }
+
+ try {
+ if (file.state === 'remote') {
+ const convertFile = async () => {
+ if (file.fileRole === 'thumbnail') {
+ if (['image/jpeg', 'image/webp', 'image/avif', 'image/png', 'image/svg+xml'].includes(file.mime)) {
+ return this.imageProcessingService.convertToWebpStream(
+ file.path,
+ 498,
+ 280
+ );
+ } else if (file.mime.startsWith('video/')) {
+ return await this.videoProcessingService.generateVideoThumbnail(file.path);
}
+ }
- if (isWebpublic) {
- if (['image/svg+xml'].includes(mime)) {
- return await this.imageProcessingService.convertToPng(path, 2048, 2048);
- }
+ if (file.fileRole === 'webpublic') {
+ if (['image/svg+xml'].includes(file.mime)) {
+ return this.imageProcessingService.convertToWebpStream(
+ file.path,
+ 2048,
+ 2048,
+ { ...webpDefault, lossless: true }
+ )
}
+ }
- return {
- data: fs.readFileSync(path),
- ext,
- type: mime,
- };
+ return {
+ data: fs.createReadStream(file.path),
+ ext: file.ext,
+ type: file.mime,
};
+ };
- const image = await convertFile();
- reply.header('Content-Type', FILE_TYPE_BROWSERSAFE.includes(image.type) ? image.type : 'application/octet-stream');
- reply.header('Cache-Control', 'max-age=31536000, immutable');
- return image.data;
- } catch (err) {
- this.logger.error(`${err}`);
+ const image = await convertFile();
- if (err instanceof StatusError && err.isClientError) {
- reply.code(err.statusCode);
- reply.header('Cache-Control', 'max-age=86400');
- } else {
- reply.code(500);
- reply.header('Cache-Control', 'max-age=300');
- }
- } finally {
- cleanup();
+ if ('pipe' in image.data && typeof image.data.pipe === 'function') {
+ // image.dataがstreamなら、stream終了後にcleanup
+ image.data.on('end', file.cleanup);
+ image.data.on('close', file.cleanup);
+ } else {
+ // image.dataがstreamでないなら直ちにcleanup
+ file.cleanup();
}
- return;
+
+ reply.header('Content-Type', FILE_TYPE_BROWSERSAFE.includes(image.type) ? image.type : 'application/octet-stream');
+ reply.header('Cache-Control', 'max-age=31536000, immutable');
+ return image.data;
}
+ if (file.fileRole !== 'original') {
+ const filename = rename(file.file.name, {
+ suffix: file.fileRole === 'thumbnail' ? '-thumb' : '-web',
+ extname: file.ext ? `.${file.ext}` : undefined,
+ }).toString();
+
+ reply.header('Content-Type', FILE_TYPE_BROWSERSAFE.includes(file.mime) ? file.mime : 'application/octet-stream');
+ reply.header('Cache-Control', 'max-age=31536000, immutable');
+ reply.header('Content-Disposition', contentDisposition('inline', filename));
+ return fs.createReadStream(file.path);
+ } else {
+ const stream = fs.createReadStream(file.path);
+ stream.on('error', this.commonReadableHandlerGenerator(reply));
+ reply.header('Content-Type', FILE_TYPE_BROWSERSAFE.includes(file.file.type) ? file.file.type : 'application/octet-stream');
+ reply.header('Cache-Control', 'max-age=31536000, immutable');
+ reply.header('Content-Disposition', contentDisposition('inline', file.file.name));
+ return stream;
+ }
+ } catch (e) {
+ if ('cleanup' in file) file.cleanup();
+ throw e;
+ }
+ }
+
+ @bindThis
+ private async proxyHandler(request: FastifyRequest<{ Params: { url: string; }; Querystring: { url?: string; }; }>, reply: FastifyReply) {
+ const url = 'url' in request.query ? request.query.url : 'https://' + request.params.url;
+
+ if (typeof url !== 'string') {
+ reply.code(400);
+ return;
+ }
+
+ // Create temp file
+ const file = await this.getStreamAndTypeFromUrl(url);
+ if (file === '404') {
+ reply.code(404);
+ reply.header('Cache-Control', 'max-age=86400');
+ return reply.sendFile('/dummy.png', assets);
+ }
+
+ if (file === '204') {
reply.code(204);
reply.header('Cache-Control', 'max-age=86400');
return;
}
- if (isThumbnail || isWebpublic) {
- const { mime, ext } = await this.fileInfoService.detectType(this.internalStorageService.resolvePath(key));
- const filename = rename(file.name, {
- suffix: isThumbnail ? '-thumb' : '-web',
- extname: ext ? `.${ext}` : undefined,
- }).toString();
+ try {
+ const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image');
+ const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image');
- reply.header('Content-Type', FILE_TYPE_BROWSERSAFE.includes(mime) ? mime : 'application/octet-stream');
- reply.header('Cache-Control', 'max-age=31536000, immutable');
- reply.header('Content-Disposition', contentDisposition('inline', filename));
- return this.internalStorageService.read(key);
- } else {
- const readable = this.internalStorageService.read(file.accessKey!);
- readable.on('error', this.commonReadableHandlerGenerator(reply));
- reply.header('Content-Type', FILE_TYPE_BROWSERSAFE.includes(file.type) ? file.type : 'application/octet-stream');
+ let image: IImageStreamable | null = null;
+ if ('emoji' in request.query && isConvertibleImage) {
+ if (!isAnimationConvertibleImage && !('static' in request.query)) {
+ image = {
+ data: fs.createReadStream(file.path),
+ ext: file.ext,
+ type: file.mime,
+ };
+ } else {
+ const data = sharp(file.path, { animated: !('static' in request.query) })
+ .resize({
+ height: 128,
+ withoutEnlargement: true,
+ })
+ .webp(webpDefault);
+
+ image = {
+ data,
+ ext: 'webp',
+ type: 'image/webp',
+ };
+ }
+ } else if ('static' in request.query && isConvertibleImage) {
+ image = this.imageProcessingService.convertToWebpStream(file.path, 498, 280);
+ } else if ('preview' in request.query && isConvertibleImage) {
+ image = this.imageProcessingService.convertToWebpStream(file.path, 200, 200);
+ } else if ('badge' in request.query) {
+ if (!isConvertibleImage) {
+ // 画像でないなら404でお茶を濁す
+ throw new StatusError('Unexpected mime', 404);
+ }
+
+ const mask = sharp(file.path)
+ .resize(96, 96, {
+ fit: 'inside',
+ withoutEnlargement: false,
+ })
+ .greyscale()
+ .normalise()
+ .linear(1.75, -(128 * 1.75) + 128) // 1.75x contrast
+ .flatten({ background: '#000' })
+ .toColorspace('b-w');
+
+ const stats = await mask.clone().stats();
+
+ if (stats.entropy < 0.1) {
+ // エントロピーがあまりない場合は404にする
+ throw new StatusError('Skip to provide badge', 404);
+ }
+
+ const data = sharp({
+ create: { width: 96, height: 96, channels: 4, background: { r: 0, g: 0, b: 0, alpha: 0 } },
+ })
+ .pipelineColorspace('b-w')
+ .boolean(await mask.png().toBuffer(), 'eor');
+
+ image = {
+ data: await data.png().toBuffer(),
+ ext: 'png',
+ type: 'image/png',
+ };
+ } else if (file.mime === 'image/svg+xml') {
+ image = this.imageProcessingService.convertToWebpStream(file.path, 2048, 2048);
+ } else if (!file.mime.startsWith('image/') || !FILE_TYPE_BROWSERSAFE.includes(file.mime)) {
+ throw new StatusError('Rejected type', 403, 'Rejected type');
+ }
+
+ if (!image) {
+ image = {
+ data: fs.createReadStream(file.path),
+ ext: file.ext,
+ type: file.mime,
+ };
+ }
+
+ if ('cleanup' in file) {
+ if ('pipe' in image.data && typeof image.data.pipe === 'function') {
+ // image.dataがstreamなら、stream終了後にcleanup
+ image.data.on('end', file.cleanup);
+ image.data.on('close', file.cleanup);
+ } else {
+ // image.dataがstreamでないなら直ちにcleanup
+ file.cleanup();
+ }
+ }
+
+ reply.header('Content-Type', image.type);
reply.header('Cache-Control', 'max-age=31536000, immutable');
- reply.header('Content-Disposition', contentDisposition('inline', file.name));
- return readable;
+ return image.data;
+ } catch (e) {
+ if ('cleanup' in file) file.cleanup();
+ throw e;
+ }
+ }
+
+ @bindThis
+ private async getStreamAndTypeFromUrl(url: string): Promise<
+ { state: 'remote'; fileRole?: 'thumbnail' | 'webpublic' | 'original'; file?: DriveFile; mime: string; ext: string | null; path: string; cleanup: () => void; }
+ | { state: 'stored_internal'; fileRole: 'thumbnail' | 'webpublic' | 'original'; file: DriveFile; mime: string; ext: string | null; path: string; }
+ | '404'
+ | '204'
+ > {
+ if (url.startsWith(`${this.config.url}/files/`)) {
+ const key = url.replace(`${this.config.url}/files/`, '').split('/').shift();
+ if (!key) throw new StatusError('Invalid File Key', 400, 'Invalid File Key');
+
+ return await this.getFileFromKey(key);
+ }
+
+ return await this.downloadAndDetectTypeFromUrl(url);
+ }
+
+ @bindThis
+ private async downloadAndDetectTypeFromUrl(url: string): Promise<
+ { state: 'remote' ; mime: string; ext: string | null; path: string; cleanup: () => void; }
+ > {
+ const [path, cleanup] = await createTemp();
+ try {
+ await this.downloadService.downloadUrl(url, path);
+
+ const { mime, ext } = await this.fileInfoService.detectType(path);
+
+ return {
+ state: 'remote',
+ mime, ext,
+ path, cleanup,
+ }
+ } catch (e) {
+ cleanup();
+ throw e;
+ }
+ }
+
+ @bindThis
+ private async getFileFromKey(key: string): Promise<
+ { state: 'remote'; fileRole: 'thumbnail' | 'webpublic' | 'original'; file: DriveFile; mime: string; ext: string | null; path: string; cleanup: () => void; }
+ | { state: 'stored_internal'; fileRole: 'thumbnail' | 'webpublic' | 'original'; file: DriveFile; mime: string; ext: string | null; path: string; }
+ | '404'
+ | '204'
+ > {
+ // Fetch drive file
+ const file = await this.driveFilesRepository.createQueryBuilder('file')
+ .where('file.accessKey = :accessKey', { accessKey: key })
+ .orWhere('file.thumbnailAccessKey = :thumbnailAccessKey', { thumbnailAccessKey: key })
+ .orWhere('file.webpublicAccessKey = :webpublicAccessKey', { webpublicAccessKey: key })
+ .getOne();
+
+ if (file == null) return '404';
+
+ const isThumbnail = file.thumbnailAccessKey === key;
+ const isWebpublic = file.webpublicAccessKey === key;
+
+ if (!file.storedInternal) {
+ if (!(file.isLink && file.uri)) return '204';
+ const result = await this.downloadAndDetectTypeFromUrl(file.uri);
+ return {
+ ...result,
+ fileRole: isThumbnail ? 'thumbnail' : isWebpublic ? 'webpublic' : 'original',
+ file,
+ }
+ }
+
+ const path = this.internalStorageService.resolvePath(key);
+
+ if (isThumbnail || isWebpublic) {
+ const { mime, ext } = await this.fileInfoService.detectType(path);
+ return {
+ state: 'stored_internal',
+ fileRole: isThumbnail ? 'thumbnail' : 'webpublic',
+ file,
+ mime, ext,
+ path,
+ };
+ }
+
+ return {
+ state: 'stored_internal',
+ fileRole: 'original',
+ file,
+ mime: file.type,
+ ext: null,
+ path,
}
}
}
diff --git a/packages/backend/src/server/MediaProxyServerService.ts b/packages/backend/src/server/MediaProxyServerService.ts
deleted file mode 100644
index 5b76f15020..0000000000
--- a/packages/backend/src/server/MediaProxyServerService.ts
+++ /dev/null
@@ -1,177 +0,0 @@
-import * as fs from 'node:fs';
-import { fileURLToPath } from 'node:url';
-import { dirname } from 'node:path';
-import { Inject, Injectable } from '@nestjs/common';
-import sharp from 'sharp';
-import fastifyStatic from '@fastify/static';
-import { DI } from '@/di-symbols.js';
-import type { Config } from '@/config.js';
-import { isMimeImage } from '@/misc/is-mime-image.js';
-import { createTemp } from '@/misc/create-temp.js';
-import { DownloadService } from '@/core/DownloadService.js';
-import { ImageProcessingService, webpDefault } from '@/core/ImageProcessingService.js';
-import type { IImage } from '@/core/ImageProcessingService.js';
-import { FILE_TYPE_BROWSERSAFE } from '@/const.js';
-import { StatusError } from '@/misc/status-error.js';
-import type Logger from '@/logger.js';
-import { FileInfoService } from '@/core/FileInfoService.js';
-import { LoggerService } from '@/core/LoggerService.js';
-import { bindThis } from '@/decorators.js';
-import type { FastifyInstance, FastifyPluginOptions, FastifyReply, FastifyRequest } from 'fastify';
-
-const _filename = fileURLToPath(import.meta.url);
-const _dirname = dirname(_filename);
-
-const assets = `${_dirname}/../../src/server/assets/`;
-
-@Injectable()
-export class MediaProxyServerService {
- private logger: Logger;
-
- constructor(
- @Inject(DI.config)
- private config: Config,
-
- private fileInfoService: FileInfoService,
- private downloadService: DownloadService,
- private imageProcessingService: ImageProcessingService,
- private loggerService: LoggerService,
- ) {
- this.logger = this.loggerService.getLogger('server', 'gray', false);
-
- //this.createServer = this.createServer.bind(this);
- }
-
- @bindThis
- public createServer(fastify: FastifyInstance, options: FastifyPluginOptions, done: (err?: Error) => void) {
- fastify.addHook('onRequest', (request, reply, done) => {
- reply.header('Content-Security-Policy', 'default-src \'none\'; img-src \'self\'; media-src \'self\'; style-src \'unsafe-inline\'');
- done();
- });
-
- fastify.register(fastifyStatic, {
- root: _dirname,
- serve: false,
- });
-
- fastify.get<{
- Params: { url: string; };
- Querystring: { url?: string; };
- }>('/:url*', async (request, reply) => await this.handler(request, reply));
-
- done();
- }
-
- @bindThis
- private async handler(request: FastifyRequest<{ Params: { url: string; }; Querystring: { url?: string; }; }>, reply: FastifyReply) {
- const url = 'url' in request.query ? request.query.url : 'https://' + request.params.url;
-
- if (typeof url !== 'string') {
- reply.code(400);
- return;
- }
-
- // Create temp file
- const [path, cleanup] = await createTemp();
-
- try {
- await this.downloadService.downloadUrl(url, path);
-
- const { mime, ext } = await this.fileInfoService.detectType(path);
- const isConvertibleImage = isMimeImage(mime, 'sharp-convertible-image');
- const isAnimationConvertibleImage = isMimeImage(mime, 'sharp-animation-convertible-image');
-
- let image: IImage;
- if ('emoji' in request.query && isConvertibleImage) {
- if (!isAnimationConvertibleImage && !('static' in request.query)) {
- image = {
- data: fs.readFileSync(path),
- ext,
- type: mime,
- };
- } else {
- const data = await sharp(path, { animated: !('static' in request.query) })
- .resize({
- height: 128,
- withoutEnlargement: true,
- })
- .webp(webpDefault)
- .toBuffer();
-
- image = {
- data,
- ext: 'webp',
- type: 'image/webp',
- };
- }
- } else if ('static' in request.query && isConvertibleImage) {
- image = await this.imageProcessingService.convertToWebp(path, 498, 280);
- } else if ('preview' in request.query && isConvertibleImage) {
- image = await this.imageProcessingService.convertToWebp(path, 200, 200);
- } else if ('badge' in request.query) {
- if (!isConvertibleImage) {
- // 画像でないなら404でお茶を濁す
- throw new StatusError('Unexpected mime', 404);
- }
-
- const mask = sharp(path)
- .resize(96, 96, {
- fit: 'inside',
- withoutEnlargement: false,
- })
- .greyscale()
- .normalise()
- .linear(1.75, -(128 * 1.75) + 128) // 1.75x contrast
- .flatten({ background: '#000' })
- .toColorspace('b-w');
-
- const stats = await mask.clone().stats();
-
- if (stats.entropy < 0.1) {
- // エントロピーがあまりない場合は404にする
- throw new StatusError('Skip to provide badge', 404);
- }
-
- const data = sharp({
- create: { width: 96, height: 96, channels: 4, background: { r: 0, g: 0, b: 0, alpha: 0 } },
- })
- .pipelineColorspace('b-w')
- .boolean(await mask.png().toBuffer(), 'eor');
-
- image = {
- data: await data.png().toBuffer(),
- ext: 'png',
- type: 'image/png',
- };
- } else if (mime === 'image/svg+xml') {
- image = await this.imageProcessingService.convertToWebp(path, 2048, 2048, webpDefault);
- } else if (!mime.startsWith('image/') || !FILE_TYPE_BROWSERSAFE.includes(mime)) {
- throw new StatusError('Rejected type', 403, 'Rejected type');
- } else {
- image = {
- data: fs.readFileSync(path),
- ext,
- type: mime,
- };
- }
-
- reply.header('Content-Type', image.type);
- reply.header('Cache-Control', 'max-age=31536000, immutable');
- return image.data;
- } catch (err) {
- this.logger.error(`${err}`);
-
- if ('fallback' in request.query) {
- return reply.sendFile('/dummy.png', assets);
- }
-
- if (err instanceof StatusError && (err.statusCode === 302 || err.isClientError)) {
- reply.code(err.statusCode);
- } else {
- reply.code(500);
- }
- } finally {
- cleanup();
- }
- }
-}
diff --git a/packages/backend/src/server/ServerModule.ts b/packages/backend/src/server/ServerModule.ts
index 474edafe41..9dc1527698 100644
--- a/packages/backend/src/server/ServerModule.ts
+++ b/packages/backend/src/server/ServerModule.ts
@@ -3,7 +3,6 @@ import { EndpointsModule } from '@/server/api/EndpointsModule.js';
import { CoreModule } from '@/core/CoreModule.js';
import { ApiCallService } from './api/ApiCallService.js';
import { FileServerService } from './FileServerService.js';
-import { MediaProxyServerService } from './MediaProxyServerService.js';
import { NodeinfoServerService } from './NodeinfoServerService.js';
import { ServerService } from './ServerService.js';
import { WellKnownServerService } from './WellKnownServerService.js';
@@ -51,7 +50,6 @@ import { UserListChannelService } from './api/stream/channels/user-list.js';
UrlPreviewService,
ActivityPubServerService,
FileServerService,
- MediaProxyServerService,
NodeinfoServerService,
ServerService,
WellKnownServerService,
diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts
index eb6a3795eb..beb3a34ecd 100644
--- a/packages/backend/src/server/ServerService.ts
+++ b/packages/backend/src/server/ServerService.ts
@@ -20,7 +20,6 @@ import { NodeinfoServerService } from './NodeinfoServerService.js';
import { ApiServerService } from './api/ApiServerService.js';
import { StreamingApiServerService } from './api/StreamingApiServerService.js';
import { WellKnownServerService } from './WellKnownServerService.js';
-import { MediaProxyServerService } from './MediaProxyServerService.js';
import { FileServerService } from './FileServerService.js';
import { ClientServerService } from './web/ClientServerService.js';
@@ -48,7 +47,6 @@ export class ServerService {
private wellKnownServerService: WellKnownServerService,
private nodeinfoServerService: NodeinfoServerService,
private fileServerService: FileServerService,
- private mediaProxyServerService: MediaProxyServerService,
private clientServerService: ClientServerService,
private globalEventService: GlobalEventService,
private loggerService: LoggerService,
@@ -73,8 +71,7 @@ export class ServerService {
}
fastify.register(this.apiServerService.createServer, { prefix: '/api' });
- fastify.register(this.fileServerService.createServer, { prefix: '/files' });
- fastify.register(this.mediaProxyServerService.createServer, { prefix: '/proxy' });
+ fastify.register(this.fileServerService.createServer);
fastify.register(this.activityPubServerService.createServer);
fastify.register(this.nodeinfoServerService.createServer);
fastify.register(this.wellKnownServerService.createServer);
diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts
index 9ec911f322..ac401a60ee 100644
--- a/packages/backend/src/server/api/endpoints/users/reactions.ts
+++ b/packages/backend/src/server/api/endpoints/users/reactions.ts
@@ -61,7 +61,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> {
super(meta, paramDef, async (ps, me) => {
const profile = await this.userProfilesRepository.findOneByOrFail({ userId: ps.userId });
- if (me == null || (me.id !== ps.userId && !profile.publicReactions)) {
+ if ((me == null || me.id !== ps.userId) && !profile.publicReactions) {
throw new ApiError(meta.errors.reactionsNotPublic);
}
diff --git a/packages/frontend/package.json b/packages/frontend/package.json
index da568a9eac..12f890aa53 100644
--- a/packages/frontend/package.json
+++ b/packages/frontend/package.json
@@ -12,7 +12,7 @@
"@rollup/plugin-json": "6.0.0",
"@rollup/pluginutils": "5.0.2",
"@syuilo/aiscript": "0.12.2",
- "@tabler/icons-webfont": "^2.0.0",
+ "@tabler/icons-webfont": "^2.1.2",
"@vitejs/plugin-vue": "4.0.0",
"@vue/compiler-sfc": "3.2.45",
"autobind-decorator": "2.4.0",
@@ -44,7 +44,7 @@
"punycode": "2.3.0",
"querystring": "0.2.1",
"rndstr": "1.0.0",
- "rollup": "3.10.1",
+ "rollup": "3.11.0",
"s-age": "1.1.2",
"sanitize-html": "^2.8.1",
"sass": "1.57.1",
@@ -53,7 +53,7 @@
"stringz": "2.1.0",
"syuilo-password-strength": "0.0.1",
"textarea-caret": "3.1.0",
- "three": "0.148.0",
+ "three": "0.149.0",
"throttle-debounce": "5.0.0",
"tinycolor2": "1.5.2",
"tsc-alias": "1.8.2",
@@ -86,7 +86,7 @@
"@typescript-eslint/parser": "5.49.0",
"@vue/runtime-core": "3.2.45",
"cross-env": "7.0.3",
- "cypress": "12.3.0",
+ "cypress": "12.4.0",
"eslint": "8.32.0",
"eslint-plugin-import": "2.27.5",
"eslint-plugin-vue": "9.9.0",
diff --git a/packages/frontend/src/components/MkAutocomplete.vue b/packages/frontend/src/components/MkAutocomplete.vue
index 2cb3aeb3d8..27997eb330 100644
--- a/packages/frontend/src/components/MkAutocomplete.vue
+++ b/packages/frontend/src/components/MkAutocomplete.vue
@@ -17,7 +17,7 @@
</ol>
<ol v-else-if="emojis.length > 0" ref="suggests" :class="$style.list">
<li v-for="emoji in emojis" :key="emoji.emoji" :class="$style.item" tabindex="-1" @click="complete(type, emoji.emoji)" @keydown="onKeydown">
- <MkEmoji :emoji="emoji.emoji" :class="$style.emoji"/>
+ <MkCustomEmoji :name="emoji.emoji" :class="$style.emoji"/>
<!-- eslint-disable-next-line vue/no-v-html -->
<span v-if="q" :class="$style.emojiName" v-html="sanitizeHtml(emoji.name.replace(q, `<b>${q}</b>`))"></span>
<span v-else v-text="emoji.name"></span>
@@ -112,7 +112,7 @@ const emojiDb = computed(() => {
customEmojiDB.sort((a, b) => a.name.length - b.name.length);
//#endregion
- return markRaw([ ...customEmojiDB, ...unicodeEmojiDB ]);
+ return markRaw([...customEmojiDB, ...unicodeEmojiDB]);
});
export default {
diff --git a/packages/frontend/src/components/MkEmojiPicker.section.vue b/packages/frontend/src/components/MkEmojiPicker.section.vue
index acced44793..c418ac2c52 100644
--- a/packages/frontend/src/components/MkEmojiPicker.section.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.section.vue
@@ -11,7 +11,8 @@
class="_button item"
@click="emit('chosen', emoji, $event)"
>
- <MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
+ <MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
+ <MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
</button>
</div>
</section>
diff --git a/packages/frontend/src/components/MkEmojiPicker.vue b/packages/frontend/src/components/MkEmojiPicker.vue
index f64cc6e9aa..39e274ba11 100644
--- a/packages/frontend/src/components/MkEmojiPicker.vue
+++ b/packages/frontend/src/components/MkEmojiPicker.vue
@@ -12,7 +12,7 @@
tabindex="0"
@click="chosen(emoji, $event)"
>
- <MkEmoji class="emoji" :emoji="`:${emoji.name}:`"/>
+ <MkCustomEmoji class="emoji" :name="emoji.name"/>
</button>
</div>
<div v-if="searchResultUnicode.length > 0" class="body">
@@ -39,7 +39,8 @@
tabindex="0"
@click="chosen(emoji, $event)"
>
- <MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
+ <MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
+ <MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
</button>
</div>
</section>
@@ -53,7 +54,8 @@
class="_button item"
@click="chosen(emoji, $event)"
>
- <MkEmoji class="emoji" :emoji="emoji" :normal="true"/>
+ <MkCustomEmoji v-if="emoji[0] === ':'" class="emoji" :name="emoji" :normal="true"/>
+ <MkEmoji v-else class="emoji" :emoji="emoji" :normal="true"/>
</button>
</div>
</section>
diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue
index 1f6a2883d7..351861ac17 100644
--- a/packages/frontend/src/components/MkNote.vue
+++ b/packages/frontend/src/components/MkNote.vue
@@ -48,12 +48,12 @@
<div :class="$style.text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<MkA v-if="appearNote.replyId" :class="$style.replyIcon" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
- <Mfm v-if="appearNote.text" v-once :text="appearNote.text" :author="appearNote.user" :i="$i"/>
+ <Mfm v-if="appearNote.text" v-once :text="appearNote.text" :author="appearNote.user" :i="$i" :emoji-urls="appearNote.emojis"/>
<div v-if="translating || translation" :class="$style.translation">
<MkLoading v-if="translating" mini/>
<div v-else :class="$style.translated">
<b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}: </b>
- <Mfm :text="translation.text" :author="appearNote.user" :i="$i"/>
+ <Mfm :text="translation.text" :author="appearNote.user" :i="$i" :emoji-urls="appearNote.emojis"/>
</div>
</div>
</div>
diff --git a/packages/frontend/src/components/MkNoteDetailed.vue b/packages/frontend/src/components/MkNoteDetailed.vue
index 48ace56d9c..0da06c4f14 100644
--- a/packages/frontend/src/components/MkNoteDetailed.vue
+++ b/packages/frontend/src/components/MkNoteDetailed.vue
@@ -65,13 +65,13 @@
<div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<MkA v-if="appearNote.replyId" class="reply" :to="`/notes/${appearNote.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
- <Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i"/>
+ <Mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$i" :emoji-urls="appearNote.emojis"/>
<a v-if="appearNote.renote != null" class="rp">RN:</a>
<div v-if="translating || translation" class="translation">
<MkLoading v-if="translating" mini/>
<div v-else class="translated">
<b>{{ $t('translatedFrom', { x: translation.sourceLang }) }}: </b>
- <Mfm :text="translation.text" :author="appearNote.user" :i="$i"/>
+ <Mfm :text="translation.text" :author="appearNote.user" :i="$i" :emoji-urls="appearNote.emojis"/>
</div>
</div>
</div>
diff --git a/packages/frontend/src/components/MkNoteSimple.vue b/packages/frontend/src/components/MkNoteSimple.vue
index 828bbee5af..757b325a06 100644
--- a/packages/frontend/src/components/MkNoteSimple.vue
+++ b/packages/frontend/src/components/MkNoteSimple.vue
@@ -5,7 +5,7 @@
<MkNoteHeader :class="$style.header" :note="note" :mini="true"/>
<div>
<p v-if="note.cw != null" :class="$style.cw">
- <Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :i="$i"/>
+ <Mfm v-if="note.cw != ''" style="margin-right: 8px;" :text="note.cw" :author="note.user" :i="$i" :emoji-urls="note.emojis"/>
<MkCwButton v-model="showContent" :note="note"/>
</p>
<div v-show="note.cw == null || showContent">
diff --git a/packages/frontend/src/components/MkNotification.vue b/packages/frontend/src/components/MkNotification.vue
index a8b8fec346..b51d456eab 100644
--- a/packages/frontend/src/components/MkNotification.vue
+++ b/packages/frontend/src/components/MkNotification.vue
@@ -38,26 +38,26 @@
<div v-once :class="$style.content">
<MkA v-if="notification.type === 'reaction'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
<i class="ti ti-quote" :class="$style.quote"></i>
- <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :author="notification.note.user"/>
+ <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
<i class="ti ti-quote" :class="$style.quote"></i>
</MkA>
<MkA v-else-if="notification.type === 'renote'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note.renote)">
<i class="ti ti-quote" :class="$style.quote"></i>
- <Mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="!full" :author="notification.note.renote.user"/>
+ <Mfm :text="getNoteSummary(notification.note.renote)" :plain="true" :nowrap="true" :author="notification.note.renote.user"/>
<i class="ti ti-quote" :class="$style.quote"></i>
</MkA>
<MkA v-else-if="notification.type === 'reply'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
- <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :author="notification.note.user"/>
+ <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
</MkA>
<MkA v-else-if="notification.type === 'mention'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
- <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :author="notification.note.user"/>
+ <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
</MkA>
<MkA v-else-if="notification.type === 'quote'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
- <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :author="notification.note.user"/>
+ <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
</MkA>
<MkA v-else-if="notification.type === 'pollEnded'" :class="$style.text" :to="notePage(notification.note)" :title="getNoteSummary(notification.note)">
<i class="ti ti-quote" :class="$style.quote"></i>
- <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="!full" :author="notification.note.user"/>
+ <Mfm :text="getNoteSummary(notification.note)" :plain="true" :nowrap="true" :author="notification.note.user"/>
<i class="ti ti-quote" :class="$style.quote"></i>
</MkA>
<MkA v-else-if="notification.type === 'achievementEarned'" :class="$style.text" to="/my/achievements">
@@ -68,7 +68,7 @@
<span v-else-if="notification.type === 'receiveFollowRequest'" :class="$style.text" style="opacity: 0.6;">{{ i18n.ts.receiveFollowRequest }}<div v-if="full && !followRequestDone"><button class="_textButton" @click="acceptFollowRequest()">{{ i18n.ts.accept }}</button> | <button class="_textButton" @click="rejectFollowRequest()">{{ i18n.ts.reject }}</button></div></span>
<span v-else-if="notification.type === 'groupInvited'" :class="$style.text" style="opacity: 0.6;">{{ i18n.ts.groupInvited }}: <b>{{ notification.invitation.group.name }}</b><div v-if="full && !groupInviteDone"><button class="_textButton" @click="acceptGroupInvitation()">{{ i18n.ts.accept }}</button> | <button class="_textButton" @click="rejectGroupInvitation()">{{ i18n.ts.reject }}</button></div></span>
<span v-else-if="notification.type === 'app'" :class="$style.text">
- <Mfm :text="notification.body" :nowrap="!full"/>
+ <Mfm :text="notification.body" :nowrap="false"/>
</span>
</div>
</div>
diff --git a/packages/frontend/src/components/MkNotifications.vue b/packages/frontend/src/components/MkNotifications.vue
index f5ae7bcee4..ab5dff8db5 100644
--- a/packages/frontend/src/components/MkNotifications.vue
+++ b/packages/frontend/src/components/MkNotifications.vue
@@ -10,7 +10,7 @@
<template #default="{ items: notifications }">
<MkDateSeparatedList v-slot="{ item: notification }" :class="$style.list" :items="notifications" :no-gap="true">
<XNote v-if="['reply', 'quote', 'mention'].includes(notification.type)" :key="notification.id" :note="notification.note"/>
- <XNotification v-else :key="notification.id" :notification="notification" :with-time="true" :full="false" class="_panel notification"/>
+ <XNotification v-else :key="notification.id" :notification="notification" :with-time="true" :full="true" class="_panel notification"/>
</MkDateSeparatedList>
</template>
</MkPagination>
diff --git a/packages/frontend/src/components/MkReactionIcon.vue b/packages/frontend/src/components/MkReactionIcon.vue
index 6e9d2b1a6c..29b3f9b85b 100644
--- a/packages/frontend/src/components/MkReactionIcon.vue
+++ b/packages/frontend/src/components/MkReactionIcon.vue
@@ -1,5 +1,6 @@
<template>
-<MkEmoji :emoji="reaction" :is-reaction="true" :normal="true" :no-style="noStyle"/>
+<MkCustomEmoji v-if="reaction[0] === ':'" :name="reaction" :normal="true" :no-style="noStyle" :url="emojiUrl"/>
+<MkEmoji v-else :emoji="reaction" :normal="true" :no-style="noStyle"/>
</template>
<script lang="ts" setup>
@@ -8,5 +9,6 @@ import { } from 'vue';
const props = defineProps<{
reaction: string;
noStyle?: boolean;
+ emojiUrl?: string;
}>();
</script>
diff --git a/packages/frontend/src/components/MkReactionsViewer.reaction.vue b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
index eed6b46594..83fdf0f988 100644
--- a/packages/frontend/src/components/MkReactionsViewer.reaction.vue
+++ b/packages/frontend/src/components/MkReactionsViewer.reaction.vue
@@ -6,7 +6,7 @@
:class="[$style.root, { [$style.reacted]: note.myReaction == reaction, [$style.canToggle]: canToggle }]"
@click="toggleReaction()"
>
- <MkReactionIcon :class="$style.icon" :reaction="reaction"/>
+ <MkReactionIcon :class="$style.icon" :reaction="reaction" :emoji-url="note.reactionEmojis[reaction.substr(1, reaction.length - 2)]"/>
<span :class="$style.count">{{ count }}</span>
</button>
</template>
diff --git a/packages/frontend/src/components/MkSubNoteContent.vue b/packages/frontend/src/components/MkSubNoteContent.vue
index 482a43f474..7e6833dae9 100644
--- a/packages/frontend/src/components/MkSubNoteContent.vue
+++ b/packages/frontend/src/components/MkSubNoteContent.vue
@@ -4,7 +4,7 @@
<span v-if="note.isHidden" style="opacity: 0.5">({{ i18n.ts.private }})</span>
<span v-if="note.deletedAt" style="opacity: 0.5">({{ i18n.ts.deleted }})</span>
<MkA v-if="note.replyId" :class="$style.reply" :to="`/notes/${note.replyId}`"><i class="ti ti-arrow-back-up"></i></MkA>
- <Mfm v-if="note.text" v-once :text="note.text" :author="note.user" :i="$i"/>
+ <Mfm v-if="note.text" v-once :text="note.text" :author="note.user" :i="$i" :emoji-urls="note.emojis"/>
<MkA v-if="note.renoteId" :class="$style.rp" :to="`/notes/${note.renoteId}`">RN: ...</MkA>
</div>
<details v-if="note.files.length > 0">
diff --git a/packages/frontend/src/components/global/MkCustomEmoji.vue b/packages/frontend/src/components/global/MkCustomEmoji.vue
new file mode 100644
index 0000000000..93c47f0c27
--- /dev/null
+++ b/packages/frontend/src/components/global/MkCustomEmoji.vue
@@ -0,0 +1,61 @@
+<template>
+<span v-if="errored">:{{ customEmojiName }}:</span>
+<img v-else :class="[$style.root, { [$style.normal]: normal, [$style.noStyle]: noStyle }]" :src="url" :alt="alt" :title="alt" decoding="async" @error="errored = true" @load="errored = false"/>
+</template>
+
+<script lang="ts" setup>
+import { computed } from 'vue';
+import { getStaticImageUrl } from '@/scripts/media-proxy';
+import { defaultStore } from '@/store';
+import { customEmojis } from '@/custom-emojis';
+
+const props = defineProps<{
+ name: string;
+ normal?: boolean;
+ noStyle?: boolean;
+ host?: string | null;
+ url?: string;
+}>();
+
+const customEmojiName = computed(() => (props.name[0] === ':' ? props.name.substr(1, props.name.length - 2) : props.name).replace('@.', ''));
+const url = computed(() => {
+ if (props.url) {
+ return props.url;
+ } else if (props.host == null && !customEmojiName.value.includes('@')) {
+ const found = customEmojis.value.find(x => x.name === customEmojiName.value);
+ return found ? defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(found.url) : found.url : null;
+ } else {
+ const rawUrl = props.host ? `/emoji/${customEmojiName.value}@${props.host}.webp` : `/emoji/${customEmojiName.value}.webp`;
+ return defaultStore.state.disableShowingAnimatedImages
+ ? getStaticImageUrl(rawUrl)
+ : rawUrl;
+ }
+});
+const alt = computed(() => `:${customEmojiName.value}:`);
+let errored = $ref(url.value == null);
+</script>
+
+<style lang="scss" module>
+.root {
+ height: 2.5em;
+ vertical-align: middle;
+ transition: transform 0.2s ease;
+
+ &:hover {
+ transform: scale(1.2);
+ }
+}
+
+.normal {
+ height: 1.25em;
+ vertical-align: -0.25em;
+
+ &:hover {
+ transform: none;
+ }
+}
+
+.noStyle {
+ height: auto !important;
+}
+</style>
diff --git a/packages/frontend/src/components/global/MkEmoji.vue b/packages/frontend/src/components/global/MkEmoji.vue
index b554d5e47c..1b0d34a445 100644
--- a/packages/frontend/src/components/global/MkEmoji.vue
+++ b/packages/frontend/src/components/global/MkEmoji.vue
@@ -1,54 +1,29 @@
<template>
-<span v-if="isCustom && errored">:{{ customEmojiName }}:</span>
-<img v-else-if="isCustom" :class="[$style.root, $style.custom, { [$style.normal]: normal, [$style.noStyle]: noStyle }]" :src="url" :alt="alt" :title="alt" decoding="async" @error="errored = true" @load="errored = false"/>
-<img v-else-if="char && !useOsNativeEmojis" :class="$style.root" :src="url" :alt="alt" decoding="async" @pointerenter="computeTitle"/>
-<span v-else-if="char && useOsNativeEmojis" :alt="alt" @pointerenter="computeTitle">{{ char }}</span>
+<img v-if="!useOsNativeEmojis" :class="$style.root" :src="url" :alt="props.emoji" decoding="async" @pointerenter="computeTitle"/>
+<span v-else-if="useOsNativeEmojis" :alt="props.emoji" @pointerenter="computeTitle">{{ props.emoji }}</span>
<span v-else>{{ emoji }}</span>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
-import { getStaticImageUrl } from '@/scripts/media-proxy';
import { char2twemojiFilePath, char2fluentEmojiFilePath } from '@/scripts/emoji-base';
import { defaultStore } from '@/store';
import { getEmojiName } from '@/scripts/emojilist';
-import { customEmojis } from '@/custom-emojis';
const props = defineProps<{
emoji: string;
- normal?: boolean;
- noStyle?: boolean;
- isReaction?: boolean;
- host?: string | null;
}>();
const char2path = defaultStore.state.emojiStyle === 'twemoji' ? char2twemojiFilePath : char2fluentEmojiFilePath;
-const isCustom = computed(() => props.emoji.startsWith(':'));
-const customEmojiName = computed(() => props.emoji.substr(1, props.emoji.length - 2).replace('@.', ''));
-const char = computed(() => isCustom.value ? undefined : props.emoji);
-const useOsNativeEmojis = computed(() => defaultStore.state.emojiStyle === 'native' && !props.isReaction);
+const useOsNativeEmojis = computed(() => defaultStore.state.emojiStyle === 'native');
const url = computed(() => {
- if (char.value) {
- return char2path(char.value);
- } else if (props.host == null && !customEmojiName.value.includes('@')) {
- const found = customEmojis.value.find(x => x.name === customEmojiName.value);
- return found ? defaultStore.state.disableShowingAnimatedImages ? getStaticImageUrl(found.url) : found.url : null;
- } else {
- const rawUrl = props.host ? `/emoji/${customEmojiName.value}@${props.host}.webp` : `/emoji/${customEmojiName.value}.webp`;
- return defaultStore.state.disableShowingAnimatedImages
- ? getStaticImageUrl(rawUrl)
- : rawUrl;
- }
+ return char2path(props.emoji);
});
-const alt = computed(() => isCustom.value ? `:${customEmojiName.value}:` : char.value);
-let errored = $ref(isCustom.value && url.value == null);
// Searching from an array with 2000 items for every emoji felt like too energy-consuming, so I decided to do it lazily on pointerenter
function computeTitle(event: PointerEvent): void {
- const title = isCustom.value
- ? `:${customEmojiName.value}:`
- : (getEmojiName(char.value as string) ?? char.value as string);
+ const title = getEmojiName(props.emoji as string) ?? props.emoji as string;
(event.target as HTMLElement).title = title;
}
</script>
@@ -58,27 +33,4 @@ function computeTitle(event: PointerEvent): void {
height: 1.25em;
vertical-align: -0.25em;
}
-
-.custom {
- height: 2.5em;
- vertical-align: middle;
- transition: transform 0.2s ease;
-
- &:hover {
- transform: scale(1.2);
- }
-}
-
-.normal {
- height: 1.25em;
- vertical-align: -0.25em;
-
- &:hover {
- transform: none;
- }
-}
-
-.noStyle {
- height: auto !important;
-}
</style>
diff --git a/packages/frontend/src/components/global/MkUserName.vue b/packages/frontend/src/components/global/MkUserName.vue
index fc08310acc..4186a4a4fb 100644
--- a/packages/frontend/src/components/global/MkUserName.vue
+++ b/packages/frontend/src/components/global/MkUserName.vue
@@ -1,5 +1,5 @@
<template>
-<Mfm :text="user.name ?? user.username" :author="user" :plain="true" :nowrap="nowrap"/>
+<Mfm :text="user.name ?? user.username" :author="user" :plain="true" :nowrap="nowrap" :emoji-urls="user.emojis"/>
</template>
<script lang="ts" setup>
diff --git a/packages/frontend/src/components/index.ts b/packages/frontend/src/components/index.ts
index 8639257003..560870f84c 100644
--- a/packages/frontend/src/components/index.ts
+++ b/packages/frontend/src/components/index.ts
@@ -5,6 +5,7 @@ import MkA from './global/MkA.vue';
import MkAcct from './global/MkAcct.vue';
import MkAvatar from './global/MkAvatar.vue';
import MkEmoji from './global/MkEmoji.vue';
+import MkCustomEmoji from './global/MkCustomEmoji.vue';
import MkUserName from './global/MkUserName.vue';
import MkEllipsis from './global/MkEllipsis.vue';
import MkTime from './global/MkTime.vue';
@@ -26,6 +27,7 @@ export default function(app: App) {
app.component('MkAcct', MkAcct);
app.component('MkAvatar', MkAvatar);
app.component('MkEmoji', MkEmoji);
+ app.component('MkCustomEmoji', MkCustomEmoji);
app.component('MkUserName', MkUserName);
app.component('MkEllipsis', MkEllipsis);
app.component('MkTime', MkTime);
@@ -47,6 +49,7 @@ declare module '@vue/runtime-core' {
MkAcct: typeof MkAcct;
MkAvatar: typeof MkAvatar;
MkEmoji: typeof MkEmoji;
+ MkCustomEmoji: typeof MkCustomEmoji;
MkUserName: typeof MkUserName;
MkEllipsis: typeof MkEllipsis;
MkTime: typeof MkTime;
diff --git a/packages/frontend/src/components/mfm.ts b/packages/frontend/src/components/mfm.ts
index b9ed9002ac..7cfb19aeb6 100644
--- a/packages/frontend/src/components/mfm.ts
+++ b/packages/frontend/src/components/mfm.ts
@@ -4,6 +4,7 @@ import MkUrl from '@/components/global/MkUrl.vue';
import MkLink from '@/components/MkLink.vue';
import MkMention from '@/components/MkMention.vue';
import MkEmoji from '@/components/global/MkEmoji.vue';
+import MkCustomEmoji from '@/components/global/MkCustomEmoji.vue';
import { concat } from '@/scripts/array';
import MkCode from '@/components/MkCode.vue';
import MkGoogle from '@/components/MkGoogle.vue';
@@ -47,6 +48,10 @@ export default defineComponent({
type: Boolean,
default: true,
},
+ emojiUrls: {
+ type: Object,
+ default: null,
+ },
},
render() {
@@ -301,20 +306,35 @@ export default defineComponent({
}
case 'emojiCode': {
- return [h(MkEmoji, {
- key: Math.random(),
- emoji: `:${token.props.name}:`,
- normal: this.plain,
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ if (this.author?.host == null) {
+ return [h(MkCustomEmoji, {
+ key: Math.random(),
+ name: token.props.name,
+ normal: this.plain,
+ host: null,
+ })];
+ } else {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
- host: this.author?.host,
- })];
+ if (this.emojiUrls && (this.emojiUrls[token.props.name] == null)) {
+ return [h('span', `:${token.props.name}:`)];
+ } else {
+ return [h(MkCustomEmoji, {
+ key: Math.random(),
+ name: token.props.name,
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
+ url: this.emojiUrls ? this.emojiUrls[token.props.name] : null,
+ normal: this.plain,
+ host: this.author.host,
+ })];
+ }
+ }
}
case 'unicodeEmoji': {
return [h(MkEmoji, {
key: Math.random(),
emoji: token.props.emoji,
- normal: this.plain,
})];
}
diff --git a/packages/frontend/src/custom-emojis.ts b/packages/frontend/src/custom-emojis.ts
index 0ba7cab5e2..9ce370e7e8 100644
--- a/packages/frontend/src/custom-emojis.ts
+++ b/packages/frontend/src/custom-emojis.ts
@@ -1,6 +1,6 @@
import { shallowRef, computed, markRaw } from 'vue';
import * as Misskey from 'misskey-js';
-import { apiGet } from './os';
+import { api, apiGet } from './os';
import { miLocalStorage } from './local-storage';
import { stream } from '@/stream';
@@ -28,12 +28,17 @@ stream.on('emojiDeleted', emojiData => {
customEmojis.value = customEmojis.value.filter(item => !emojiData.emojis.some(search => search.name === item.name));
});
-export async function fetchCustomEmojis() {
+export async function fetchCustomEmojis(force = false) {
const now = Date.now();
- const lastFetchedAt = miLocalStorage.getItem('lastEmojisFetchedAt');
- if (lastFetchedAt && (now - parseInt(lastFetchedAt)) < 1000 * 60 * 60) return;
- const res = await apiGet('emojis', {});
+ let res;
+ if (force) {
+ res = await api('emojis', {});
+ } else {
+ const lastFetchedAt = miLocalStorage.getItem('lastEmojisFetchedAt');
+ if (lastFetchedAt && (now - parseInt(lastFetchedAt)) < 1000 * 60 * 60) return;
+ res = await apiGet('emojis', {});
+ }
customEmojis.value = res.emojis;
miLocalStorage.setItem('emojis', JSON.stringify(res.emojis));
diff --git a/packages/frontend/src/pages/about-misskey.vue b/packages/frontend/src/pages/about-misskey.vue
index bc63d7159a..6d88feceaf 100644
--- a/packages/frontend/src/pages/about-misskey.vue
+++ b/packages/frontend/src/pages/about-misskey.vue
@@ -9,7 +9,10 @@
<img src="/client-assets/about-icon.png" alt="" class="icon" draggable="false" @load="iconLoaded" @click="gravity"/>
<div class="misskey">Misskey</div>
<div class="version">v{{ version }}</div>
- <span v-for="emoji in easterEggEmojis" :key="emoji.id" class="emoji" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }"><MkEmoji class="emoji" :emoji="emoji.emoji" :is-reaction="false" :normal="true" :no-style="true"/></span>
+ <span v-for="emoji in easterEggEmojis" :key="emoji.id" class="emoji" :data-physics-x="emoji.left" :data-physics-y="emoji.top" :class="{ _physics_circle_: !emoji.emoji.startsWith(':') }">
+ <MkCustomEmoji v-if="emoji.emoji[0] === ':'" class="emoji" :name="emoji.emoji" :normal="true" :no-style="true"/>
+ <MkEmoji v-else class="emoji" :emoji="emoji.emoji" :normal="true" :no-style="true"/>
+ </span>
</div>
<button v-if="thereIsTreasure" class="_button treasure" @click="getTreasure"><img src="/fluent-emoji/1f3c6.png" class="treasureImg"></button>
</div>
diff --git a/packages/frontend/src/pages/admin/overview.stats.vue b/packages/frontend/src/pages/admin/overview.stats.vue
index ce68222fbb..bd636cc3ef 100644
--- a/packages/frontend/src/pages/admin/overview.stats.vue
+++ b/packages/frontend/src/pages/admin/overview.stats.vue
@@ -45,7 +45,7 @@
<div class="icon"><i class="ti ti-access-point"></i></div>
<div class="body">
<div class="value">
- <MkNumber :value="stats.onlineUsersCount" style="margin-right: 0.5em;"/>
+ <MkNumber :value="onlineUsersCount" style="margin-right: 0.5em;"/>
</div>
<div class="label">Online</div>
</div>
diff --git a/packages/frontend/src/pages/settings/index.vue b/packages/frontend/src/pages/settings/index.vue
index e1e050ee70..4dbc6ec74c 100644
--- a/packages/frontend/src/pages/settings/index.vue
+++ b/packages/frontend/src/pages/settings/index.vue
@@ -34,6 +34,7 @@ import { useRouter } from '@/router';
import { definePageMetadata, provideMetadataReceiver, setPageMetadata } from '@/scripts/page-metadata';
import * as os from '@/os';
import { miLocalStorage } from '@/local-storage';
+import { fetchCustomEmojis } from '@/custom-emojis';
const indexInfo = {
title: i18n.ts.settings,
@@ -180,11 +181,13 @@ const menuDef = computed(() => [{
type: 'button',
icon: 'ti ti-trash',
text: i18n.ts.clearCache,
- action: () => {
+ action: async () => {
+ os.waiting();
miLocalStorage.removeItem('locale');
miLocalStorage.removeItem('theme');
miLocalStorage.removeItem('emojis');
miLocalStorage.removeItem('lastEmojisFetchedAt');
+ await fetchCustomEmojis();
unisonReload();
},
}, {
diff --git a/packages/frontend/src/pages/settings/reaction.vue b/packages/frontend/src/pages/settings/reaction.vue
index e307abe2d4..c8b47b8299 100644
--- a/packages/frontend/src/pages/settings/reaction.vue
+++ b/packages/frontend/src/pages/settings/reaction.vue
@@ -6,7 +6,8 @@
<Sortable v-model="reactions" class="zoaiodol" :item-key="item => item" :animation="150" :delay="100" :delay-on-touch-only="true">
<template #item="{element}">
<button class="_button item" @click="remove(element, $event)">
- <MkEmoji :emoji="element" :normal="true"/>
+ <MkCustomEmoji v-if="element[0] === ':'" :name="element" :normal="true"/>
+ <MkEmoji v-else :emoji="element" :normal="true"/>
</button>
</template>
<template #footer>
diff --git a/packages/frontend/src/scripts/device-kind.ts b/packages/frontend/src/scripts/device-kind.ts
index 544cac0604..6bb349c554 100644
--- a/packages/frontend/src/scripts/device-kind.ts
+++ b/packages/frontend/src/scripts/device-kind.ts
@@ -4,7 +4,7 @@ const ua = navigator.userAgent.toLowerCase();
const isTablet = /ipad/.test(ua) || (/mobile|iphone|android/.test(ua) && window.innerWidth > 700);
const isSmartphone = !isTablet && /mobile|iphone|android/.test(ua);
-export const deviceKind = defaultStore.state.overridedDeviceKind ? defaultStore.state.overridedDeviceKind
+export const deviceKind: 'smartphone' | 'tablet' | 'desktop' = defaultStore.state.overridedDeviceKind ? defaultStore.state.overridedDeviceKind
: isSmartphone ? 'smartphone'
: isTablet ? 'tablet'
: 'desktop';
diff --git a/packages/frontend/src/scripts/use-note-capture.ts b/packages/frontend/src/scripts/use-note-capture.ts
index 389ee12561..ffe33cccc0 100644
--- a/packages/frontend/src/scripts/use-note-capture.ts
+++ b/packages/frontend/src/scripts/use-note-capture.ts
@@ -20,11 +20,8 @@ export function useNoteCapture(props: {
case 'reacted': {
const reaction = body.reaction;
- if (body.emoji) {
- const emojis = note.value.emojis || [];
- if (!emojis.includes(body.emoji)) {
- note.value.emojis = [...emojis, body.emoji];
- }
+ if (body.emoji && !(body.emoji.name in note.value.reactionEmojis)) {
+ note.value.reactionEmojis[body.emoji.name] = body.emoji.url;
}
// TODO: reactionsプロパティがない場合ってあったっけ? なければ || {} は消せる
diff --git a/packages/frontend/src/store.ts b/packages/frontend/src/store.ts
index b29d9355ba..f9ad50b30d 100644
--- a/packages/frontend/src/store.ts
+++ b/packages/frontend/src/store.ts
@@ -156,7 +156,7 @@ export const defaultStore = markRaw(new Storage('base', {
},
animation: {
where: 'device',
- default: true,
+ default: !matchMedia('(prefers-reduced-motion)').matches,
},
animatedMfm: {
where: 'device',
@@ -184,11 +184,11 @@ export const defaultStore = markRaw(new Storage('base', {
},
useBlurEffectForModal: {
where: 'device',
- default: true,
+ default: !/mobile|iphone|android/.test(navigator.userAgent.toLowerCase()), // 循環参照するのでdevice-kind.tsは参照できない
},
useBlurEffect: {
where: 'device',
- default: true,
+ default: !/mobile|iphone|android/.test(navigator.userAgent.toLowerCase()), // 循環参照するのでdevice-kind.tsは参照できない
},
showFixedPostForm: {
where: 'device',
diff --git a/packages/frontend/src/ui/_common_/notification.vue b/packages/frontend/src/ui/_common_/notification.vue
index 1f9c675a15..06dfcb0a23 100644
--- a/packages/frontend/src/ui/_common_/notification.vue
+++ b/packages/frontend/src/ui/_common_/notification.vue
@@ -1,6 +1,6 @@
<template>
<div :class="$style.root">
- <XNotification :notification="notification" class="notification _acrylic"/>
+ <XNotification :notification="notification" class="notification _acrylic" :full="false"/>
</div>
</template>
diff --git a/packages/sw/package.json b/packages/sw/package.json
index 163cdf5926..ef46112dac 100644
--- a/packages/sw/package.json
+++ b/packages/sw/package.json
@@ -7,15 +7,15 @@
"lint": "tsc --noEmit && eslint --quiet src/**/*.ts"
},
"dependencies": {
- "esbuild": "^0.14.42",
- "idb-keyval": "^6.1.0",
+ "esbuild": "^0.17.4",
+ "idb-keyval": "^6.2.0",
"misskey-js": "0.0.14"
},
"devDependencies": {
- "@typescript-eslint/parser": "^5.45.0",
- "@typescript/lib-webworker": "npm:@types/serviceworker@^0.0.58",
- "eslint": "^8.16.0",
- "eslint-plugin-import": "^2.26.0",
+ "@typescript-eslint/parser": "^5.49.0",
+ "@typescript/lib-webworker": "npm:@types/serviceworker@0.0.61",
+ "eslint": "^8.32.0",
+ "eslint-plugin-import": "^2.27.5",
"typescript": "4.9.4"
}
}
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a6b7699e2c..dda76c38f0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -14,7 +14,7 @@ importers:
'@typescript-eslint/eslint-plugin': 5.49.0
'@typescript-eslint/parser': 5.49.0
cross-env: 7.0.3
- cypress: 12.3.0
+ cypress: 12.4.0
eslint: ^8.32.0
execa: 5.1.1
gulp: 4.0.2
@@ -42,7 +42,7 @@ importers:
'@typescript-eslint/eslint-plugin': 5.49.0_iu322prlnwsygkcra5kbpy22si
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje
cross-env: 7.0.3
- cypress: 12.3.0
+ cypress: 12.4.0
eslint: 8.32.0
start-server-and-test: 1.15.3
@@ -57,8 +57,8 @@ importers:
'@fastify/cors': 8.2.0
'@fastify/http-proxy': ^8.4.0
'@fastify/multipart': 7.4.0
- '@fastify/static': 6.6.1
- '@fastify/view': 7.4.0
+ '@fastify/static': 6.7.0
+ '@fastify/view': 7.4.1
'@nestjs/common': 9.2.1
'@nestjs/core': 9.2.1
'@nestjs/testing': 9.2.1
@@ -66,7 +66,7 @@ importers:
'@redocly/openapi-core': 1.0.0-beta.120
'@sinonjs/fake-timers': 10.0.2
'@swc/cli': ^0.1.59
- '@swc/core': 1.3.27
+ '@swc/core': 1.3.29
'@swc/jest': 0.2.24
'@tensorflow/tfjs': ^4.2.0
'@tensorflow/tfjs-node': 4.2.0
@@ -80,11 +80,11 @@ importers:
'@types/escape-regexp': 0.0.1
'@types/fluent-ffmpeg': 2.1.20
'@types/ioredis': 4.28.10
- '@types/jest': 29.2.6
+ '@types/jest': 29.4.0
'@types/js-yaml': 4.0.5
'@types/jsdom': 20.0.1
'@types/jsonld': 1.5.8
- '@types/jsrsasign': 10.5.4
+ '@types/jsrsasign': 10.5.5
'@types/mime-types': 2.1.1
'@types/node': 18.11.18
'@types/node-fetch': 3.0.3
@@ -147,8 +147,8 @@ importers:
ioredis: 4.28.5
ip-cidr: 3.0.11
is-svg: 4.3.2
- jest: 29.3.1
- jest-mock: ^29.3.1
+ jest: 29.4.1
+ jest-mock: ^29.4.1
js-yaml: 4.1.0
jsdom: 21.1.0
json5: 2.2.3
@@ -192,7 +192,7 @@ importers:
stringz: 2.1.0
summaly: 2.7.0
syslog-pro: git+https://github.com/misskey-dev/SyslogPro#0.2.9-misskey.2
- systeminformation: 5.17.3
+ systeminformation: 5.17.4
tinycolor2: 1.5.2
tmp: 0.2.1
tsc-alias: 1.8.2
@@ -218,8 +218,8 @@ importers:
'@fastify/cors': 8.2.0
'@fastify/http-proxy': 8.4.0
'@fastify/multipart': 7.4.0
- '@fastify/static': 6.6.1
- '@fastify/view': 7.4.0
+ '@fastify/static': 6.7.0
+ '@fastify/view': 7.4.1
'@nestjs/common': 9.2.1_mnr6j2del53muneqly5h4y27ai
'@nestjs/core': 9.2.1_b4pxbpa7chblgbyake5iz5rdmu
'@nestjs/testing': 9.2.1_hjcqpoaebdr7gdo5hgc22hthbe
@@ -297,7 +297,7 @@ importers:
stringz: 2.1.0
summaly: 2.7.0
syslog-pro: github.com/misskey-dev/SyslogPro/2772b33fa126784fc6e21377786471a918b22dc7
- systeminformation: 5.17.3
+ systeminformation: 5.17.4
tinycolor2: 1.5.2
tmp: 0.2.1
tsc-alias: 1.8.2
@@ -318,9 +318,9 @@ importers:
'@tensorflow/tfjs-node': 4.2.0_seedrandom@3.0.5
devDependencies:
'@redocly/openapi-core': 1.0.0-beta.120
- '@swc/cli': 0.1.59_2w2rsb5d2wh3txrlxuiknf4vra
- '@swc/core': 1.3.27
- '@swc/jest': 0.2.24_@swc+core@1.3.27
+ '@swc/cli': 0.1.59_dbbgdut2njxjatv5n3st5z6gqa
+ '@swc/core': 1.3.29
+ '@swc/jest': 0.2.24_@swc+core@1.3.29
'@types/accepts': 1.3.5
'@types/archiver': 5.3.1
'@types/bcryptjs': 2.4.2
@@ -331,11 +331,11 @@ importers:
'@types/escape-regexp': 0.0.1
'@types/fluent-ffmpeg': 2.1.20
'@types/ioredis': 4.28.10
- '@types/jest': 29.2.6
+ '@types/jest': 29.4.0
'@types/js-yaml': 4.0.5
'@types/jsdom': 20.0.1
'@types/jsonld': 1.5.8
- '@types/jsrsasign': 10.5.4
+ '@types/jsrsasign': 10.5.5
'@types/mime-types': 2.1.1
'@types/node': 18.11.18
'@types/node-fetch': 3.0.3
@@ -369,8 +369,8 @@ importers:
eslint: 8.32.0
eslint-plugin-import: 2.27.5_6savw6y3b7jng6f64kgkyoij64
execa: 6.1.0
- jest: 29.3.1_@types+node@18.11.18
- jest-mock: 29.3.1
+ jest: 29.4.1_@types+node@18.11.18
+ jest-mock: 29.4.1
packages/frontend:
specifiers:
@@ -379,7 +379,7 @@ importers:
'@rollup/plugin-json': 6.0.0
'@rollup/pluginutils': 5.0.2
'@syuilo/aiscript': 0.12.2
- '@tabler/icons-webfont': ^2.0.0
+ '@tabler/icons-webfont': ^2.1.2
'@types/escape-regexp': 0.0.1
'@types/glob': 8.0.1
'@types/gulp': 4.0.10
@@ -413,7 +413,7 @@ importers:
compare-versions: 5.0.1
cropperjs: 2.0.0-beta.2
cross-env: 7.0.3
- cypress: 12.3.0
+ cypress: 12.4.0
date-fns: 2.29.3
escape-regexp: 0.0.1
eslint: 8.32.0
@@ -433,7 +433,7 @@ importers:
punycode: 2.3.0
querystring: 0.2.1
rndstr: 1.0.0
- rollup: 3.10.1
+ rollup: 3.11.0
s-age: 1.1.2
sanitize-html: ^2.8.1
sass: 1.57.1
@@ -443,7 +443,7 @@ importers:
stringz: 2.1.0
syuilo-password-strength: 0.0.1
textarea-caret: 3.1.0
- three: 0.148.0
+ three: 0.149.0
throttle-debounce: 5.0.0
tinycolor2: 1.5.2
tsc-alias: 1.8.2
@@ -460,11 +460,11 @@ importers:
vuedraggable: next
dependencies:
'@discordapp/twemoji': 14.0.2
- '@rollup/plugin-alias': 4.0.3_rollup@3.10.1
- '@rollup/plugin-json': 6.0.0_rollup@3.10.1
- '@rollup/pluginutils': 5.0.2_rollup@3.10.1
+ '@rollup/plugin-alias': 4.0.3_rollup@3.11.0
+ '@rollup/plugin-json': 6.0.0_rollup@3.11.0
+ '@rollup/pluginutils': 5.0.2_rollup@3.11.0
'@syuilo/aiscript': 0.12.2
- '@tabler/icons-webfont': 2.0.0
+ '@tabler/icons-webfont': 2.1.2
'@vitejs/plugin-vue': 4.0.0_vite@4.0.4+vue@3.2.45
'@vue/compiler-sfc': 3.2.45
autobind-decorator: 2.4.0
@@ -496,7 +496,7 @@ importers:
punycode: 2.3.0
querystring: 0.2.1
rndstr: 1.0.0
- rollup: 3.10.1
+ rollup: 3.11.0
s-age: 1.1.2
sanitize-html: 2.8.1
sass: 1.57.1
@@ -505,7 +505,7 @@ importers:
stringz: 2.1.0
syuilo-password-strength: 0.0.1
textarea-caret: 3.1.0
- three: 0.148.0
+ three: 0.149.0
throttle-debounce: 5.0.0
tinycolor2: 1.5.2
tsc-alias: 1.8.2
@@ -537,7 +537,7 @@ importers:
'@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje
'@vue/runtime-core': 3.2.45
cross-env: 7.0.3
- cypress: 12.3.0
+ cypress: 12.4.0
eslint: 8.32.0
eslint-plugin-import: 2.27.5_6savw6y3b7jng6f64kgkyoij64
eslint-plugin-vue: 9.9.0_eslint@8.32.0
@@ -547,23 +547,23 @@ importers:
packages/sw:
specifiers:
- '@typescript-eslint/parser': ^5.45.0
- '@typescript/lib-webworker': npm:@types/serviceworker@^0.0.58
- esbuild: ^0.14.42
- eslint: ^8.16.0
- eslint-plugin-import: ^2.26.0
- idb-keyval: ^6.1.0
+ '@typescript-eslint/parser': ^5.49.0
+ '@typescript/lib-webworker': npm:@types/serviceworker@0.0.61
+ esbuild: ^0.17.4
+ eslint: ^8.32.0
+ eslint-plugin-import: ^2.27.5
+ idb-keyval: ^6.2.0
misskey-js: 0.0.14
typescript: 4.9.4
dependencies:
- esbuild: 0.14.54
+ esbuild: 0.17.4
idb-keyval: 6.2.0
misskey-js: 0.0.14
devDependencies:
- '@typescript-eslint/parser': 5.48.1_iukboom6ndih5an6iafl45j2fe
- '@typescript/lib-webworker': /@types/serviceworker/0.0.58
- eslint: 8.31.0
- eslint-plugin-import: 2.27.4_qdjeohovcytra7xto5vgmxssaq
+ '@typescript-eslint/parser': 5.49.0_7uibuqfxkfaozanbtbziikiqje
+ '@typescript/lib-webworker': /@types/serviceworker/0.0.61
+ eslint: 8.32.0
+ eslint-plugin-import: 2.27.5_6savw6y3b7jng6f64kgkyoij64
typescript: 4.9.4
packages:
@@ -922,8 +922,8 @@ packages:
dependencies:
'@bull-board/api': 4.11.0
'@bull-board/ui': 4.11.0
- '@fastify/static': 6.6.1
- '@fastify/view': 7.4.0
+ '@fastify/static': 6.7.0
+ '@fastify/view': 7.4.1
ejs: 3.1.8
transitivePeerDependencies:
- supports-color
@@ -1096,6 +1096,15 @@ packages:
dev: false
optional: true
+ /@esbuild/android-arm/0.17.4:
+ resolution: {integrity: sha512-R9GCe2xl2XDSc2XbQB63mFiFXHIVkOP+ltIxICKXqUPrFX97z6Z7vONCLQM1pSOLGqfLrGi3B7nbhxmFY/fomg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/android-arm64/0.16.17:
resolution: {integrity: sha512-MIGl6p5sc3RDTLLkYL1MyL8BMRN4tLMRCn+yRJJmEDvYZ2M7tmAf80hx1kbNEUX2KJ50RRtxZ4JHLvCfuB6kBg==}
engines: {node: '>=12'}
@@ -1105,6 +1114,15 @@ packages:
dev: false
optional: true
+ /@esbuild/android-arm64/0.17.4:
+ resolution: {integrity: sha512-91VwDrl4EpxBCiG6h2LZZEkuNvVZYJkv2T9gyLG/mhGG1qrM7i5SwUcg/hlSPnL/4hDT0TFcF35/XMGSn0bemg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/android-x64/0.16.17:
resolution: {integrity: sha512-a3kTv3m0Ghh4z1DaFEuEDfz3OLONKuFvI4Xqczqx4BqLyuFaFkuaG4j2MtA6fuWEFeC5x9IvqnX7drmRq/fyAQ==}
engines: {node: '>=12'}
@@ -1114,6 +1132,15 @@ packages:
dev: false
optional: true
+ /@esbuild/android-x64/0.17.4:
+ resolution: {integrity: sha512-mGSqhEPL7029XL7QHNPxPs15JVa02hvZvysUcyMP9UXdGFwncl2WU0bqx+Ysgzd+WAbv8rfNa73QveOxAnAM2w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/darwin-arm64/0.16.17:
resolution: {integrity: sha512-/2agbUEfmxWHi9ARTX6OQ/KgXnOWfsNlTeLcoV7HSuSTv63E4DqtAc+2XqGw1KHxKMHGZgbVCZge7HXWX9Vn+w==}
engines: {node: '>=12'}
@@ -1123,6 +1150,15 @@ packages:
dev: false
optional: true
+ /@esbuild/darwin-arm64/0.17.4:
+ resolution: {integrity: sha512-tTyJRM9dHvlMPt1KrBFVB5OW1kXOsRNvAPtbzoKazd5RhD5/wKlXk1qR2MpaZRYwf4WDMadt0Pv0GwxB41CVow==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/darwin-x64/0.16.17:
resolution: {integrity: sha512-2By45OBHulkd9Svy5IOCZt376Aa2oOkiE9QWUK9fe6Tb+WDr8hXL3dpqi+DeLiMed8tVXspzsTAvd0jUl96wmg==}
engines: {node: '>=12'}
@@ -1132,6 +1168,15 @@ packages:
dev: false
optional: true
+ /@esbuild/darwin-x64/0.17.4:
+ resolution: {integrity: sha512-phQuC2Imrb3TjOJwLN8EO50nb2FHe8Ew0OwgZDH1SV6asIPGudnwTQtighDF2EAYlXChLoMJwqjAp4vAaACq6w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/freebsd-arm64/0.16.17:
resolution: {integrity: sha512-mt+cxZe1tVx489VTb4mBAOo2aKSnJ33L9fr25JXpqQqzbUIw/yzIzi+NHwAXK2qYV1lEFp4OoVeThGjUbmWmdw==}
engines: {node: '>=12'}
@@ -1141,6 +1186,15 @@ packages:
dev: false
optional: true
+ /@esbuild/freebsd-arm64/0.17.4:
+ resolution: {integrity: sha512-oH6JUZkocgmjzzYaP5juERLpJQSwazdjZrTPgLRmAU2bzJ688x0vfMB/WTv4r58RiecdHvXOPC46VtsMy/mepg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/freebsd-x64/0.16.17:
resolution: {integrity: sha512-8ScTdNJl5idAKjH8zGAsN7RuWcyHG3BAvMNpKOBaqqR7EbUhhVHOqXRdL7oZvz8WNHL2pr5+eIT5c65kA6NHug==}
engines: {node: '>=12'}
@@ -1150,6 +1204,15 @@ packages:
dev: false
optional: true
+ /@esbuild/freebsd-x64/0.17.4:
+ resolution: {integrity: sha512-U4iWGn/9TrAfpAdfd56eO0pRxIgb0a8Wj9jClrhT8hvZnOnS4dfMPW7o4fn15D/KqoiVYHRm43jjBaTt3g/2KA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/linux-arm/0.16.17:
resolution: {integrity: sha512-iihzrWbD4gIT7j3caMzKb/RsFFHCwqqbrbH9SqUSRrdXkXaygSZCZg1FybsZz57Ju7N/SHEgPyaR0LZ8Zbe9gQ==}
engines: {node: '>=12'}
@@ -1159,6 +1222,15 @@ packages:
dev: false
optional: true
+ /@esbuild/linux-arm/0.17.4:
+ resolution: {integrity: sha512-S2s9xWTGMTa/fG5EyMGDeL0wrWVgOSQcNddJWgu6rG1NCSXJHs76ZP9AsxjB3f2nZow9fWOyApklIgiTGZKhiw==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/linux-arm64/0.16.17:
resolution: {integrity: sha512-7S8gJnSlqKGVJunnMCrXHU9Q8Q/tQIxk/xL8BqAP64wchPCTzuM6W3Ra8cIa1HIflAvDnNOt2jaL17vaW+1V0g==}
engines: {node: '>=12'}
@@ -1168,6 +1240,15 @@ packages:
dev: false
optional: true
+ /@esbuild/linux-arm64/0.17.4:
+ resolution: {integrity: sha512-UkGfQvYlwOaeYJzZG4cLV0hCASzQZnKNktRXUo3/BMZvdau40AOz9GzmGA063n1piq6VrFFh43apRDQx8hMP2w==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/linux-ia32/0.16.17:
resolution: {integrity: sha512-kiX69+wcPAdgl3Lonh1VI7MBr16nktEvOfViszBSxygRQqSpzv7BffMKRPMFwzeJGPxcio0pdD3kYQGpqQ2SSg==}
engines: {node: '>=12'}
@@ -1177,10 +1258,10 @@ packages:
dev: false
optional: true
- /@esbuild/linux-loong64/0.14.54:
- resolution: {integrity: sha512-bZBrLAIX1kpWelV0XemxBZllyRmM6vgFQQG2GdNb+r3Fkp0FOh1NJSvekXDs7jq70k4euu1cryLMfU+mTXlEpw==}
+ /@esbuild/linux-ia32/0.17.4:
+ resolution: {integrity: sha512-3lqFi4VFo/Vwvn77FZXeLd0ctolIJH/uXkH3yNgEk89Eh6D3XXAC9/iTPEzeEpsNE5IqGIsFa5Z0iPeOh25IyA==}
engines: {node: '>=12'}
- cpu: [loong64]
+ cpu: [ia32]
os: [linux]
requiresBuild: true
dev: false
@@ -1195,6 +1276,15 @@ packages:
dev: false
optional: true
+ /@esbuild/linux-loong64/0.17.4:
+ resolution: {integrity: sha512-HqpWZkVslDHIwdQ9D+gk7NuAulgQvRxF9no54ut/M55KEb3mi7sQS3GwpPJzSyzzP0UkjQVN7/tbk88/CaX4EQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/linux-mips64el/0.16.17:
resolution: {integrity: sha512-ezbDkp2nDl0PfIUn0CsQ30kxfcLTlcx4Foz2kYv8qdC6ia2oX5Q3E/8m6lq84Dj/6b0FrkgD582fJMIfHhJfSw==}
engines: {node: '>=12'}
@@ -1204,6 +1294,15 @@ packages:
dev: false
optional: true
+ /@esbuild/linux-mips64el/0.17.4:
+ resolution: {integrity: sha512-d/nMCKKh/SVDbqR9ju+b78vOr0tNXtfBjcp5vfHONCCOAL9ad8gN9dC/u+UnH939pz7wO+0u/x9y1MaZcb/lKA==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/linux-ppc64/0.16.17:
resolution: {integrity: sha512-dzS678gYD1lJsW73zrFhDApLVdM3cUF2MvAa1D8K8KtcSKdLBPP4zZSLy6LFZ0jYqQdQ29bjAHJDgz0rVbLB3g==}
engines: {node: '>=12'}
@@ -1213,6 +1312,15 @@ packages:
dev: false
optional: true
+ /@esbuild/linux-ppc64/0.17.4:
+ resolution: {integrity: sha512-lOD9p2dmjZcNiTU+sGe9Nn6G3aYw3k0HBJies1PU0j5IGfp6tdKOQ6mzfACRFCqXjnBuTqK7eTYpwx09O5LLfg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/linux-riscv64/0.16.17:
resolution: {integrity: sha512-ylNlVsxuFjZK8DQtNUwiMskh6nT0vI7kYl/4fZgV1llP5d6+HIeL/vmmm3jpuoo8+NuXjQVZxmKuhDApK0/cKw==}
engines: {node: '>=12'}
@@ -1222,6 +1330,15 @@ packages:
dev: false
optional: true
+ /@esbuild/linux-riscv64/0.17.4:
+ resolution: {integrity: sha512-mTGnwWwVshAjGsd8rP+K6583cPDgxOunsqqldEYij7T5/ysluMHKqUIT4TJHfrDFadUwrghAL6QjER4FeqQXoA==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/linux-s390x/0.16.17:
resolution: {integrity: sha512-gzy7nUTO4UA4oZ2wAMXPNBGTzZFP7mss3aKR2hH+/4UUkCOyqmjXiKpzGrY2TlEUhbbejzXVKKGazYcQTZWA/w==}
engines: {node: '>=12'}
@@ -1231,6 +1348,15 @@ packages:
dev: false
optional: true
+ /@esbuild/linux-s390x/0.17.4:
+ resolution: {integrity: sha512-AQYuUGp50XM29/N/dehADxvc2bUqDcoqrVuijop1Wv72SyxT6dDB9wjUxuPZm2HwIM876UoNNBMVd+iX/UTKVQ==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/linux-x64/0.16.17:
resolution: {integrity: sha512-mdPjPxfnmoqhgpiEArqi4egmBAMYvaObgn4poorpUaqmvzzbvqbowRllQ+ZgzGVMGKaPkqUmPDOOFQRUFDmeUw==}
engines: {node: '>=12'}
@@ -1240,6 +1366,15 @@ packages:
dev: false
optional: true
+ /@esbuild/linux-x64/0.17.4:
+ resolution: {integrity: sha512-+AsFBwKgQuhV2shfGgA9YloxLDVjXgUEWZum7glR5lLmV94IThu/u2JZGxTgjYby6kyXEx8lKOqP5rTEVBR0Rw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/netbsd-x64/0.16.17:
resolution: {integrity: sha512-/PzmzD/zyAeTUsduZa32bn0ORug+Jd1EGGAUJvqfeixoEISYpGnAezN6lnJoskauoai0Jrs+XSyvDhppCPoKOA==}
engines: {node: '>=12'}
@@ -1249,6 +1384,15 @@ packages:
dev: false
optional: true
+ /@esbuild/netbsd-x64/0.17.4:
+ resolution: {integrity: sha512-zD1TKYX9553OiLS/qkXPMlWoELYkH/VkzRYNKEU+GwFiqkq0SuxsKnsCg5UCdxN3cqd+1KZ8SS3R+WG/Hxy2jQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/openbsd-x64/0.16.17:
resolution: {integrity: sha512-2yaWJhvxGEz2RiftSk0UObqJa/b+rIAjnODJgv2GbGGpRwAfpgzyrg1WLK8rqA24mfZa9GvpjLcBBg8JHkoodg==}
engines: {node: '>=12'}
@@ -1258,6 +1402,15 @@ packages:
dev: false
optional: true
+ /@esbuild/openbsd-x64/0.17.4:
+ resolution: {integrity: sha512-PY1NjEsLRhPEFFg1AV0/4Or/gR+q2dOb9s5rXcPuCjyHRzbt8vnHJl3vYj+641TgWZzTFmSUnZbzs1zwTzjeqw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/sunos-x64/0.16.17:
resolution: {integrity: sha512-xtVUiev38tN0R3g8VhRfN7Zl42YCJvyBhRKw1RJjwE1d2emWTVToPLNEQj/5Qxc6lVFATDiy6LjVHYhIPrLxzw==}
engines: {node: '>=12'}
@@ -1267,6 +1420,15 @@ packages:
dev: false
optional: true
+ /@esbuild/sunos-x64/0.17.4:
+ resolution: {integrity: sha512-B3Z7s8QZQW9tKGleMRXvVmwwLPAUoDCHs4WZ2ElVMWiortLJFowU1NjAhXOKjDgC7o9ByeVcwyOlJ+F2r6ZgmQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/win32-arm64/0.16.17:
resolution: {integrity: sha512-ga8+JqBDHY4b6fQAmOgtJJue36scANy4l/rL97W+0wYmijhxKetzZdKOJI7olaBaMhWt8Pac2McJdZLxXWUEQw==}
engines: {node: '>=12'}
@@ -1276,6 +1438,15 @@ packages:
dev: false
optional: true
+ /@esbuild/win32-arm64/0.17.4:
+ resolution: {integrity: sha512-0HCu8R3mY/H5V7N6kdlsJkvrT591bO/oRZy8ztF1dhgNU5xD5tAh5bKByT1UjTGjp/VVBsl1PDQ3L18SfvtnBQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/win32-ia32/0.16.17:
resolution: {integrity: sha512-WnsKaf46uSSF/sZhwnqE4L/F89AYNMiD4YtEcYekBt9Q7nj0DiId2XH2Ng2PHM54qi5oPrQ8luuzGszqi/veig==}
engines: {node: '>=12'}
@@ -1285,6 +1456,15 @@ packages:
dev: false
optional: true
+ /@esbuild/win32-ia32/0.17.4:
+ resolution: {integrity: sha512-VUjhVDQycse1gLbe06pC/uaA0M+piQXJpdpNdhg8sPmeIZZqu5xPoGWVCmcsOO2gaM2cywuTYTHkXRozo3/Nkg==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@esbuild/win32-x64/0.16.17:
resolution: {integrity: sha512-y+EHuSchhL7FjHgvQL/0fnnFmO4T1bhvWANX6gcnqTjtnKWbTvUMCpGnv2+t+31d7RzyEAYAd4u2fnIhHL6N/Q==}
engines: {node: '>=12'}
@@ -1294,6 +1474,15 @@ packages:
dev: false
optional: true
+ /@esbuild/win32-x64/0.17.4:
+ resolution: {integrity: sha512-0kLAjs+xN5OjhTt/aUA6t48SfENSCKgGPfExADYTOo/UCn0ivxos9/anUVeSfg+L+2O9xkFxvJXIJfG+Q4sYSg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: false
+ optional: true
+
/@eslint/eslintrc/1.4.1:
resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -1422,8 +1611,8 @@ packages:
- supports-color
dev: false
- /@fastify/static/6.6.1:
- resolution: {integrity: sha512-sylhlmhclqwkyZy/SD5wzd4yjmMuqW8cRmfnuPXPhftZuEwJ8G2apm0kECQRnHJnk+W3Ksx2fpIHHcthzxNRTA==}
+ /@fastify/static/6.7.0:
+ resolution: {integrity: sha512-GYFDTSK83OL3mlzEDhgZXwFqPpGPiOsOr+dx63y2hcDF+NF4j1Ps2Swvmq/tMc5CFGoEDhkVN+P9fWG+/4a30Q==}
dependencies:
'@fastify/accept-negotiator': 1.0.0
'@fastify/send': 1.0.0
@@ -1436,8 +1625,8 @@ packages:
- supports-color
dev: false
- /@fastify/view/7.4.0:
- resolution: {integrity: sha512-0AzLsS7+Vbn2ElN2w1MqbHacecv4FJxWuiDg9LrqeWeG8suUIV5qBnF1ZGbf023NQUchgR++g2hY7uAyk5PaWA==}
+ /@fastify/view/7.4.1:
+ resolution: {integrity: sha512-ahmRmSbNVM8bIoz0BAFnY0jNigom+xbPQ9Q1ZjmNOtGVVT3nYXCxw2OMkTr9iXwrJ4Le3EtWDHlFkZ2fCQ2hJA==}
dependencies:
fastify-plugin: 4.5.0
hashlru: 2.3.0
@@ -1496,20 +1685,20 @@ packages:
engines: {node: '>=8'}
dev: true
- /@jest/console/29.3.1:
- resolution: {integrity: sha512-IRE6GD47KwcqA09RIWrabKdHPiKDGgtAL31xDxbi/RjQMsr+lY+ppxmHwY0dUEV3qvvxZzoe5Hl0RXZJOjQNUg==}
+ /@jest/console/29.4.1:
+ resolution: {integrity: sha512-m+XpwKSi3PPM9znm5NGS8bBReeAJJpSkL1OuFCqaMaJL2YX9YXLkkI+MBchMPwu+ZuM2rynL51sgfkQteQ1CKQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.3.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
chalk: 4.1.2
- jest-message-util: 29.3.1
- jest-util: 29.3.1
+ jest-message-util: 29.4.1
+ jest-util: 29.4.1
slash: 3.0.0
dev: true
- /@jest/core/29.3.1:
- resolution: {integrity: sha512-0ohVjjRex985w5MmO5L3u5GR1O30DexhBSpuwx2P+9ftyqHdJXnk7IUWiP80oHMvt7ubHCJHxV0a0vlKVuZirw==}
+ /@jest/core/29.4.1:
+ resolution: {integrity: sha512-RXFTohpBqpaTebNdg5l3I5yadnKo9zLBajMT0I38D0tDhreVBYv3fA8kywthI00sWxPztWLD3yjiUkewwu/wKA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
@@ -1517,32 +1706,32 @@ packages:
node-notifier:
optional: true
dependencies:
- '@jest/console': 29.3.1
- '@jest/reporters': 29.3.1
- '@jest/test-result': 29.3.1
- '@jest/transform': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/console': 29.4.1
+ '@jest/reporters': 29.4.1
+ '@jest/test-result': 29.4.1
+ '@jest/transform': 29.4.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
ansi-escapes: 4.3.2
chalk: 4.1.2
ci-info: 3.7.1
exit: 0.1.2
graceful-fs: 4.2.10
- jest-changed-files: 29.2.0
- jest-config: 29.3.1_@types+node@18.11.18
- jest-haste-map: 29.3.1
- jest-message-util: 29.3.1
+ jest-changed-files: 29.4.0
+ jest-config: 29.4.1_@types+node@18.11.18
+ jest-haste-map: 29.4.1
+ jest-message-util: 29.4.1
jest-regex-util: 29.2.0
- jest-resolve: 29.3.1
- jest-resolve-dependencies: 29.3.1
- jest-runner: 29.3.1
- jest-runtime: 29.3.1
- jest-snapshot: 29.3.1
- jest-util: 29.3.1
- jest-validate: 29.3.1
- jest-watcher: 29.3.1
+ jest-resolve: 29.4.1
+ jest-resolve-dependencies: 29.4.1
+ jest-runner: 29.4.1
+ jest-runtime: 29.4.1
+ jest-snapshot: 29.4.1
+ jest-util: 29.4.1
+ jest-validate: 29.4.1
+ jest-watcher: 29.4.1
micromatch: 4.0.5
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
slash: 3.0.0
strip-ansi: 6.0.1
transitivePeerDependencies:
@@ -1557,14 +1746,14 @@ packages:
'@jest/types': 27.5.1
dev: true
- /@jest/environment/29.3.1:
- resolution: {integrity: sha512-pMmvfOPmoa1c1QpfFW0nXYtNLpofqo4BrCIk6f2kW4JFeNlHV2t3vd+3iDLf31e2ot2Mec0uqZfmI+U0K2CFag==}
+ /@jest/environment/29.4.1:
+ resolution: {integrity: sha512-pJ14dHGSQke7Q3mkL/UZR9ZtTOxqskZaC91NzamEH4dlKRt42W+maRBXiw/LWkdJe+P0f/zDR37+SPMplMRlPg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/fake-timers': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/fake-timers': 29.4.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
- jest-mock: 29.3.1
+ jest-mock: 29.4.1
dev: true
/@jest/expect-utils/29.3.1:
@@ -1574,42 +1763,49 @@ packages:
jest-get-type: 29.2.0
dev: true
- /@jest/expect/29.3.1:
- resolution: {integrity: sha512-QivM7GlSHSsIAWzgfyP8dgeExPRZ9BIe2LsdPyEhCGkZkoyA+kGsoIzbKAfZCvvRzfZioKwPtCZIt5SaoxYCvg==}
+ /@jest/expect-utils/29.4.1:
+ resolution: {integrity: sha512-w6YJMn5DlzmxjO00i9wu2YSozUYRBhIoJ6nQwpMYcBMtiqMGJm1QBzOf6DDgRao8dbtpDoaqLg6iiQTvv0UHhQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- expect: 29.3.1
- jest-snapshot: 29.3.1
+ jest-get-type: 29.2.0
+ dev: true
+
+ /@jest/expect/29.4.1:
+ resolution: {integrity: sha512-ZxKJP5DTUNF2XkpJeZIzvnzF1KkfrhEF6Rz0HGG69fHl6Bgx5/GoU3XyaeFYEjuuKSOOsbqD/k72wFvFxc3iTw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ expect: 29.4.1
+ jest-snapshot: 29.4.1
transitivePeerDependencies:
- supports-color
dev: true
- /@jest/fake-timers/29.3.1:
- resolution: {integrity: sha512-iHTL/XpnDlFki9Tq0Q1GGuVeQ8BHZGIYsvCO5eN/O/oJaRzofG9Xndd9HuSDBI/0ZS79pg0iwn07OMTQ7ngF2A==}
+ /@jest/fake-timers/29.4.1:
+ resolution: {integrity: sha512-/1joI6rfHFmmm39JxNfmNAO3Nwm6Y0VoL5fJDy7H1AtWrD1CgRtqJbN9Ld6rhAkGO76qqp4cwhhxJ9o9kYjQMw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.3.1
- '@sinonjs/fake-timers': 9.1.2
+ '@jest/types': 29.4.1
+ '@sinonjs/fake-timers': 10.0.2
'@types/node': 18.11.18
- jest-message-util: 29.3.1
- jest-mock: 29.3.1
- jest-util: 29.3.1
+ jest-message-util: 29.4.1
+ jest-mock: 29.4.1
+ jest-util: 29.4.1
dev: true
- /@jest/globals/29.3.1:
- resolution: {integrity: sha512-cTicd134vOcwO59OPaB6AmdHQMCtWOe+/DitpTZVxWgMJ+YvXL1HNAmPyiGbSHmF/mXVBkvlm8YYtQhyHPnV6Q==}
+ /@jest/globals/29.4.1:
+ resolution: {integrity: sha512-znoK2EuFytbHH0ZSf2mQK2K1xtIgmaw4Da21R2C/NE/+NnItm5mPEFQmn8gmF3f0rfOlmZ3Y3bIf7bFj7DHxAA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/environment': 29.3.1
- '@jest/expect': 29.3.1
- '@jest/types': 29.3.1
- jest-mock: 29.3.1
+ '@jest/environment': 29.4.1
+ '@jest/expect': 29.4.1
+ '@jest/types': 29.4.1
+ jest-mock: 29.4.1
transitivePeerDependencies:
- supports-color
dev: true
- /@jest/reporters/29.3.1:
- resolution: {integrity: sha512-GhBu3YFuDrcAYW/UESz1JphEAbvUjaY2vShRZRoRY1mxpCMB3yGSJ4j9n0GxVlEOdCf7qjvUfBCrTUUqhVfbRA==}
+ /@jest/reporters/29.4.1:
+ resolution: {integrity: sha512-AISY5xpt2Xpxj9R6y0RF1+O6GRy9JsGa8+vK23Lmzdy1AYcpQn5ItX79wJSsTmfzPKSAcsY1LNt/8Y5Xe5LOSg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0
@@ -1618,10 +1814,10 @@ packages:
optional: true
dependencies:
'@bcoe/v8-coverage': 0.2.3
- '@jest/console': 29.3.1
- '@jest/test-result': 29.3.1
- '@jest/transform': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/console': 29.4.1
+ '@jest/test-result': 29.4.1
+ '@jest/transform': 29.4.1
+ '@jest/types': 29.4.1
'@jridgewell/trace-mapping': 0.3.17
'@types/node': 18.11.18
chalk: 4.1.2
@@ -1634,9 +1830,9 @@ packages:
istanbul-lib-report: 3.0.0
istanbul-lib-source-maps: 4.0.1
istanbul-reports: 3.1.5
- jest-message-util: 29.3.1
- jest-util: 29.3.1
- jest-worker: 29.3.1
+ jest-message-util: 29.4.1
+ jest-util: 29.4.1
+ jest-worker: 29.4.1
slash: 3.0.0
string-length: 4.0.2
strip-ansi: 6.0.1
@@ -1652,6 +1848,13 @@ packages:
'@sinclair/typebox': 0.24.51
dev: true
+ /@jest/schemas/29.4.0:
+ resolution: {integrity: sha512-0E01f/gOZeNTG76i5eWWSupvSHaIINrTie7vCyjiYFKgzNdyEGd12BUv4oNBFHOqlHDbtoJi3HrQ38KCC90NsQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ '@sinclair/typebox': 0.25.21
+ dev: true
+
/@jest/source-map/29.2.0:
resolution: {integrity: sha512-1NX9/7zzI0nqa6+kgpSdKPK+WU1p+SJk3TloWZf5MzPbxri9UEeXX5bWZAPCzbQcyuAzubcdUHA7hcNznmRqWQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -1661,45 +1864,45 @@ packages:
graceful-fs: 4.2.10
dev: true
- /@jest/test-result/29.3.1:
- resolution: {integrity: sha512-qeLa6qc0ddB0kuOZyZIhfN5q0e2htngokyTWsGriedsDhItisW7SDYZ7ceOe57Ii03sL988/03wAcBh3TChMGw==}
+ /@jest/test-result/29.4.1:
+ resolution: {integrity: sha512-WRt29Lwt+hEgfN8QDrXqXGgCTidq1rLyFqmZ4lmJOpVArC8daXrZWkWjiaijQvgd3aOUj2fM8INclKHsQW9YyQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/console': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/console': 29.4.1
+ '@jest/types': 29.4.1
'@types/istanbul-lib-coverage': 2.0.4
collect-v8-coverage: 1.0.1
dev: true
- /@jest/test-sequencer/29.3.1:
- resolution: {integrity: sha512-IqYvLbieTv20ArgKoAMyhLHNrVHJfzO6ARZAbQRlY4UGWfdDnLlZEF0BvKOMd77uIiIjSZRwq3Jb3Fa3I8+2UA==}
+ /@jest/test-sequencer/29.4.1:
+ resolution: {integrity: sha512-v5qLBNSsM0eHzWLXsQ5fiB65xi49A3ILPSFQKPXzGL4Vyux0DPZAIN7NAFJa9b4BiTDP9MBF/Zqc/QA1vuiJ0w==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/test-result': 29.3.1
+ '@jest/test-result': 29.4.1
graceful-fs: 4.2.10
- jest-haste-map: 29.3.1
+ jest-haste-map: 29.4.1
slash: 3.0.0
dev: true
- /@jest/transform/29.3.1:
- resolution: {integrity: sha512-8wmCFBTVGYqFNLWfcOWoVuMuKYPUBTnTMDkdvFtAYELwDOl9RGwOsvQWGPFxDJ8AWY9xM/8xCXdqmPK3+Q5Lug==}
+ /@jest/transform/29.4.1:
+ resolution: {integrity: sha512-5w6YJrVAtiAgr0phzKjYd83UPbCXsBRTeYI4BXokv9Er9CcrH9hfXL/crCvP2d2nGOcovPUnlYiLPFLZrkG5Hg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/core': 7.20.12
- '@jest/types': 29.3.1
+ '@jest/types': 29.4.1
'@jridgewell/trace-mapping': 0.3.17
babel-plugin-istanbul: 6.1.1
chalk: 4.1.2
convert-source-map: 2.0.0
fast-json-stable-stringify: 2.1.0
graceful-fs: 4.2.10
- jest-haste-map: 29.3.1
+ jest-haste-map: 29.4.1
jest-regex-util: 29.2.0
- jest-util: 29.3.1
+ jest-util: 29.4.1
micromatch: 4.0.5
pirates: 4.0.5
slash: 3.0.0
- write-file-atomic: 4.0.2
+ write-file-atomic: 5.0.0
transitivePeerDependencies:
- supports-color
dev: true
@@ -1715,11 +1918,11 @@ packages:
chalk: 4.1.2
dev: true
- /@jest/types/29.3.1:
- resolution: {integrity: sha512-d0S0jmmTpjnhCmNpApgX3jrUZgZ22ivKJRvL2lli5hpCRoNnp1f85r2/wpKfXuYu8E7Jjh1hGfhPyup1NM5AmA==}
+ /@jest/types/29.4.1:
+ resolution: {integrity: sha512-zbrAXDUOnpJ+FMST2rV7QZOgec8rskg2zv8g2ajeqitp4tvZiyqTCYXANrKsM+ryj5o+LI+ZN2EgU9drrkiwSA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/schemas': 29.0.0
+ '@jest/schemas': 29.4.0
'@types/istanbul-lib-coverage': 2.0.4
'@types/istanbul-reports': 3.0.1
'@types/node': 18.11.18
@@ -2055,7 +2258,7 @@ packages:
- encoding
dev: true
- /@rollup/plugin-alias/4.0.3_rollup@3.10.1:
+ /@rollup/plugin-alias/4.0.3_rollup@3.11.0:
resolution: {integrity: sha512-ZuDWE1q4PQDhvm/zc5Prun8sBpLJy41DMptYrS6MhAy9s9kL/doN1613BWfEchGVfKxzliJ3BjbOPizXX38DbQ==}
engines: {node: '>=14.0.0'}
peerDependencies:
@@ -2064,11 +2267,11 @@ packages:
rollup:
optional: true
dependencies:
- rollup: 3.10.1
+ rollup: 3.11.0
slash: 4.0.0
dev: false
- /@rollup/plugin-json/6.0.0_rollup@3.10.1:
+ /@rollup/plugin-json/6.0.0_rollup@3.11.0:
resolution: {integrity: sha512-i/4C5Jrdr1XUarRhVu27EEwjt4GObltD7c+MkCIpO2QIbojw8MUs+CCTqOphQi3Qtg1FLmYt+l+6YeoIf51J7w==}
engines: {node: '>=14.0.0'}
peerDependencies:
@@ -2077,11 +2280,11 @@ packages:
rollup:
optional: true
dependencies:
- '@rollup/pluginutils': 5.0.2_rollup@3.10.1
- rollup: 3.10.1
+ '@rollup/pluginutils': 5.0.2_rollup@3.11.0
+ rollup: 3.11.0
dev: false
- /@rollup/pluginutils/5.0.2_rollup@3.10.1:
+ /@rollup/pluginutils/5.0.2_rollup@3.11.0:
resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==}
engines: {node: '>=14.0.0'}
peerDependencies:
@@ -2093,7 +2296,7 @@ packages:
'@types/estree': 1.0.0
estree-walker: 2.0.2
picomatch: 2.3.1
- rollup: 3.10.1
+ rollup: 3.11.0
dev: false
/@sideway/address/4.1.4:
@@ -2114,6 +2317,10 @@ packages:
resolution: {integrity: sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==}
dev: true
+ /@sinclair/typebox/0.25.21:
+ resolution: {integrity: sha512-gFukHN4t8K4+wVC+ECqeqwzBDeFeTzBXroBTqE6vcWrQGbEUpHO7LYdG0f4xnvYq4VOEwITSlHlp0JBAIFMS/g==}
+ dev: true
+
/@sindresorhus/is/0.7.0:
resolution: {integrity: sha512-ONhaKPIufzzrlNbqtWFFd+jlnemX6lJAgq9ZeiZtS7I1PIf/la7CW4m83rTXRnVnsMbW2k56pGYu7AUFJD9Pow==}
engines: {node: '>=4'}
@@ -2129,35 +2336,21 @@ packages:
engines: {node: '>=14.16'}
dev: false
- /@sinonjs/commons/1.8.6:
- resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==}
- dependencies:
- type-detect: 4.0.8
- dev: true
-
/@sinonjs/commons/2.0.0:
resolution: {integrity: sha512-uLa0j859mMrg2slwQYdO/AkrOfmH+X6LTVmNTS9CqexuE2IvVORIkSpJLqePAbEnKJ77aMmCwr1NUZ57120Xcg==}
dependencies:
type-detect: 4.0.8
- dev: false
/@sinonjs/fake-timers/10.0.2:
resolution: {integrity: sha512-SwUDyjWnah1AaNl7kxsa7cfLhlTYoiyhDAIgyh+El30YvXs/o7OLXpYH88Zdhyx9JExKrmHDJ+10bwIcY80Jmw==}
dependencies:
'@sinonjs/commons': 2.0.0
- dev: false
-
- /@sinonjs/fake-timers/9.1.2:
- resolution: {integrity: sha512-BPS4ynJW/o92PUR4wgriz2Ud5gpST5vz6GQfMixEDK0Z8ZCUv2M7SkBLykH56T++Xs+8ln9zTGbOvNGIe02/jw==}
- dependencies:
- '@sinonjs/commons': 1.8.6
- dev: true
/@sqltools/formatter/1.2.5:
resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==}
dev: false
- /@swc/cli/0.1.59_2w2rsb5d2wh3txrlxuiknf4vra:
+ /@swc/cli/0.1.59_dbbgdut2njxjatv5n3st5z6gqa:
resolution: {integrity: sha512-BlX3wIxYTwdtR22dIqZ3FEIOJPqnlByAp4JY46OMZi2UXMB3ZbOzefawD2ZlLafRUWyy5NtiZZty5waKzaYRnA==}
engines: {node: '>= 12.13'}
hasBin: true
@@ -2168,7 +2361,7 @@ packages:
chokidar:
optional: true
dependencies:
- '@swc/core': 1.3.27
+ '@swc/core': 1.3.29
bin-wrapper: 4.1.0
chokidar: 3.5.3
commander: 7.2.0
@@ -2178,8 +2371,8 @@ packages:
source-map: 0.7.4
dev: true
- /@swc/core-darwin-arm64/1.3.27:
- resolution: {integrity: sha512-IKlxkhEy99CnP9nduaf5IJWIFcr6D5cZCjYmCs7nWkjMV+aAieyDO9AX4LT8AcHy6CF7ByOX7SKoqk+gVMAaKw==}
+ /@swc/core-darwin-arm64/1.3.29:
+ resolution: {integrity: sha512-1RQ0MCmWOQmo3qG60vhbNaO/qMZ25lDfjhTayAzHjS1k7WyoUv3M8Em2Fip2VKJz5cN2M7MWiP5aHMotMovuaQ==}
engines: {node: '>=10'}
cpu: [arm64]
os: [darwin]
@@ -2187,8 +2380,8 @@ packages:
dev: true
optional: true
- /@swc/core-darwin-x64/1.3.27:
- resolution: {integrity: sha512-MtabZIhFf/dL3vs6UMbd+vJsjIkm2NaFqulGV0Jofy2bfVZPTj/b5pXeOlUsTWy7JcH1uixjdx4RvJRyvqJxQA==}
+ /@swc/core-darwin-x64/1.3.29:
+ resolution: {integrity: sha512-UXiVOkt9i/mwarhHiN6o5RAi3Q7riCQTiOO2e98c/qi3SiYqbgd6kil+2gBcpVB0CGEFyyGB9rECwNBkaYe7zw==}
engines: {node: '>=10'}
cpu: [x64]
os: [darwin]
@@ -2196,8 +2389,8 @@ packages:
dev: true
optional: true
- /@swc/core-linux-arm-gnueabihf/1.3.27:
- resolution: {integrity: sha512-XELMoGcUTAkk+G4buwIIhu6AIr1U418Odt22HUW8+ZvV+Wty2ICgR/myOIhM3xMb6U2L8ay+evMqoVNMQ0RRTg==}
+ /@swc/core-linux-arm-gnueabihf/1.3.29:
+ resolution: {integrity: sha512-0B7+FoYgEE1Yg6j5EAtEpKVbHby3jnJo6Y4g0dGxecRtXUhu8TKVI4P93sj4PJ+l4XkAyzdhSsQ+ytFRsbOJ6w==}
engines: {node: '>=10'}
cpu: [arm]
os: [linux]
@@ -2205,8 +2398,8 @@ packages:
dev: true
optional: true
- /@swc/core-linux-arm64-gnu/1.3.27:
- resolution: {integrity: sha512-O6vtT6bnrVR9PzEIuA5U7tIfYo7bv97H9K9Vqy2oyHNeGN0H36DKwS4UqPreHtziXNF5+7ubdUYUkrG/j8UnUQ==}
+ /@swc/core-linux-arm64-gnu/1.3.29:
+ resolution: {integrity: sha512-XN9axiTuiFOm+UBnDDOQV3b2OekziXHtVPBAPSEssRsNGS4uN7YvCyVAcS8GYdK7GoZ+cmoZBYwD4trir48WXw==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
@@ -2214,8 +2407,8 @@ packages:
dev: true
optional: true
- /@swc/core-linux-arm64-musl/1.3.27:
- resolution: {integrity: sha512-Oa0E1i7dOTWpaEZumKoNbTE/Ap+da6nlhqKVUdYrFDrOBi25tz76SdxZIyvAszzmgY89b5yd1naourKmkPXpww==}
+ /@swc/core-linux-arm64-musl/1.3.29:
+ resolution: {integrity: sha512-M6eE02Dzl1efRLozitGvgjiNEee0VQInqMX4tvfpzQwqZsKNAD8/NGPeTG4763BLDHc4hnMZbnt5wncDLjFq7A==}
engines: {node: '>=10'}
cpu: [arm64]
os: [linux]
@@ -2223,8 +2416,8 @@ packages:
dev: true
optional: true
- /@swc/core-linux-x64-gnu/1.3.27:
- resolution: {integrity: sha512-S3v9H8oL2a8Ur6AjQyhkC6HfBVPOxKMdBhcZmdNuVgEUHbHdbf/Lka85F9IOYXEarMn0FtQw3ywowS22O9L5Uw==}
+ /@swc/core-linux-x64-gnu/1.3.29:
+ resolution: {integrity: sha512-t2e9byHRpxKyUsLeODlb3yKJcm8wMirsLIxjr24q5YbnChD3QUMQwA8aA9w2PWc86ihukw7Ksx3RYT7uR706HA==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
@@ -2232,8 +2425,8 @@ packages:
dev: true
optional: true
- /@swc/core-linux-x64-musl/1.3.27:
- resolution: {integrity: sha512-6DDkdXlOADpwICFZTRphCR+cIeS8aEYh4NlyzBito0mOWwIIdfCgALzhkTQOzTOkcD42bP97CIoZ97hqV/puOg==}
+ /@swc/core-linux-x64-musl/1.3.29:
+ resolution: {integrity: sha512-3jDzDYIyHXrXKOSnTtsN56eINbTPuVQj65D3K8+zo1o52GGwNGyCvQt2RpxNfM8+ptb4j6v7weSU8kVvbUzGTQ==}
engines: {node: '>=10'}
cpu: [x64]
os: [linux]
@@ -2241,8 +2434,8 @@ packages:
dev: true
optional: true
- /@swc/core-win32-arm64-msvc/1.3.27:
- resolution: {integrity: sha512-baxfH4AbEcaTNo08wxV0W6hiMXwVCxPS4qc0amHpXPti92unvSqeDR1W3C9GjHqzXlWtmCRsq8Ww1pal6ZVLrw==}
+ /@swc/core-win32-arm64-msvc/1.3.29:
+ resolution: {integrity: sha512-3PadPieyslG++7SQ42OApfiXtQdzFpnCv/i/UJ6gOL5d0MluNzZ2nIxD8LwXXizVdmcm8bmc0WRhK3JhvhzVJA==}
engines: {node: '>=10'}
cpu: [arm64]
os: [win32]
@@ -2250,8 +2443,8 @@ packages:
dev: true
optional: true
- /@swc/core-win32-ia32-msvc/1.3.27:
- resolution: {integrity: sha512-7iLJnH71k5qCwxv9NcM/P7nIEzTsC7r1sIiQW6bu+CpC8qZvwl0PS+XvQRlLly2gCZM+Le98tksYG14MEh+Hrw==}
+ /@swc/core-win32-ia32-msvc/1.3.29:
+ resolution: {integrity: sha512-tUFrHxxYz9Cfz07yGwDXdtRziC3q1ia2SHodzZ3obTpY+HQiBDHs0QO/HkbUBNF+du0vhnsgtWilnsMQDILFDQ==}
engines: {node: '>=10'}
cpu: [ia32]
os: [win32]
@@ -2259,8 +2452,8 @@ packages:
dev: true
optional: true
- /@swc/core-win32-x64-msvc/1.3.27:
- resolution: {integrity: sha512-mFM907PDw/jrQ44+TRjIVGEOy2Mu06mMMz0HPMFuRsBzl5t0Kajp3vmn8FkkpS9wH5982VPi6hPYVTb7QJo5Qg==}
+ /@swc/core-win32-x64-msvc/1.3.29:
+ resolution: {integrity: sha512-/Z3kxMXGKlIhtkxBxsCSZl8j/qYfbA4dtW7RKv1RNxbPLbwk8k3Owhgk/Y3JeRavcUKwja1rUX5rhMjLYeN3tw==}
engines: {node: '>=10'}
cpu: [x64]
os: [win32]
@@ -2268,31 +2461,31 @@ packages:
dev: true
optional: true
- /@swc/core/1.3.27:
- resolution: {integrity: sha512-praRNgpeYGvwDIm/Cl6JU+yHMvwVraL0U6ejMgGyzvpcm1FVsZd1/EYXGqzbBJ0ALv7Gx4eK56h4GnwV6d4L0w==}
+ /@swc/core/1.3.29:
+ resolution: {integrity: sha512-BYDBEqQ77ASZNQYTP7PlKnMLwbHh3lhtlzD/gQP2zIK9XhqQlcy/zIcLljYDn0EOogLn3IyaUiXgAzDWoAmWMg==}
engines: {node: '>=10'}
requiresBuild: true
optionalDependencies:
- '@swc/core-darwin-arm64': 1.3.27
- '@swc/core-darwin-x64': 1.3.27
- '@swc/core-linux-arm-gnueabihf': 1.3.27
- '@swc/core-linux-arm64-gnu': 1.3.27
- '@swc/core-linux-arm64-musl': 1.3.27
- '@swc/core-linux-x64-gnu': 1.3.27
- '@swc/core-linux-x64-musl': 1.3.27
- '@swc/core-win32-arm64-msvc': 1.3.27
- '@swc/core-win32-ia32-msvc': 1.3.27
- '@swc/core-win32-x64-msvc': 1.3.27
+ '@swc/core-darwin-arm64': 1.3.29
+ '@swc/core-darwin-x64': 1.3.29
+ '@swc/core-linux-arm-gnueabihf': 1.3.29
+ '@swc/core-linux-arm64-gnu': 1.3.29
+ '@swc/core-linux-arm64-musl': 1.3.29
+ '@swc/core-linux-x64-gnu': 1.3.29
+ '@swc/core-linux-x64-musl': 1.3.29
+ '@swc/core-win32-arm64-msvc': 1.3.29
+ '@swc/core-win32-ia32-msvc': 1.3.29
+ '@swc/core-win32-x64-msvc': 1.3.29
dev: true
- /@swc/jest/0.2.24_@swc+core@1.3.27:
+ /@swc/jest/0.2.24_@swc+core@1.3.29:
resolution: {integrity: sha512-fwgxQbM1wXzyKzl1+IW0aGrRvAA8k0Y3NxFhKigbPjOJ4mCKnWEcNX9HQS3gshflcxq8YKhadabGUVfdwjCr6Q==}
engines: {npm: '>= 7.0.0'}
peerDependencies:
'@swc/core': '*'
dependencies:
'@jest/create-cache-key-function': 27.5.1
- '@swc/core': 1.3.27
+ '@swc/core': 1.3.29
jsonc-parser: 3.2.0
dev: true
@@ -2319,14 +2512,14 @@ packages:
defer-to-connect: 2.0.1
dev: false
- /@tabler/icons-webfont/2.0.0:
- resolution: {integrity: sha512-ApVVupe7WKZOJzK6T2iw15/k6VrTALsL5YzAmvgvcriuX8sRCKlcWaRljcf2sZMUrqyY+Yq6xiOpL2p2NHgQBQ==}
+ /@tabler/icons-webfont/2.1.2:
+ resolution: {integrity: sha512-UoLIUeaZSDH4ORAbxvt/jO3RZ4AjaNV/qw7LXMWmEfsDUY3teaB4xrwW1WkyMqMU1HjkX5dR1z7P8Ajxxucjyw==}
dependencies:
- '@tabler/icons': 2.0.0
+ '@tabler/icons': 2.1.2
dev: false
- /@tabler/icons/2.0.0:
- resolution: {integrity: sha512-ye93cVD8baCwJJ7J3GKlUM3FN+qW6lsEz4uaH8bHCwC8un2R4p+ZzyRNc/ksqVgMQJ4PKQ8xbYpv4dnbbRffsA==}
+ /@tabler/icons/2.1.2:
+ resolution: {integrity: sha512-+CPB+BSqVDP4+/d+cHSaGwG460C3sob7EJkQ+ZS8xV6bRER64OsCP92O7M+uYBhJFDWuf6poCeSETNZNcFa2nA==}
dev: false
/@tensorflow/tfjs-backend-cpu/4.2.0_tkoh6rxfpzme3tc2ndqbqcrg7y:
@@ -2624,8 +2817,8 @@ packages:
'@types/istanbul-lib-report': 3.0.0
dev: true
- /@types/jest/29.2.6:
- resolution: {integrity: sha512-XEUC/Tgw3uMh6Ho8GkUtQ2lPhY5Fmgyp3TdlkTJs1W9VgNxs+Ow/x3Elh8lHQKqCbZL0AubQuqWjHVT033Hhrw==}
+ /@types/jest/29.4.0:
+ resolution: {integrity: sha512-VaywcGQ9tPorCX/Jkkni7RWGFfI11whqzs8dvxF41P17Z+z872thvEvlIbznjPJ02kl1HMX3LmLOonsj2n7HeQ==}
dependencies:
expect: 29.3.1
pretty-format: 29.3.1
@@ -2655,8 +2848,8 @@ packages:
resolution: {integrity: sha512-4l5t/jDnJpqZ+i7CLTTgPcT5BYXnAnwJupb07aAokPufCV0SjDHcwctUkSTuhIuSU9yHok+WOOngIGCtpL96gw==}
dev: true
- /@types/jsrsasign/10.5.4:
- resolution: {integrity: sha512-05S2f4lGaWgCwFHsa3OEirc4VJf/sJRfhofzxUbuFbmm6NbffPXZrnJqquQAtS3g4C8Z0L9NHgW0znmtDxNoTQ==}
+ /@types/jsrsasign/10.5.5:
+ resolution: {integrity: sha512-M2Et4hgTigFoArTu6ylK3hYFEH+UuXfgFXRXZ+flpCfux8j7fQ2D+0zEwiu6ehx0h5otaauhLSFzMzEtNA784A==}
dev: true
/@types/keyv/3.1.4:
@@ -2793,8 +2986,8 @@ packages:
resolution: {integrity: sha512-21cFJr9z3g5dW8B0CVI9g2O9beqaThGQ6ZFBqHfwhzLDKUxaqTIy3vnfah/UPkfOiF2pLq+tGz+W8RyCskuslw==}
dev: true
- /@types/serviceworker/0.0.58:
- resolution: {integrity: sha512-bFRpZYjYbEgfPYBVR9Vfn/95ao7PvXCjQy6Eh1rbPnZBbTPpQlurLAciLF8qWN54F0WoVwE5xcaJPeDRdLGivg==}
+ /@types/serviceworker/0.0.61:
+ resolution: {integrity: sha512-j/FCintE+6dLM4Wyej1OMTPJy8rBHOmZ9O4XgEy9OQ4B7SfAHwWEZQQk/PXuBl/tFyE+r87eOm+x+wQiiiHIag==}
dev: true
/@types/sharp/0.31.1:
@@ -2960,26 +3153,6 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/parser/5.48.1_iukboom6ndih5an6iafl45j2fe:
- resolution: {integrity: sha512-4yg+FJR/V1M9Xoq56SF9Iygqm+r5LMXvheo6DQ7/yUWynQ4YfCRnsKuRgqH4EQ5Ya76rVwlEpw4Xu+TgWQUcdA==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
- dependencies:
- '@typescript-eslint/scope-manager': 5.48.1
- '@typescript-eslint/types': 5.48.1
- '@typescript-eslint/typescript-estree': 5.48.1_typescript@4.9.4
- debug: 4.3.4
- eslint: 8.31.0
- typescript: 4.9.4
- transitivePeerDependencies:
- - supports-color
- dev: true
-
/@typescript-eslint/parser/5.49.0_7uibuqfxkfaozanbtbziikiqje:
resolution: {integrity: sha512-veDlZN9mUhGqU31Qiv2qEp+XrJj5fgZpJ8PW30sHU+j/8/e5ruAhLaVDAeznS7A7i4ucb/s8IozpDtt9NqCkZg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3000,14 +3173,6 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/scope-manager/5.48.1:
- resolution: {integrity: sha512-S035ueRrbxRMKvSTv9vJKIWgr86BD8s3RqoRZmsSh/s8HhIs90g6UlK8ZabUSjUZQkhVxt7nmZ63VJ9dcZhtDQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dependencies:
- '@typescript-eslint/types': 5.48.1
- '@typescript-eslint/visitor-keys': 5.48.1
- dev: true
-
/@typescript-eslint/scope-manager/5.49.0:
resolution: {integrity: sha512-clpROBOiMIzpbWNxCe1xDK14uPZh35u4QaZO1GddilEzoCLAEz4szb51rBpdgurs5k2YzPtJeTEN3qVbG+LRUQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3036,37 +3201,11 @@ packages:
- supports-color
dev: true
- /@typescript-eslint/types/5.48.1:
- resolution: {integrity: sha512-xHyDLU6MSuEEdIlzrrAerCGS3T7AA/L8Hggd0RCYBi0w3JMvGYxlLlXHeg50JI9Tfg5MrtsfuNxbS/3zF1/ATg==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dev: true
-
/@typescript-eslint/types/5.49.0:
resolution: {integrity: sha512-7If46kusG+sSnEpu0yOz2xFv5nRz158nzEXnJFCGVEHWnuzolXKwrH5Bsf9zsNlOQkyZuk0BZKKoJQI+1JPBBg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
- /@typescript-eslint/typescript-estree/5.48.1_typescript@4.9.4:
- resolution: {integrity: sha512-Hut+Osk5FYr+sgFh8J/FHjqX6HFcDzTlWLrFqGoK5kVUN3VBHF/QzZmAsIXCQ8T/W9nQNBTqalxi1P3LSqWnRA==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- peerDependencies:
- typescript: '*'
- peerDependenciesMeta:
- typescript:
- optional: true
- dependencies:
- '@typescript-eslint/types': 5.48.1
- '@typescript-eslint/visitor-keys': 5.48.1
- debug: 4.3.4
- globby: 11.1.0
- is-glob: 4.0.3
- semver: 7.3.8
- tsutils: 3.21.0_typescript@4.9.4
- typescript: 4.9.4
- transitivePeerDependencies:
- - supports-color
- dev: true
-
/@typescript-eslint/typescript-estree/5.49.0_typescript@4.9.4:
resolution: {integrity: sha512-PBdx+V7deZT/3GjNYPVQv1Nc0U46dAHbIuOG8AZ3on3vuEKiPDwFE/lG1snN2eUB9IhF7EyF7K1hmTcLztNIsA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3108,14 +3247,6 @@ packages:
- typescript
dev: true
- /@typescript-eslint/visitor-keys/5.48.1:
- resolution: {integrity: sha512-Ns0XBwmfuX7ZknznfXozgnydyR8F6ev/KEGePP4i74uL3ArsKbEhJ7raeKr1JSa997DBDwol/4a0Y+At82c9dA==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- dependencies:
- '@typescript-eslint/types': 5.48.1
- eslint-visitor-keys: 3.3.0
- dev: true
-
/@typescript-eslint/visitor-keys/5.49.0:
resolution: {integrity: sha512-v9jBMjpNWyn8B6k/Mjt6VbUS4J1GvUlR4x3Y+ibnP1z7y7V4n0WRz+50DY6+Myj0UaXVSuUlHohO+eZ8IJEnkg==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -3813,17 +3944,17 @@ packages:
- debug
dev: true
- /babel-jest/29.3.1_@babel+core@7.20.12:
- resolution: {integrity: sha512-aard+xnMoxgjwV70t0L6wkW/3HQQtV+O0PEimxKgzNqCJnbYmroPojdP2tqKSOAt8QAKV/uSZU8851M7B5+fcA==}
+ /babel-jest/29.4.1_@babel+core@7.20.12:
+ resolution: {integrity: sha512-xBZa/pLSsF/1sNpkgsiT3CmY7zV1kAsZ9OxxtrFqYucnOuRftXAfcJqcDVyOPeN4lttWTwhLdu0T9f8uvoPEUg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
'@babel/core': ^7.8.0
dependencies:
'@babel/core': 7.20.12
- '@jest/transform': 29.3.1
+ '@jest/transform': 29.4.1
'@types/babel__core': 7.1.20
babel-plugin-istanbul: 6.1.1
- babel-preset-jest: 29.2.0_@babel+core@7.20.12
+ babel-preset-jest: 29.4.0_@babel+core@7.20.12
chalk: 4.1.2
graceful-fs: 4.2.10
slash: 3.0.0
@@ -3844,8 +3975,8 @@ packages:
- supports-color
dev: true
- /babel-plugin-jest-hoist/29.2.0:
- resolution: {integrity: sha512-TnspP2WNiR3GLfCsUNHqeXw0RoQ2f9U5hQ5L3XFpwuO8htQmSrhh8qsB6vi5Yi8+kuynN1yjDjQsPfkebmB6ZA==}
+ /babel-plugin-jest-hoist/29.4.0:
+ resolution: {integrity: sha512-a/sZRLQJEmsmejQ2rPEUe35nO1+C9dc9O1gplH1SXmJxveQSRUYdBk8yGZG/VOUuZs1u2aHZJusEGoRMbhhwCg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/template': 7.20.7
@@ -3874,14 +4005,14 @@ packages:
'@babel/plugin-syntax-top-level-await': 7.14.5_@babel+core@7.20.12
dev: true
- /babel-preset-jest/29.2.0_@babel+core@7.20.12:
- resolution: {integrity: sha512-z9JmMJppMxNv8N7fNRHvhMg9cvIkMxQBXgFkane3yKVEvEOP+kB50lk8DFRvF9PGqbyXxlmebKWhuDORO8RgdA==}
+ /babel-preset-jest/29.4.0_@babel+core@7.20.12:
+ resolution: {integrity: sha512-fUB9vZflUSM3dO/6M2TCAepTzvA4VkOvl67PjErcrQMGt9Eve7uazaeyCZ2th3UtI7ljpiBJES0F7A1vBRsLZA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
'@babel/core': ^7.0.0
dependencies:
'@babel/core': 7.20.12
- babel-plugin-jest-hoist: 29.2.0
+ babel-plugin-jest-hoist: 29.4.0
babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.12
dev: true
@@ -5078,8 +5209,8 @@ packages:
uniq: 1.0.1
dev: false
- /cypress/12.3.0:
- resolution: {integrity: sha512-ZQNebibi6NBt51TRxRMYKeFvIiQZ01t50HSy7z/JMgRVqBUey3cdjog5MYEbzG6Ktti5ckDt1tfcC47lmFwXkw==}
+ /cypress/12.4.0:
+ resolution: {integrity: sha512-//h93K/yGC/7pxv1KamlkADbKHLp5h3f9rZDE2McRjXZDagMETH0sXowOOanvhsH8cFt/JWspIcK+p9cuaoAqg==}
engines: {node: ^14.0.0 || ^16.0.0 || >=18.0.0}
hasBin: true
requiresBuild: true
@@ -5783,215 +5914,6 @@ packages:
es6-symbol: 3.1.3
dev: false
- /esbuild-android-64/0.14.54:
- resolution: {integrity: sha512-Tz2++Aqqz0rJ7kYBfz+iqyE3QMycD4vk7LBRyWaAVFgFtQ/O8EJOnVmTOiDWYZ/uYzB4kvP+bqejYdVKzE5lAQ==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [android]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-android-arm64/0.14.54:
- resolution: {integrity: sha512-F9E+/QDi9sSkLaClO8SOV6etqPd+5DgJje1F9lOWoNncDdOBL2YF59IhsWATSt0TLZbYCf3pNlTHvVV5VfHdvg==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [android]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-darwin-64/0.14.54:
- resolution: {integrity: sha512-jtdKWV3nBviOd5v4hOpkVmpxsBy90CGzebpbO9beiqUYVMBtSc0AL9zGftFuBon7PNDcdvNCEuQqw2x0wP9yug==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [darwin]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-darwin-arm64/0.14.54:
- resolution: {integrity: sha512-OPafJHD2oUPyvJMrsCvDGkRrVCar5aVyHfWGQzY1dWnzErjrDuSETxwA2HSsyg2jORLY8yBfzc1MIpUkXlctmw==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [darwin]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-freebsd-64/0.14.54:
- resolution: {integrity: sha512-OKwd4gmwHqOTp4mOGZKe/XUlbDJ4Q9TjX0hMPIDBUWWu/kwhBAudJdBoxnjNf9ocIB6GN6CPowYpR/hRCbSYAg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [freebsd]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-freebsd-arm64/0.14.54:
- resolution: {integrity: sha512-sFwueGr7OvIFiQT6WeG0jRLjkjdqWWSrfbVwZp8iMP+8UHEHRBvlaxL6IuKNDwAozNUmbb8nIMXa7oAOARGs1Q==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [freebsd]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-linux-32/0.14.54:
- resolution: {integrity: sha512-1ZuY+JDI//WmklKlBgJnglpUL1owm2OX+8E1syCD6UAxcMM/XoWd76OHSjl/0MR0LisSAXDqgjT3uJqT67O3qw==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [linux]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-linux-64/0.14.54:
- resolution: {integrity: sha512-EgjAgH5HwTbtNsTqQOXWApBaPVdDn7XcK+/PtJwZLT1UmpLoznPd8c5CxqsH2dQK3j05YsB3L17T8vE7cp4cCg==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [linux]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-linux-arm/0.14.54:
- resolution: {integrity: sha512-qqz/SjemQhVMTnvcLGoLOdFpCYbz4v4fUo+TfsWG+1aOu70/80RV6bgNpR2JCrppV2moUQkww+6bWxXRL9YMGw==}
- engines: {node: '>=12'}
- cpu: [arm]
- os: [linux]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-linux-arm64/0.14.54:
- resolution: {integrity: sha512-WL71L+0Rwv+Gv/HTmxTEmpv0UgmxYa5ftZILVi2QmZBgX3q7+tDeOQNqGtdXSdsL8TQi1vIaVFHUPDe0O0kdig==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [linux]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-linux-mips64le/0.14.54:
- resolution: {integrity: sha512-qTHGQB8D1etd0u1+sB6p0ikLKRVuCWhYQhAHRPkO+OF3I/iSlTKNNS0Lh2Oc0g0UFGguaFZZiPJdJey3AGpAlw==}
- engines: {node: '>=12'}
- cpu: [mips64el]
- os: [linux]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-linux-ppc64le/0.14.54:
- resolution: {integrity: sha512-j3OMlzHiqwZBDPRCDFKcx595XVfOfOnv68Ax3U4UKZ3MTYQB5Yz3X1mn5GnodEVYzhtZgxEBidLWeIs8FDSfrQ==}
- engines: {node: '>=12'}
- cpu: [ppc64]
- os: [linux]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-linux-riscv64/0.14.54:
- resolution: {integrity: sha512-y7Vt7Wl9dkOGZjxQZnDAqqn+XOqFD7IMWiewY5SPlNlzMX39ocPQlOaoxvT4FllA5viyV26/QzHtvTjVNOxHZg==}
- engines: {node: '>=12'}
- cpu: [riscv64]
- os: [linux]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-linux-s390x/0.14.54:
- resolution: {integrity: sha512-zaHpW9dziAsi7lRcyV4r8dhfG1qBidQWUXweUjnw+lliChJqQr+6XD71K41oEIC3Mx1KStovEmlzm+MkGZHnHA==}
- engines: {node: '>=12'}
- cpu: [s390x]
- os: [linux]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-netbsd-64/0.14.54:
- resolution: {integrity: sha512-PR01lmIMnfJTgeU9VJTDY9ZerDWVFIUzAtJuDHwwceppW7cQWjBBqP48NdeRtoP04/AtO9a7w3viI+PIDr6d+w==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [netbsd]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-openbsd-64/0.14.54:
- resolution: {integrity: sha512-Qyk7ikT2o7Wu76UsvvDS5q0amJvmRzDyVlL0qf5VLsLchjCa1+IAvd8kTBgUxD7VBUUVgItLkk609ZHUc1oCaw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [openbsd]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-sunos-64/0.14.54:
- resolution: {integrity: sha512-28GZ24KmMSeKi5ueWzMcco6EBHStL3B6ubM7M51RmPwXQGLe0teBGJocmWhgwccA1GeFXqxzILIxXpHbl9Q/Kw==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [sunos]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-windows-32/0.14.54:
- resolution: {integrity: sha512-T+rdZW19ql9MjS7pixmZYVObd9G7kcaZo+sETqNH4RCkuuYSuv9AGHUVnPoP9hhuE1WM1ZimHz1CIBHBboLU7w==}
- engines: {node: '>=12'}
- cpu: [ia32]
- os: [win32]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-windows-64/0.14.54:
- resolution: {integrity: sha512-AoHTRBUuYwXtZhjXZbA1pGfTo8cJo3vZIcWGLiUcTNgHpJJMC1rVA44ZereBHMJtotyN71S8Qw0npiCIkW96cQ==}
- engines: {node: '>=12'}
- cpu: [x64]
- os: [win32]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild-windows-arm64/0.14.54:
- resolution: {integrity: sha512-M0kuUvXhot1zOISQGXwWn6YtS+Y/1RT9WrVIOywZnJHo3jCDyewAc79aKNQWFCQm+xNHVTq9h8dZKvygoXQQRg==}
- engines: {node: '>=12'}
- cpu: [arm64]
- os: [win32]
- requiresBuild: true
- dev: false
- optional: true
-
- /esbuild/0.14.54:
- resolution: {integrity: sha512-Cy9llcy8DvET5uznocPyqL3BFRrFXSVqbgpMJ9Wz8oVjZlh/zUSNbPRbov0VX7VxN2JH1Oa0uNxZ7eLRb62pJA==}
- engines: {node: '>=12'}
- hasBin: true
- requiresBuild: true
- optionalDependencies:
- '@esbuild/linux-loong64': 0.14.54
- esbuild-android-64: 0.14.54
- esbuild-android-arm64: 0.14.54
- esbuild-darwin-64: 0.14.54
- esbuild-darwin-arm64: 0.14.54
- esbuild-freebsd-64: 0.14.54
- esbuild-freebsd-arm64: 0.14.54
- esbuild-linux-32: 0.14.54
- esbuild-linux-64: 0.14.54
- esbuild-linux-arm: 0.14.54
- esbuild-linux-arm64: 0.14.54
- esbuild-linux-mips64le: 0.14.54
- esbuild-linux-ppc64le: 0.14.54
- esbuild-linux-riscv64: 0.14.54
- esbuild-linux-s390x: 0.14.54
- esbuild-netbsd-64: 0.14.54
- esbuild-openbsd-64: 0.14.54
- esbuild-sunos-64: 0.14.54
- esbuild-windows-32: 0.14.54
- esbuild-windows-64: 0.14.54
- esbuild-windows-arm64: 0.14.54
- dev: false
-
/esbuild/0.16.17:
resolution: {integrity: sha512-G8LEkV0XzDMNwXKgM0Jwu3nY3lSTwSGY6XbxM9cr9+s0T/qSV1q1JVPBGzm3dcjhCic9+emZDmMffkwgPeOeLg==}
engines: {node: '>=12'}
@@ -6022,6 +5944,36 @@ packages:
'@esbuild/win32-x64': 0.16.17
dev: false
+ /esbuild/0.17.4:
+ resolution: {integrity: sha512-zBn9MeCwT7W5F1a3lXClD61ip6vQM+H8Msb0w8zMT4ZKBpDg+rFAraNyWCDelB/2L6M3g6AXHPnsyvjMFnxtFw==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/android-arm': 0.17.4
+ '@esbuild/android-arm64': 0.17.4
+ '@esbuild/android-x64': 0.17.4
+ '@esbuild/darwin-arm64': 0.17.4
+ '@esbuild/darwin-x64': 0.17.4
+ '@esbuild/freebsd-arm64': 0.17.4
+ '@esbuild/freebsd-x64': 0.17.4
+ '@esbuild/linux-arm': 0.17.4
+ '@esbuild/linux-arm64': 0.17.4
+ '@esbuild/linux-ia32': 0.17.4
+ '@esbuild/linux-loong64': 0.17.4
+ '@esbuild/linux-mips64el': 0.17.4
+ '@esbuild/linux-ppc64': 0.17.4
+ '@esbuild/linux-riscv64': 0.17.4
+ '@esbuild/linux-s390x': 0.17.4
+ '@esbuild/linux-x64': 0.17.4
+ '@esbuild/netbsd-x64': 0.17.4
+ '@esbuild/openbsd-x64': 0.17.4
+ '@esbuild/sunos-x64': 0.17.4
+ '@esbuild/win32-arm64': 0.17.4
+ '@esbuild/win32-ia32': 0.17.4
+ '@esbuild/win32-x64': 0.17.4
+ dev: false
+
/escalade/3.1.1:
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
engines: {node: '>=6'}
@@ -6099,68 +6051,6 @@ packages:
- supports-color
dev: true
- /eslint-module-utils/2.7.4_sqt5xxn4ciiurbqrzlaarm6ama:
- resolution: {integrity: sha512-j4GT+rqzCoRKHwURX7pddtIPGySnX9Si/cgMI5ztrcqOPtk5dDEeZ34CQVPphnqkJytlc97Vuk05Um2mJ3gEQA==}
- engines: {node: '>=4'}
- peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: '*'
- eslint-import-resolver-node: '*'
- eslint-import-resolver-typescript: '*'
- eslint-import-resolver-webpack: '*'
- peerDependenciesMeta:
- '@typescript-eslint/parser':
- optional: true
- eslint:
- optional: true
- eslint-import-resolver-node:
- optional: true
- eslint-import-resolver-typescript:
- optional: true
- eslint-import-resolver-webpack:
- optional: true
- dependencies:
- '@typescript-eslint/parser': 5.48.1_iukboom6ndih5an6iafl45j2fe
- debug: 3.2.7
- eslint: 8.31.0
- eslint-import-resolver-node: 0.3.7
- transitivePeerDependencies:
- - supports-color
- dev: true
-
- /eslint-plugin-import/2.27.4_qdjeohovcytra7xto5vgmxssaq:
- resolution: {integrity: sha512-Z1jVt1EGKia1X9CnBCkpAOhWy8FgQ7OmJ/IblEkT82yrFU/xJaxwujaTzLWqigewwynRQ9mmHfX9MtAfhxm0sA==}
- engines: {node: '>=4'}
- peerDependencies:
- '@typescript-eslint/parser': '*'
- eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8
- peerDependenciesMeta:
- '@typescript-eslint/parser':
- optional: true
- dependencies:
- '@typescript-eslint/parser': 5.48.1_iukboom6ndih5an6iafl45j2fe
- array-includes: 3.1.6
- array.prototype.flat: 1.3.1
- array.prototype.flatmap: 1.3.1
- debug: 3.2.7
- doctrine: 2.1.0
- eslint: 8.31.0
- eslint-import-resolver-node: 0.3.7
- eslint-module-utils: 2.7.4_sqt5xxn4ciiurbqrzlaarm6ama
- has: 1.0.3
- is-core-module: 2.11.0
- is-glob: 4.0.3
- minimatch: 3.1.2
- object.values: 1.1.6
- resolve: 1.22.1
- semver: 6.3.0
- tsconfig-paths: 3.14.1
- transitivePeerDependencies:
- - eslint-import-resolver-typescript
- - eslint-import-resolver-webpack
- - supports-color
- dev: true
-
/eslint-plugin-import/2.27.5_6savw6y3b7jng6f64kgkyoij64:
resolution: {integrity: sha512-LmEt3GVofgiGuiE+ORpnvP+kAm3h6MLZJ4Q5HCyHADofsb4VzXFsRiWj3c0OFiV+3DWFh0qg3v9gcPlfc3zRow==}
engines: {node: '>=4'}
@@ -6228,16 +6118,6 @@ packages:
estraverse: 5.3.0
dev: true
- /eslint-utils/3.0.0_eslint@8.31.0:
- resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
- engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
- peerDependencies:
- eslint: '>=5'
- dependencies:
- eslint: 8.31.0
- eslint-visitor-keys: 2.1.0
- dev: true
-
/eslint-utils/3.0.0_eslint@8.32.0:
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
@@ -6258,54 +6138,6 @@ packages:
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
dev: true
- /eslint/8.31.0:
- resolution: {integrity: sha512-0tQQEVdmPZ1UtUKXjX7EMm9BlgJ08G90IhWh0PKDCb3ZLsgAOHI8fYSIzYVZej92zsgq+ft0FGsxhJ3xo2tbuA==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- hasBin: true
- dependencies:
- '@eslint/eslintrc': 1.4.1
- '@humanwhocodes/config-array': 0.11.8
- '@humanwhocodes/module-importer': 1.0.1
- '@nodelib/fs.walk': 1.2.8
- ajv: 6.12.6
- chalk: 4.1.2
- cross-spawn: 7.0.3
- debug: 4.3.4
- doctrine: 3.0.0
- escape-string-regexp: 4.0.0
- eslint-scope: 7.1.1
- eslint-utils: 3.0.0_eslint@8.31.0
- eslint-visitor-keys: 3.3.0
- espree: 9.4.1
- esquery: 1.4.0
- esutils: 2.0.3
- fast-deep-equal: 3.1.3
- file-entry-cache: 6.0.1
- find-up: 5.0.0
- glob-parent: 6.0.2
- globals: 13.19.0
- grapheme-splitter: 1.0.4
- ignore: 5.2.4
- import-fresh: 3.3.0
- imurmurhash: 0.1.4
- is-glob: 4.0.3
- is-path-inside: 3.0.3
- js-sdsl: 4.2.0
- js-yaml: 4.1.0
- json-stable-stringify-without-jsonify: 1.0.1
- levn: 0.4.1
- lodash.merge: 4.6.2
- minimatch: 3.1.2
- natural-compare: 1.4.0
- optionator: 0.9.1
- regexpp: 3.2.0
- strip-ansi: 6.0.1
- strip-json-comments: 3.1.1
- text-table: 0.2.0
- transitivePeerDependencies:
- - supports-color
- dev: true
-
/eslint/8.32.0:
resolution: {integrity: sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
@@ -6565,7 +6397,18 @@ packages:
jest-get-type: 29.2.0
jest-matcher-utils: 29.3.1
jest-message-util: 29.3.1
- jest-util: 29.3.1
+ jest-util: 29.4.1
+ dev: true
+
+ /expect/29.4.1:
+ resolution: {integrity: sha512-OKrGESHOaMxK3b6zxIq9SOW8kEXztKff/Dvg88j4xIJxur1hspEbedVkR3GpHe5LO+WB2Qw7OWN0RMTdp6as5A==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ '@jest/expect-utils': 29.4.1
+ jest-get-type: 29.2.0
+ jest-matcher-utils: 29.4.1
+ jest-message-util: 29.4.1
+ jest-util: 29.4.1
dev: true
/ext-list/2.2.2:
@@ -8598,43 +8441,43 @@ packages:
minimatch: 3.1.2
dev: false
- /jest-changed-files/29.2.0:
- resolution: {integrity: sha512-qPVmLLyBmvF5HJrY7krDisx6Voi8DmlV3GZYX0aFNbaQsZeoz1hfxcCMbqDGuQCxU1dJy9eYc2xscE8QrCCYaA==}
+ /jest-changed-files/29.4.0:
+ resolution: {integrity: sha512-rnI1oPxgFghoz32Y8eZsGJMjW54UlqT17ycQeCEktcxxwqqKdlj9afl8LNeO0Pbu+h2JQHThQP0BzS67eTRx4w==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
execa: 5.1.1
p-limit: 3.1.0
dev: true
- /jest-circus/29.3.1:
- resolution: {integrity: sha512-wpr26sEvwb3qQQbdlmei+gzp6yoSSoSL6GsLPxnuayZSMrSd5Ka7IjAvatpIernBvT2+Ic6RLTg+jSebScmasg==}
+ /jest-circus/29.4.1:
+ resolution: {integrity: sha512-v02NuL5crMNY4CGPHBEflLzl4v91NFb85a+dH9a1pUNx6Xjggrd8l9pPy4LZ1VYNRXlb+f65+7O/MSIbLir6pA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/environment': 29.3.1
- '@jest/expect': 29.3.1
- '@jest/test-result': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/environment': 29.4.1
+ '@jest/expect': 29.4.1
+ '@jest/test-result': 29.4.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
chalk: 4.1.2
co: 4.6.0
dedent: 0.7.0
is-generator-fn: 2.1.0
- jest-each: 29.3.1
- jest-matcher-utils: 29.3.1
- jest-message-util: 29.3.1
- jest-runtime: 29.3.1
- jest-snapshot: 29.3.1
- jest-util: 29.3.1
+ jest-each: 29.4.1
+ jest-matcher-utils: 29.4.1
+ jest-message-util: 29.4.1
+ jest-runtime: 29.4.1
+ jest-snapshot: 29.4.1
+ jest-util: 29.4.1
p-limit: 3.1.0
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
slash: 3.0.0
stack-utils: 2.0.6
transitivePeerDependencies:
- supports-color
dev: true
- /jest-cli/29.3.1_@types+node@18.11.18:
- resolution: {integrity: sha512-TO/ewvwyvPOiBBuWZ0gm04z3WWP8TIK8acgPzE4IxgsLKQgb377NYGrQLc3Wl/7ndWzIH2CDNNsUjGxwLL43VQ==}
+ /jest-cli/29.4.1_@types+node@18.11.18:
+ resolution: {integrity: sha512-jz7GDIhtxQ37M+9dlbv5K+/FVcIo1O/b1sX3cJgzlQUf/3VG25nvuWzlDC4F1FLLzUThJeWLu8I7JF9eWpuURQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
peerDependencies:
@@ -8643,16 +8486,16 @@ packages:
node-notifier:
optional: true
dependencies:
- '@jest/core': 29.3.1
- '@jest/test-result': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/core': 29.4.1
+ '@jest/test-result': 29.4.1
+ '@jest/types': 29.4.1
chalk: 4.1.2
exit: 0.1.2
graceful-fs: 4.2.10
import-local: 3.1.0
- jest-config: 29.3.1_@types+node@18.11.18
- jest-util: 29.3.1
- jest-validate: 29.3.1
+ jest-config: 29.4.1_@types+node@18.11.18
+ jest-util: 29.4.1
+ jest-validate: 29.4.1
prompts: 2.4.2
yargs: 17.6.2
transitivePeerDependencies:
@@ -8661,8 +8504,8 @@ packages:
- ts-node
dev: true
- /jest-config/29.3.1_@types+node@18.11.18:
- resolution: {integrity: sha512-y0tFHdj2WnTEhxmGUK1T7fgLen7YK4RtfvpLFBXfQkh2eMJAQq24Vx9472lvn5wg0MAO6B+iPfJfzdR9hJYalg==}
+ /jest-config/29.4.1_@types+node@18.11.18:
+ resolution: {integrity: sha512-g7p3q4NuXiM4hrS4XFATTkd+2z0Ml2RhFmFPM8c3WyKwVDNszbl4E7cV7WIx1YZeqqCtqbtTtZhGZWJlJqngzg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
peerDependencies:
'@types/node': '*'
@@ -8674,26 +8517,26 @@ packages:
optional: true
dependencies:
'@babel/core': 7.20.12
- '@jest/test-sequencer': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/test-sequencer': 29.4.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
- babel-jest: 29.3.1_@babel+core@7.20.12
+ babel-jest: 29.4.1_@babel+core@7.20.12
chalk: 4.1.2
ci-info: 3.7.1
deepmerge: 4.2.2
glob: 7.2.3
graceful-fs: 4.2.10
- jest-circus: 29.3.1
- jest-environment-node: 29.3.1
+ jest-circus: 29.4.1
+ jest-environment-node: 29.4.1
jest-get-type: 29.2.0
jest-regex-util: 29.2.0
- jest-resolve: 29.3.1
- jest-runner: 29.3.1
- jest-util: 29.3.1
- jest-validate: 29.3.1
+ jest-resolve: 29.4.1
+ jest-runner: 29.4.1
+ jest-util: 29.4.1
+ jest-validate: 29.4.1
micromatch: 4.0.5
parse-json: 5.2.0
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
slash: 3.0.0
strip-json-comments: 3.1.1
transitivePeerDependencies:
@@ -8707,7 +8550,17 @@ packages:
chalk: 4.1.2
diff-sequences: 29.3.1
jest-get-type: 29.2.0
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
+ dev: true
+
+ /jest-diff/29.4.1:
+ resolution: {integrity: sha512-uazdl2g331iY56CEyfbNA0Ut7Mn2ulAG5vUaEHXycf1L6IPyuImIxSz4F0VYBKi7LYIuxOwTZzK3wh5jHzASMw==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ chalk: 4.1.2
+ diff-sequences: 29.3.1
+ jest-get-type: 29.2.0
+ pretty-format: 29.4.1
dev: true
/jest-docblock/29.2.0:
@@ -8717,27 +8570,27 @@ packages:
detect-newline: 3.1.0
dev: true
- /jest-each/29.3.1:
- resolution: {integrity: sha512-qrZH7PmFB9rEzCSl00BWjZYuS1BSOH8lLuC0azQE9lQrAx3PWGKHTDudQiOSwIy5dGAJh7KA0ScYlCP7JxvFYA==}
+ /jest-each/29.4.1:
+ resolution: {integrity: sha512-QlYFiX3llJMWUV0BtWht/esGEz9w+0i7BHwODKCze7YzZzizgExB9MOfiivF/vVT0GSQ8wXLhvHXh3x2fVD4QQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.3.1
+ '@jest/types': 29.4.1
chalk: 4.1.2
jest-get-type: 29.2.0
- jest-util: 29.3.1
- pretty-format: 29.3.1
+ jest-util: 29.4.1
+ pretty-format: 29.4.1
dev: true
- /jest-environment-node/29.3.1:
- resolution: {integrity: sha512-xm2THL18Xf5sIHoU7OThBPtuH6Lerd+Y1NLYiZJlkE3hbE+7N7r8uvHIl/FkZ5ymKXJe/11SQuf3fv4v6rUMag==}
+ /jest-environment-node/29.4.1:
+ resolution: {integrity: sha512-x/H2kdVgxSkxWAIlIh9MfMuBa0hZySmfsC5lCsWmWr6tZySP44ediRKDUiNggX/eHLH7Cd5ZN10Rw+XF5tXsqg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/environment': 29.3.1
- '@jest/fake-timers': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/environment': 29.4.1
+ '@jest/fake-timers': 29.4.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
- jest-mock: 29.3.1
- jest-util: 29.3.1
+ jest-mock: 29.4.1
+ jest-util: 29.4.1
dev: true
/jest-get-type/29.2.0:
@@ -8745,31 +8598,31 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dev: true
- /jest-haste-map/29.3.1:
- resolution: {integrity: sha512-/FFtvoG1xjbbPXQLFef+WSU4yrc0fc0Dds6aRPBojUid7qlPqZvxdUBA03HW0fnVHXVCnCdkuoghYItKNzc/0A==}
+ /jest-haste-map/29.4.1:
+ resolution: {integrity: sha512-imTjcgfVVTvg02khXL11NNLTx9ZaofbAWhilrMg/G8dIkp+HYCswhxf0xxJwBkfhWb3e8dwbjuWburvxmcr58w==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.3.1
+ '@jest/types': 29.4.1
'@types/graceful-fs': 4.1.6
'@types/node': 18.11.18
anymatch: 3.1.3
fb-watchman: 2.0.2
graceful-fs: 4.2.10
jest-regex-util: 29.2.0
- jest-util: 29.3.1
- jest-worker: 29.3.1
+ jest-util: 29.4.1
+ jest-worker: 29.4.1
micromatch: 4.0.5
walker: 1.0.8
optionalDependencies:
fsevents: 2.3.2
dev: true
- /jest-leak-detector/29.3.1:
- resolution: {integrity: sha512-3DA/VVXj4zFOPagGkuqHnSQf1GZBmmlagpguxEERO6Pla2g84Q1MaVIB3YMxgUaFIaYag8ZnTyQgiZ35YEqAQA==}
+ /jest-leak-detector/29.4.1:
+ resolution: {integrity: sha512-akpZv7TPyGMnH2RimOCgy+hPmWZf55EyFUvymQ4LMsQP8xSPlZumCPtXGoDhFNhUE2039RApZkTQDKU79p/FiQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
jest-get-type: 29.2.0
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
dev: true
/jest-matcher-utils/29.3.1:
@@ -8779,7 +8632,17 @@ packages:
chalk: 4.1.2
jest-diff: 29.3.1
jest-get-type: 29.2.0
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
+ dev: true
+
+ /jest-matcher-utils/29.4.1:
+ resolution: {integrity: sha512-k5h0u8V4nAEy6lSACepxL/rw78FLDkBnXhZVgFneVpnJONhb2DhZj/Gv4eNe+1XqQ5IhgUcqj745UwH0HJmMnA==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ chalk: 4.1.2
+ jest-diff: 29.4.1
+ jest-get-type: 29.2.0
+ pretty-format: 29.4.1
dev: true
/jest-message-util/29.3.1:
@@ -8787,26 +8650,41 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/code-frame': 7.18.6
- '@jest/types': 29.3.1
+ '@jest/types': 29.4.1
'@types/stack-utils': 2.0.1
chalk: 4.1.2
graceful-fs: 4.2.10
micromatch: 4.0.5
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
slash: 3.0.0
stack-utils: 2.0.6
dev: true
- /jest-mock/29.3.1:
- resolution: {integrity: sha512-H8/qFDtDVMFvFP4X8NuOT3XRDzOUTz+FeACjufHzsOIBAxivLqkB1PoLCaJx9iPPQ8dZThHPp/G3WRWyMgA3JA==}
+ /jest-message-util/29.4.1:
+ resolution: {integrity: sha512-H4/I0cXUaLeCw6FM+i4AwCnOwHRgitdaUFOdm49022YD5nfyr8C/DrbXOBEyJaj+w/y0gGJ57klssOaUiLLQGQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.3.1
+ '@babel/code-frame': 7.18.6
+ '@jest/types': 29.4.1
+ '@types/stack-utils': 2.0.1
+ chalk: 4.1.2
+ graceful-fs: 4.2.10
+ micromatch: 4.0.5
+ pretty-format: 29.4.1
+ slash: 3.0.0
+ stack-utils: 2.0.6
+ dev: true
+
+ /jest-mock/29.4.1:
+ resolution: {integrity: sha512-MwA4hQ7zBOcgVCVnsM8TzaFLVUD/pFWTfbkY953Y81L5ret3GFRZtmPmRFAjKQSdCKoJvvqOu6Bvfpqlwwb0dQ==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
- jest-util: 29.3.1
+ jest-util: 29.4.1
dev: true
- /jest-pnp-resolver/1.2.3_jest-resolve@29.3.1:
+ /jest-pnp-resolver/1.2.3_jest-resolve@29.4.1:
resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==}
engines: {node: '>=6'}
peerDependencies:
@@ -8815,7 +8693,7 @@ packages:
jest-resolve:
optional: true
dependencies:
- jest-resolve: 29.3.1
+ jest-resolve: 29.4.1
dev: true
/jest-regex-util/29.2.0:
@@ -8823,92 +8701,93 @@ packages:
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dev: true
- /jest-resolve-dependencies/29.3.1:
- resolution: {integrity: sha512-Vk0cYq0byRw2WluNmNWGqPeRnZ3p3hHmjJMp2dyyZeYIfiBskwq4rpiuGFR6QGAdbj58WC7HN4hQHjf2mpvrLA==}
+ /jest-resolve-dependencies/29.4.1:
+ resolution: {integrity: sha512-Y3QG3M1ncAMxfjbYgtqNXC5B595zmB6e//p/qpA/58JkQXu/IpLDoLeOa8YoYfsSglBKQQzNUqtfGJJT/qLmJg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
jest-regex-util: 29.2.0
- jest-snapshot: 29.3.1
+ jest-snapshot: 29.4.1
transitivePeerDependencies:
- supports-color
dev: true
- /jest-resolve/29.3.1:
- resolution: {integrity: sha512-amXJgH/Ng712w3Uz5gqzFBBjxV8WFLSmNjoreBGMqxgCz5cH7swmBZzgBaCIOsvb0NbpJ0vgaSFdJqMdT+rADw==}
+ /jest-resolve/29.4.1:
+ resolution: {integrity: sha512-j/ZFNV2lm9IJ2wmlq1uYK0Y/1PiyDq9g4HEGsNTNr3viRbJdV+8Lf1SXIiLZXFvyiisu0qUyIXGBnw+OKWkJwQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
chalk: 4.1.2
graceful-fs: 4.2.10
- jest-haste-map: 29.3.1
- jest-pnp-resolver: 1.2.3_jest-resolve@29.3.1
- jest-util: 29.3.1
- jest-validate: 29.3.1
+ jest-haste-map: 29.4.1
+ jest-pnp-resolver: 1.2.3_jest-resolve@29.4.1
+ jest-util: 29.4.1
+ jest-validate: 29.4.1
resolve: 1.22.1
- resolve.exports: 1.1.1
+ resolve.exports: 2.0.0
slash: 3.0.0
dev: true
- /jest-runner/29.3.1:
- resolution: {integrity: sha512-oFvcwRNrKMtE6u9+AQPMATxFcTySyKfLhvso7Sdk/rNpbhg4g2GAGCopiInk1OP4q6gz3n6MajW4+fnHWlU3bA==}
+ /jest-runner/29.4.1:
+ resolution: {integrity: sha512-8d6XXXi7GtHmsHrnaqBKWxjKb166Eyj/ksSaUYdcBK09VbjPwIgWov1VwSmtupCIz8q1Xv4Qkzt/BTo3ZqiCeg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/console': 29.3.1
- '@jest/environment': 29.3.1
- '@jest/test-result': 29.3.1
- '@jest/transform': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/console': 29.4.1
+ '@jest/environment': 29.4.1
+ '@jest/test-result': 29.4.1
+ '@jest/transform': 29.4.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
chalk: 4.1.2
emittery: 0.13.1
graceful-fs: 4.2.10
jest-docblock: 29.2.0
- jest-environment-node: 29.3.1
- jest-haste-map: 29.3.1
- jest-leak-detector: 29.3.1
- jest-message-util: 29.3.1
- jest-resolve: 29.3.1
- jest-runtime: 29.3.1
- jest-util: 29.3.1
- jest-watcher: 29.3.1
- jest-worker: 29.3.1
+ jest-environment-node: 29.4.1
+ jest-haste-map: 29.4.1
+ jest-leak-detector: 29.4.1
+ jest-message-util: 29.4.1
+ jest-resolve: 29.4.1
+ jest-runtime: 29.4.1
+ jest-util: 29.4.1
+ jest-watcher: 29.4.1
+ jest-worker: 29.4.1
p-limit: 3.1.0
source-map-support: 0.5.13
transitivePeerDependencies:
- supports-color
dev: true
- /jest-runtime/29.3.1:
- resolution: {integrity: sha512-jLzkIxIqXwBEOZx7wx9OO9sxoZmgT2NhmQKzHQm1xwR1kNW/dn0OjxR424VwHHf1SPN6Qwlb5pp1oGCeFTQ62A==}
+ /jest-runtime/29.4.1:
+ resolution: {integrity: sha512-UXTMU9uKu2GjYwTtoAw5rn4STxWw/nadOfW7v1sx6LaJYa3V/iymdCLQM6xy3+7C6mY8GfX22vKpgxY171UIoA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/environment': 29.3.1
- '@jest/fake-timers': 29.3.1
- '@jest/globals': 29.3.1
+ '@jest/environment': 29.4.1
+ '@jest/fake-timers': 29.4.1
+ '@jest/globals': 29.4.1
'@jest/source-map': 29.2.0
- '@jest/test-result': 29.3.1
- '@jest/transform': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/test-result': 29.4.1
+ '@jest/transform': 29.4.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
chalk: 4.1.2
cjs-module-lexer: 1.2.2
collect-v8-coverage: 1.0.1
glob: 7.2.3
graceful-fs: 4.2.10
- jest-haste-map: 29.3.1
- jest-message-util: 29.3.1
- jest-mock: 29.3.1
+ jest-haste-map: 29.4.1
+ jest-message-util: 29.4.1
+ jest-mock: 29.4.1
jest-regex-util: 29.2.0
- jest-resolve: 29.3.1
- jest-snapshot: 29.3.1
- jest-util: 29.3.1
+ jest-resolve: 29.4.1
+ jest-snapshot: 29.4.1
+ jest-util: 29.4.1
+ semver: 7.3.8
slash: 3.0.0
strip-bom: 4.0.0
transitivePeerDependencies:
- supports-color
dev: true
- /jest-snapshot/29.3.1:
- resolution: {integrity: sha512-+3JOc+s28upYLI2OJM4PWRGK9AgpsMs/ekNryUV0yMBClT9B1DF2u2qay8YxcQd338PPYSFNb0lsar1B49sLDA==}
+ /jest-snapshot/29.4.1:
+ resolution: {integrity: sha512-l4iV8EjGgQWVz3ee/LR9sULDk2pCkqb71bjvlqn+qp90lFwpnulHj4ZBT8nm1hA1C5wowXLc7MGnw321u0tsYA==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@babel/core': 7.20.12
@@ -8917,33 +8796,33 @@ packages:
'@babel/plugin-syntax-typescript': 7.20.0_@babel+core@7.20.12
'@babel/traverse': 7.20.12
'@babel/types': 7.20.7
- '@jest/expect-utils': 29.3.1
- '@jest/transform': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/expect-utils': 29.4.1
+ '@jest/transform': 29.4.1
+ '@jest/types': 29.4.1
'@types/babel__traverse': 7.18.3
'@types/prettier': 2.7.2
babel-preset-current-node-syntax: 1.0.1_@babel+core@7.20.12
chalk: 4.1.2
- expect: 29.3.1
+ expect: 29.4.1
graceful-fs: 4.2.10
- jest-diff: 29.3.1
+ jest-diff: 29.4.1
jest-get-type: 29.2.0
- jest-haste-map: 29.3.1
- jest-matcher-utils: 29.3.1
- jest-message-util: 29.3.1
- jest-util: 29.3.1
+ jest-haste-map: 29.4.1
+ jest-matcher-utils: 29.4.1
+ jest-message-util: 29.4.1
+ jest-util: 29.4.1
natural-compare: 1.4.0
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
semver: 7.3.8
transitivePeerDependencies:
- supports-color
dev: true
- /jest-util/29.3.1:
- resolution: {integrity: sha512-7YOVZaiX7RJLv76ZfHt4nbNEzzTRiMW/IiOG7ZOKmTXmoGBxUDefgMAxQubu6WPVqP5zSzAdZG0FfLcC7HOIFQ==}
+ /jest-util/29.4.1:
+ resolution: {integrity: sha512-bQy9FPGxVutgpN4VRc0hk6w7Hx/m6L53QxpDreTZgJd9gfx/AV2MjyPde9tGyZRINAUrSv57p2inGBu2dRLmkQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.3.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
chalk: 4.1.2
ci-info: 3.7.1
@@ -8951,44 +8830,44 @@ packages:
picomatch: 2.3.1
dev: true
- /jest-validate/29.3.1:
- resolution: {integrity: sha512-N9Lr3oYR2Mpzuelp1F8negJR3YE+L1ebk1rYA5qYo9TTY3f9OWdptLoNSPP9itOCBIRBqjt/S5XHlzYglLN67g==}
+ /jest-validate/29.4.1:
+ resolution: {integrity: sha512-qNZXcZQdIQx4SfUB/atWnI4/I2HUvhz8ajOSYUu40CSmf9U5emil8EDHgE7M+3j9/pavtk3knlZBDsgFvv/SWw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/types': 29.3.1
+ '@jest/types': 29.4.1
camelcase: 6.3.0
chalk: 4.1.2
jest-get-type: 29.2.0
leven: 3.1.0
- pretty-format: 29.3.1
+ pretty-format: 29.4.1
dev: true
- /jest-watcher/29.3.1:
- resolution: {integrity: sha512-RspXG2BQFDsZSRKGCT/NiNa8RkQ1iKAjrO0//soTMWx/QUt+OcxMqMSBxz23PYGqUuWm2+m2mNNsmj0eIoOaFg==}
+ /jest-watcher/29.4.1:
+ resolution: {integrity: sha512-vFOzflGFs27nU6h8dpnVRER3O2rFtL+VMEwnG0H3KLHcllLsU8y9DchSh0AL/Rg5nN1/wSiQ+P4ByMGpuybaVw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
- '@jest/test-result': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/test-result': 29.4.1
+ '@jest/types': 29.4.1
'@types/node': 18.11.18
ansi-escapes: 4.3.2
chalk: 4.1.2
emittery: 0.13.1
- jest-util: 29.3.1
+ jest-util: 29.4.1
string-length: 4.0.2
dev: true
- /jest-worker/29.3.1:
- resolution: {integrity: sha512-lY4AnnmsEWeiXirAIA0c9SDPbuCBq8IYuDVL8PMm0MZ2PEs2yPvRA/J64QBXuZp7CYKrDM/rmNrc9/i3KJQncw==}
+ /jest-worker/29.4.1:
+ resolution: {integrity: sha512-O9doU/S1EBe+yp/mstQ0VpPwpv0Clgn68TkNwGxL6/usX/KUW9Arnn4ag8C3jc6qHcXznhsT5Na1liYzAsuAbQ==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
dependencies:
'@types/node': 18.11.18
- jest-util: 29.3.1
+ jest-util: 29.4.1
merge-stream: 2.0.0
supports-color: 8.1.1
dev: true
- /jest/29.3.1_@types+node@18.11.18:
- resolution: {integrity: sha512-6iWfL5DTT0Np6UYs/y5Niu7WIfNv/wRTtN5RSXt2DIEft3dx3zPuw/3WJQBCJfmEzvDiEKwoqMbGD9n49+qLSA==}
+ /jest/29.4.1_@types+node@18.11.18:
+ resolution: {integrity: sha512-cknimw7gAXPDOmj0QqztlxVtBVCw2lYY9CeIE5N6kD+kET1H4H79HSNISJmijb1HF+qk+G+ploJgiDi5k/fRlg==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
hasBin: true
peerDependencies:
@@ -8997,10 +8876,10 @@ packages:
node-notifier:
optional: true
dependencies:
- '@jest/core': 29.3.1
- '@jest/types': 29.3.1
+ '@jest/core': 29.4.1
+ '@jest/types': 29.4.1
import-local: 3.1.0
- jest-cli: 29.3.1_@types+node@18.11.18
+ jest-cli: 29.4.1_@types+node@18.11.18
transitivePeerDependencies:
- '@types/node'
- supports-color
@@ -11304,6 +11183,15 @@ packages:
react-is: 18.2.0
dev: true
+ /pretty-format/29.4.1:
+ resolution: {integrity: sha512-dt/Z761JUVsrIKaY215o1xQJBGlSmTx/h4cSqXqjHLnU1+Kt+mavVE7UgqJJO5ukx5HjSswHfmXz4LjS2oIJfg==}
+ engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
+ dependencies:
+ '@jest/schemas': 29.4.0
+ ansi-styles: 5.2.0
+ react-is: 18.2.0
+ dev: true
+
/pretty-hrtime/1.0.3:
resolution: {integrity: sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==}
engines: {node: '>= 0.8'}
@@ -12017,8 +11905,8 @@ packages:
deprecated: https://github.com/lydell/resolve-url#deprecated
dev: false
- /resolve.exports/1.1.1:
- resolution: {integrity: sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==}
+ /resolve.exports/2.0.0:
+ resolution: {integrity: sha512-6K/gDlqgQscOlg9fSRpWstA8sYe8rbELsSTNpx+3kTrsVCzvSl0zIvRErM7fdl9ERWDsKnrLnwB+Ne89918XOg==}
engines: {node: '>=10'}
dev: true
@@ -12099,8 +11987,8 @@ packages:
seedrandom: 2.4.2
dev: false
- /rollup/3.10.1:
- resolution: {integrity: sha512-3Er+yel3bZbZX1g2kjVM+FW+RUWDxbG87fcqFM5/9HbPCTpbVp6JOLn7jlxnNlbu7s/N/uDA4EV/91E2gWnxzw==}
+ /rollup/3.11.0:
+ resolution: {integrity: sha512-+uWPPkpWQ2H3Qi7sNBcRfhhHJyUNgBYhG4wKe5wuGRj2m55kpo+0p5jubKNBjQODyPe6tSBE3tNpdDwEisQvAQ==}
engines: {node: '>=14.18.0', npm: '>=8.0.0'}
hasBin: true
optionalDependencies:
@@ -12913,8 +12801,8 @@ packages:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
dev: false
- /systeminformation/5.17.3:
- resolution: {integrity: sha512-IAmnUJdeFUWqY+YneAWJ9rceTdRRIaTiwspvd1B6SG7yhqpxLrSosHgGZKiE8lcaBlBYpLQpY3BRLtus4n8PNQ==}
+ /systeminformation/5.17.4:
+ resolution: {integrity: sha512-mEiIYrw7X5ABX8tJUgzbumQAuFQxNyHdZDz6+UtwNKUbKgIoZqLtug2z1spFB/LiXZne5tdPBJOlvVckbvfhiQ==}
engines: {node: '>=8.0.0'}
os: [darwin, linux, win32, freebsd, openbsd, netbsd, sunos, android]
hasBin: true
@@ -13039,8 +12927,8 @@ packages:
real-require: 0.2.0
dev: false
- /three/0.148.0:
- resolution: {integrity: sha512-8uzVV+qhTPi0bOFs/3te3RW6hb3urL8jYEl6irjCWo/l6sr8MPNMcClFev/MMYeIxr0gmDcoXTy/8LXh/LXkfw==}
+ /three/0.149.0:
+ resolution: {integrity: sha512-tohpUxPDht0qExRLDTM8sjRLc5d9STURNrdnK3w9A+V4pxaTBfKWWT/IqtiLfg23Vfc3Z+ImNfvRw1/0CtxrkQ==}
dev: false
/throttle-debounce/5.0.0:
@@ -13794,7 +13682,7 @@ packages:
esbuild: 0.16.17
postcss: 8.4.21
resolve: 1.22.1
- rollup: 3.10.1
+ rollup: 3.11.0
sass: 1.57.1
optionalDependencies:
fsevents: 2.3.2
@@ -14058,9 +13946,9 @@ packages:
/wrappy/1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
- /write-file-atomic/4.0.2:
- resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==}
- engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0}
+ /write-file-atomic/5.0.0:
+ resolution: {integrity: sha512-R7NYMnHSlV42K54lwY9lvW6MnSm1HSJqZL3xiSgi9E7//FYaI74r2G0rd+/X6VAMkHEdzxQaU5HUOXWUz5kA/w==}
+ engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
dependencies:
imurmurhash: 0.1.4
signal-exit: 3.0.7