From 6dd9374b994e3c0cca75124cd174d328df4fb318 Mon Sep 17 00:00:00 2001
From: Ikumi Nakamura <28798279+johnmanjiro13@users.noreply.github.com>
Date: Sat, 4 Mar 2023 17:42:03 +0900
Subject: [PATCH 1/5] chore: Replace tab with space (#10185)

---
 chart/templates/Deployment.yml | 6 +++---
 chart/templates/Service.yml    | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/chart/templates/Deployment.yml b/chart/templates/Deployment.yml
index d16aece915..d5dd14f59e 100644
--- a/chart/templates/Deployment.yml
+++ b/chart/templates/Deployment.yml
@@ -3,16 +3,16 @@ kind: Deployment
 metadata:
   name: {{ include "misskey.fullname" . }}
   labels:
-		{{- include "misskey.labels" . | nindent 4 }}
+    {{- include "misskey.labels" . | nindent 4 }}
 spec:
   selector:
     matchLabels:
-			{{- include "misskey.selectorLabels" . | nindent 6 }}
+      {{- include "misskey.selectorLabels" . | nindent 6 }}
   replicas: 1
   template:
     metadata:
       labels:
-				{{- include "misskey.selectorLabels" . | nindent 8 }}
+        {{- include "misskey.selectorLabels" . | nindent 8 }}
     spec:
       containers:
         - name: misskey
diff --git a/chart/templates/Service.yml b/chart/templates/Service.yml
index 3209581298..afd851a9f1 100644
--- a/chart/templates/Service.yml
+++ b/chart/templates/Service.yml
@@ -11,4 +11,4 @@ spec:
       protocol: TCP
       name: http
   selector:
-		{{- include "misskey.selectorLabels" . | nindent 4 }}
+    {{- include "misskey.selectorLabels" . | nindent 4 }}

From 72b315491bfc000a433f7cbd4cbcc6df7fedd5d4 Mon Sep 17 00:00:00 2001
From: nexryai <61890205+nexryai@users.noreply.github.com>
Date: Sat, 4 Mar 2023 19:19:55 +0900
Subject: [PATCH 2/5] Fix: If mail delivery is disabled on the server, make the
 settings page indicate this (#10191)

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
---
 locales/ja-JP.yml                              | 1 +
 packages/frontend/src/pages/settings/email.vue | 7 ++++++-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index ef70469935..f94133c19f 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -956,6 +956,7 @@ exploreOtherServers: "他のサーバーを探す"
 letsLookAtTimeline: "タイムラインを見てみる"
 disableFederationWarn: "連合が無効になっています。無効にしても投稿が非公開にはなりません。ほとんどの場合、このオプションを有効にする必要はありません。"
 invitationRequiredToRegister: "現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。"
+emailNotSupported: "このサーバーではメール配信はサポートされていません"
 postToTheChannel: "チャンネルに投稿"
 
 _achievements:
diff --git a/packages/frontend/src/pages/settings/email.vue b/packages/frontend/src/pages/settings/email.vue
index 1734dcfe42..b1e6f223b6 100644
--- a/packages/frontend/src/pages/settings/email.vue
+++ b/packages/frontend/src/pages/settings/email.vue
@@ -1,5 +1,5 @@
 <template>
-<div class="_gaps_m">
+<div v-if="instance.enableEmail" class="_gaps_m">
 	<FormSection first>
 		<template #label>{{ i18n.ts.emailAddress }}</template>
 		<MkInput v-model="emailAddress" type="email" manual-save>
@@ -37,17 +37,22 @@
 		</div>
 	</FormSection>
 </div>
+<div v-if="!instance.enableEmail" class="_gaps_m">
+	<MkInfo>{{ i18n.ts.emailNotSupported }}</MkInfo>
+</div>
 </template>
 
 <script lang="ts" setup>
 import { onMounted, ref, watch } from 'vue';
 import FormSection from '@/components/form/section.vue';
+import MkInfo from '@/components/MkInfo.vue';
 import MkInput from '@/components/MkInput.vue';
 import MkSwitch from '@/components/MkSwitch.vue';
 import * as os from '@/os';
 import { $i } from '@/account';
 import { i18n } from '@/i18n';
 import { definePageMetadata } from '@/scripts/page-metadata';
+import { instance } from '@/instance';
 
 const emailAddress = ref($i!.email);
 

From c36e7d1a070b684e08a5d967e99db5e03deb9534 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Sat, 4 Mar 2023 19:23:11 +0900
Subject: [PATCH 3/5] =?UTF-8?q?enhance(server):=20=E3=83=A1=E3=83=87?=
 =?UTF-8?q?=E3=82=A3=E3=82=A2=E3=83=97=E3=83=AD=E3=82=AD=E3=82=B7=E3=81=A7?=
 =?UTF-8?q?ico,bmp=E3=82=92=E8=AA=AD=E3=82=81=E3=82=8B=E3=82=88=E3=81=86?=
 =?UTF-8?q?=E3=81=AB=20(#10186)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* enhance(server): downloadUrlでContent-Dispositionからファイル名を取得
Resolve #10036
Resolve #4750

* untitled

* オブジェクトストレージのContent-Dispositionのファイル名の拡張子をContent-Typeに添ったものにする

* :v:

* tiff

* fix filename

* add test

* /files/でもContent-Disposition

* enhance(server): メディアプロキシでico,bmpを読めるように
Fix #10120

* comment

* fix test

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
---
 packages/backend/package.json                 |  1 +
 packages/backend/src/misc/is-mime-image.ts    |  2 +
 .../backend/src/server/FileServerService.ts   | 15 ++++---
 pnpm-lock.yaml                                | 45 +++++++++++++++++--
 4 files changed, 53 insertions(+), 10 deletions(-)

diff --git a/packages/backend/package.json b/packages/backend/package.json
index 42efb881e2..35e8dc5c60 100644
--- a/packages/backend/package.json
+++ b/packages/backend/package.json
@@ -124,6 +124,7 @@
 		"seedrandom": "3.0.5",
 		"semver": "7.3.8",
 		"sharp": "0.31.3",
+		"sharp-read-bmp": "github:misskey-dev/sharp-read-bmp",
 		"strict-event-emitter-types": "2.0.0",
 		"stringz": "2.1.0",
 		"summaly": "github:misskey-dev/summaly",
diff --git a/packages/backend/src/misc/is-mime-image.ts b/packages/backend/src/misc/is-mime-image.ts
index acf5c1ede3..0b6d147dc1 100644
--- a/packages/backend/src/misc/is-mime-image.ts
+++ b/packages/backend/src/misc/is-mime-image.ts
@@ -4,6 +4,8 @@ const dictionary = {
 	'safe-file': FILE_TYPE_BROWSERSAFE,
 	'sharp-convertible-image': ['image/jpeg', 'image/png', 'image/gif', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp', 'image/avif', 'image/svg+xml'],
 	'sharp-animation-convertible-image': ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/avif', 'image/svg+xml'],
+	'sharp-convertible-image-with-bmp': ['image/jpeg', 'image/png', 'image/gif', 'image/apng', 'image/vnd.mozilla.apng', 'image/webp', 'image/avif', 'image/svg+xml', 'image/x-icon', 'image/bmp'],
+	'sharp-animation-convertible-image-with-bmp': ['image/jpeg', 'image/png', 'image/gif', 'image/webp', 'image/avif', 'image/svg+xml', 'image/x-icon', 'image/bmp'],
 };
 
 export const isMimeImage = (mime: string, type: keyof typeof dictionary): boolean => dictionary[type].includes(mime);
diff --git a/packages/backend/src/server/FileServerService.ts b/packages/backend/src/server/FileServerService.ts
index 8eeb76f7c7..835657b625 100644
--- a/packages/backend/src/server/FileServerService.ts
+++ b/packages/backend/src/server/FileServerService.ts
@@ -22,6 +22,7 @@ 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';
+import { sharpBmp } from 'sharp-read-bmp';
 import { correctFilename } from '@/misc/correct-filename.js';
 
 const _filename = fileURLToPath(import.meta.url);
@@ -132,7 +133,7 @@ export class FileServerService {
 				let image: IImageStreamable | null = null;
 
 				if (file.fileRole === 'thumbnail') {
-					if (isMimeImage(file.mime, 'sharp-convertible-image')) {
+					if (isMimeImage(file.mime, 'sharp-convertible-image-with-bmp')) {
 						reply.header('Cache-Control', 'max-age=31536000, immutable');
 
 						const url = new URL(`${this.config.mediaProxy}/static.webp`);
@@ -257,8 +258,8 @@ export class FileServerService {
 		}
 
 		try {
-			const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image');
-			const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image');
+			const isConvertibleImage = isMimeImage(file.mime, 'sharp-convertible-image-with-bmp');
+			const isAnimationConvertibleImage = isMimeImage(file.mime, 'sharp-animation-convertible-image-with-bmp');
 
 			if (
 				'emoji' in request.query ||
@@ -282,7 +283,7 @@ export class FileServerService {
 						type: file.mime,
 					};
 				} else {
-					const data = sharp(file.path, { animated: !('static' in request.query) })
+					const data = (await sharpBmp(file.path, file.mime, { animated: !('static' in request.query) }))
 							.resize({
 								height: 'emoji' in request.query ? 128 : 320,
 								withoutEnlargement: true,
@@ -296,11 +297,11 @@ export class FileServerService {
 					};
 				}
 			} else if ('static' in request.query) {
-				image = this.imageProcessingService.convertToWebpStream(file.path, 498, 280);
+				image = this.imageProcessingService.convertSharpToWebpStream(await sharpBmp(file.path, file.mime), 498, 280);
 			} else if ('preview' in request.query) {
-				image = this.imageProcessingService.convertToWebpStream(file.path, 200, 200);
+				image = this.imageProcessingService.convertSharpToWebpStream(await sharpBmp(file.path, file.mime), 200, 200);
 			} else if ('badge' in request.query) {
-				const mask = sharp(file.path)
+				const mask = (await sharpBmp(file.path, file.mime))
 					.resize(96, 96, {
 						fit: 'inside',
 						withoutEnlargement: false,
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1b9947a080..17be01e45c 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -198,6 +198,7 @@ importers:
       seedrandom: 3.0.5
       semver: 7.3.8
       sharp: 0.31.3
+      sharp-read-bmp: github:misskey-dev/sharp-read-bmp
       strict-event-emitter-types: 2.0.0
       stringz: 2.1.0
       summaly: github:misskey-dev/summaly
@@ -305,6 +306,7 @@ importers:
       seedrandom: 3.0.5
       semver: 7.3.8
       sharp: 0.31.3
+      sharp-read-bmp: github.com/misskey-dev/sharp-read-bmp/02d9dc189fa7df0c4bea09330be26741772dac01
       strict-event-emitter-types: 2.0.0
       stringz: 2.1.0
       summaly: github.com/misskey-dev/summaly/51f3870e1ff5e0b22102e804112b10cb72f3c494
@@ -948,6 +950,10 @@ packages:
       '@bull-board/api': 4.12.1
     dev: false
 
+  /@canvas/image-data/1.0.0:
+    resolution: {integrity: sha512-BxOqI5LgsIQP1odU5KMwV9yoijleOPzHL18/YvNqF9KFSGF2K/DLlYAbDQsWqd/1nbaFuSkYD/191dpMtNh4vw==}
+    dev: false
+
   /@chainsafe/is-ip/2.0.1:
     resolution: {integrity: sha512-nqSJ8u2a1Rv9FYbyI8qpDhTYujaKEyLknNrTejLYoSWmdeg+2WB7R6BZqPZYfrJzDxVi3rl6ZQuoaEvpKRZWgQ==}
     dev: false
@@ -3859,7 +3865,7 @@ packages:
   /axios/0.24.0:
     resolution: {integrity: sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==}
     dependencies:
-      follow-redirects: 1.15.2
+      follow-redirects: 1.15.2_debug@4.3.4
     transitivePeerDependencies:
       - debug
     dev: false
@@ -3867,7 +3873,7 @@ packages:
   /axios/0.27.2_debug@4.3.4:
     resolution: {integrity: sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==}
     dependencies:
-      follow-redirects: 1.15.2
+      follow-redirects: 1.15.2_debug@4.3.4
       form-data: 4.0.0
     transitivePeerDependencies:
       - debug
@@ -5201,6 +5207,23 @@ packages:
     resolution: {integrity: sha512-ic1yEvwT6GuvaYwBLLY6/aFFgjZdySKTE8en/fkU3QICTmRtgtSlFn0u0BXN06InZwtfCelR7j8LRiDI/02iGA==}
     dev: false
 
+  /decode-bmp/0.2.1:
+    resolution: {integrity: sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA==}
+    engines: {node: '>=8.6.0'}
+    dependencies:
+      '@canvas/image-data': 1.0.0
+      to-data-view: 1.1.0
+    dev: false
+
+  /decode-ico/0.4.1:
+    resolution: {integrity: sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA==}
+    engines: {node: '>=8.6'}
+    dependencies:
+      '@canvas/image-data': 1.0.0
+      decode-bmp: 0.2.1
+      to-data-view: 1.1.0
+    dev: false
+
   /decode-uri-component/0.2.2:
     resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==}
     engines: {node: '>=0.10'}
@@ -6766,7 +6789,7 @@ packages:
       readable-stream: 2.3.7
     dev: false
 
-  /follow-redirects/1.15.2:
+  /follow-redirects/1.15.2_debug@4.3.4:
     resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
     engines: {node: '>=4.0'}
     peerDependencies:
@@ -6774,6 +6797,8 @@ packages:
     peerDependenciesMeta:
       debug:
         optional: true
+    dependencies:
+      debug: 4.3.4
 
   /for-each/0.3.3:
     resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
@@ -12542,6 +12567,10 @@ packages:
       is-negated-glob: 1.0.0
     dev: false
 
+  /to-data-view/1.1.0:
+    resolution: {integrity: sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==}
+    dev: false
+
   /to-fast-properties/2.0.0:
     resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
     engines: {node: '>=4'}
@@ -13676,6 +13705,16 @@ packages:
     version: 2.2.1-misskey.3
     dev: false
 
+  github.com/misskey-dev/sharp-read-bmp/02d9dc189fa7df0c4bea09330be26741772dac01:
+    resolution: {tarball: https://codeload.github.com/misskey-dev/sharp-read-bmp/tar.gz/02d9dc189fa7df0c4bea09330be26741772dac01}
+    name: sharp-read-bmp
+    version: 1.0.0
+    dependencies:
+      decode-bmp: 0.2.1
+      decode-ico: 0.4.1
+      sharp: 0.31.3
+    dev: false
+
   github.com/misskey-dev/summaly/51f3870e1ff5e0b22102e804112b10cb72f3c494:
     resolution: {tarball: https://codeload.github.com/misskey-dev/summaly/tar.gz/51f3870e1ff5e0b22102e804112b10cb72f3c494}
     name: summaly

From ccdac0ca968ca651af97bb864fcd5bc5954cb968 Mon Sep 17 00:00:00 2001
From: rinsuki <428rinsuki+git@gmail.com>
Date: Sat, 4 Mar 2023 21:36:52 +0900
Subject: [PATCH 4/5] docker: build assets on native arch (#10080)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* docker: build assets on native arch

* 消しすぎた
---
 Dockerfile | 46 ++++++++++++++++++++++++++++++++--------------
 1 file changed, 32 insertions(+), 14 deletions(-)

diff --git a/Dockerfile b/Dockerfile
index b439716bea..eeff38e48b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,7 +2,9 @@
 
 ARG NODE_VERSION=18.13.0-bullseye
 
-FROM node:${NODE_VERSION} AS builder
+# build assets & compile TypeScript
+
+FROM --platform=$BUILDPLATFORM node:${NODE_VERSION} AS native-builder
 
 RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
 	--mount=type=cache,target=/var/lib/apt,sharing=locked \
@@ -33,33 +35,49 @@ RUN git submodule update --init
 RUN pnpm build
 RUN rm -rf .git/
 
-FROM node:${NODE_VERSION}-slim AS runner
+# build native dependencies for target platform
+
+FROM --platform=$TARGETPLATFORM node:${NODE_VERSION} AS target-builder
+
+RUN apt-get update \
+	&& apt-get install -yqq --no-install-recommends \
+	build-essential
+
+RUN corepack enable
+
+WORKDIR /misskey
+
+COPY --link ["pnpm-lock.yaml", "pnpm-workspace.yaml", "package.json", "./"]
+COPY --link ["scripts", "./scripts"]
+COPY --link ["packages/backend/package.json", "./packages/backend/"]
+
+RUN --mount=type=cache,target=/root/.local/share/pnpm/store,sharing=locked \
+	pnpm i --frozen-lockfile --aggregate-output
+
+FROM --platform=$TARGETPLATFORM node:${NODE_VERSION}-slim AS runner
 
 ARG UID="991"
 ARG GID="991"
 
-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 \
+RUN apt-get update \
 	&& apt-get install -y --no-install-recommends \
 	ffmpeg tini curl \
 	&& corepack enable \
 	&& groupadd -g "${GID}" misskey \
 	&& useradd -l -u "${UID}" -g "${GID}" -m -d /misskey misskey \
 	&& find / -type f -perm /u+s -ignore_readdir_race -exec chmod u-s {} \; \
-	&& find / -type f -perm /g+s -ignore_readdir_race -exec chmod g-s {} \;
+	&& find / -type f -perm /g+s -ignore_readdir_race -exec chmod g-s {} \; \
+	&& apt-get clean \
+	&& rm -rf /var/lib/apt/lists
 
 USER misskey
 WORKDIR /misskey
 
-COPY --chown=misskey:misskey --from=builder /misskey/node_modules ./node_modules
-COPY --chown=misskey:misskey --from=builder /misskey/built ./built
-COPY --chown=misskey:misskey --from=builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
-COPY --chown=misskey:misskey --from=builder /misskey/packages/backend/built ./packages/backend/built
-COPY --chown=misskey:misskey --from=builder /misskey/packages/frontend/node_modules ./packages/frontend/node_modules
-COPY --chown=misskey:misskey --from=builder /misskey/fluent-emojis /misskey/fluent-emojis
+COPY --chown=misskey:misskey --from=target-builder /misskey/node_modules ./node_modules
+COPY --chown=misskey:misskey --from=target-builder /misskey/packages/backend/node_modules ./packages/backend/node_modules
+COPY --chown=misskey:misskey --from=native-builder /misskey/built ./built
+COPY --chown=misskey:misskey --from=native-builder /misskey/packages/backend/built ./packages/backend/built
+COPY --chown=misskey:misskey --from=native-builder /misskey/fluent-emojis /misskey/fluent-emojis
 COPY --chown=misskey:misskey . ./
 
 ENV NODE_ENV=production

From c54712233cfe212b090a16c567cb1c1ed8cc8058 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Sun, 5 Mar 2023 01:06:30 +0900
Subject: [PATCH 5/5] =?UTF-8?q?Dev=20Container=E5=91=A8=E3=82=8A=20Related?=
 =?UTF-8?q?=20to=20#10201?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .devcontainer/devcontainer.json | 19 +++++++++++++++----
 .dockerignore                   |  2 ++
 .gitignore                      |  3 +++
 .vscode/extensions.json         |  5 ++++-
 4 files changed, 24 insertions(+), 5 deletions(-)

diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index fde7ec0f2b..59d3959462 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -3,9 +3,20 @@
 	"dockerComposeFile": "docker-compose.yml",
 	"service": "app",
 	"workspaceFolder": "/workspace",
-	"features": {
-		"ghcr.io/devcontainers-contrib/features/pnpm:2": {}
-	},
 	"forwardPorts": [3000],
-	"postCreateCommand": "sudo chmod 755 .devcontainer/init.sh && .devcontainer/init.sh"
+	"postCreateCommand": "sudo chmod 755 .devcontainer/init.sh && .devcontainer/init.sh",
+	"customizations": {
+		"vscode": {
+			"extensions": [
+				"editorconfig.editorconfig",
+				"eg2.vscode-npm-script",
+				"dbaeumer.vscode-eslint",
+				"Vue.volar",
+				"Vue.vscode-typescript-vue-plugin",
+				"Orta.vscode-jest",
+				"dbaeumer.vscode-eslint",
+				"mrmlnc.vscode-json5"
+			]
+		}
+	}
 }
diff --git a/.dockerignore b/.dockerignore
index 8f984831ef..151ede038e 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -25,6 +25,8 @@ fluent-emojis/
 !.yarn/sdks
 !.yarn/versions
 
+.pnpm-store
+
 .idea/
 packages/*/.vscode/
 packages/backend/test/docker-compose.yml
diff --git a/.gitignore b/.gitignore
index 62b818c629..c413cd4da9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -20,6 +20,9 @@ packages/frontend/.yarn/cache
 packages/backend/.yarn/cache
 packages/sw/.yarn/cache
 
+# pnpm
+.pnpm-store
+
 # Cypress
 cypress/screenshots
 cypress/videos
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
index 42264548ea..6b0c1540fb 100644
--- a/.vscode/extensions.json
+++ b/.vscode/extensions.json
@@ -4,6 +4,9 @@
 		"eg2.vscode-npm-script",
 		"dbaeumer.vscode-eslint",
 		"Vue.volar",
-		"Vue.vscode-typescript-vue-plugin"
+		"Vue.vscode-typescript-vue-plugin",
+		"Orta.vscode-jest",
+		"dbaeumer.vscode-eslint",
+		"mrmlnc.vscode-json5"
 	]
 }