From 41ed9a1a7263fbdfac46c6c49f19f8d8d82f55de Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Sun, 2 Jan 2022 21:35:23 +0900
Subject: [PATCH 01/19] tweak client

---
 packages/client/package.json                  |  2 -
 packages/client/src/components/form/group.vue |  3 +-
 packages/client/src/components/form/radio.vue | 20 ++--
 packages/client/src/init.ts                   | 14 ---
 packages/client/src/os.ts                     | 14 ---
 packages/client/src/pages/admin/index.vue     |  6 --
 packages/client/src/pages/admin/overview.vue  |  2 -
 packages/client/src/pages/reset-password.vue  | 31 +++---
 packages/client/src/pages/settings/2fa.vue    |  3 -
 packages/client/src/pages/settings/email.vue  |  4 -
 .../pages/settings/experimental-features.vue  | 52 ----------
 packages/client/src/pages/settings/index.vue  |  2 -
 packages/client/src/pages/settings/other.vue  |  3 -
 .../client/src/pages/settings/security.vue    |  2 -
 .../src/pages/settings/theme.install.vue      | 31 ++----
 .../src/pages/settings/theme.manage.vue       |  6 --
 packages/client/src/pages/settings/update.vue | 95 -------------------
 .../client/src/pages/settings/word-mute.vue   |  2 -
 packages/client/yarn.lock                     | 68 -------------
 19 files changed, 37 insertions(+), 323 deletions(-)
 delete mode 100644 packages/client/src/pages/settings/experimental-features.vue
 delete mode 100644 packages/client/src/pages/settings/update.vue

diff --git a/packages/client/package.json b/packages/client/package.json
index ff6357990..167ab2e81 100644
--- a/packages/client/package.json
+++ b/packages/client/package.json
@@ -11,8 +11,6 @@
 	},
 	"dependencies": {
 		"@discordapp/twemoji": "13.1.0",
-		"@sentry/browser": "5.29.2",
-		"@sentry/tracing": "5.29.2",
 		"@syuilo/aiscript": "0.11.1",
 		"@types/dateformat": "3.0.1",
 		"@types/escape-regexp": "0.0.0",
diff --git a/packages/client/src/components/form/group.vue b/packages/client/src/components/form/group.vue
index 2fc203f1b..1e8376ca4 100644
--- a/packages/client/src/components/form/group.vue
+++ b/packages/client/src/components/form/group.vue
@@ -1,5 +1,5 @@
 <template>
-<div v-sticky-container v-panel class="adfeebaf _formBlock">
+<div v-sticky-container class="adfeebaf _formBlock">
 	<div class="label"><slot name="label"></slot></div>
 	<div class="main _formRoot">
 		<slot></slot>
@@ -17,6 +17,7 @@ export default defineComponent({
 <style lang="scss" scoped>
 .adfeebaf {
 	padding: 24px 24px;
+	border: solid 1px var(--divider);
 	border-radius: var(--radius);
 
 	> .label {
diff --git a/packages/client/src/components/form/radio.vue b/packages/client/src/components/form/radio.vue
index f0b8c7137..2becbec6f 100644
--- a/packages/client/src/components/form/radio.vue
+++ b/packages/client/src/components/form/radio.vue
@@ -1,6 +1,6 @@
 <template>
 <div
-	v-panel
+	v-adaptive-border
 	class="novjtctn"
 	:class="{ disabled, checked }"
 	:aria-checked="checked"
@@ -53,7 +53,10 @@ export default defineComponent({
 	display: inline-block;
 	text-align: left;
 	cursor: pointer;
-	padding: 11px 14px;
+	padding: 10px 12px;
+	background-color: var(--panel);
+	background-clip: padding-box !important;
+	border: solid 1px var(--panel);
 	border-radius: 6px;
 	transition: all 0.3s;
 
@@ -69,9 +72,13 @@ export default defineComponent({
 		}
 	}
 
+	&:hover {
+		border-color: var(--inputBorderHover) !important;
+	}
+
 	&.checked {
-		background: var(--accentedBg) !important;
-		border-color: var(--accent);
+		background-color: var(--accentedBg) !important;
+		border-color: var(--accentedBg) !important;
 		color: var(--accent);
 
 		&, * {
@@ -89,11 +96,6 @@ export default defineComponent({
 		}
 	}
 
-	&:hover {
-		border-color: var(--inputBorderHover);
-		color: var(--accent);
-	}
-
 	> input {
 		position: absolute;
 		width: 0;
diff --git a/packages/client/src/init.ts b/packages/client/src/init.ts
index 131ea0cf8..2263b4ca3 100644
--- a/packages/client/src/init.ts
+++ b/packages/client/src/init.ts
@@ -13,8 +13,6 @@ if (localStorage.getItem('accounts') != null) {
 }
 //#endregion
 
-import * as Sentry from '@sentry/browser';
-import { Integrations } from '@sentry/tracing';
 import { computed, createApp, watch, markRaw, version as vueVersion } from 'vue';
 import * as compareVersions from 'compare-versions';
 
@@ -74,18 +72,6 @@ if (_DEV_) {
 	});
 }
 
-if (defaultStore.state.reportError && !_DEV_) {
-	Sentry.init({
-		dsn: 'https://fd273254a07a4b61857607a9ea05d629@o501808.ingest.sentry.io/5583438',
-		tracesSampleRate: 1.0,
-	});
-
-	Sentry.setTag('misskey_version', version);
-	Sentry.setTag('ui', ui);
-	Sentry.setTag('lang', lang);
-	Sentry.setTag('host', host);
-}
-
 // タッチデバイスでCSSの:hoverを機能させる
 document.addEventListener('touchend', () => {}, { passive: true });
 
diff --git a/packages/client/src/os.ts b/packages/client/src/os.ts
index 1ea205d5c..d9400103f 100644
--- a/packages/client/src/os.ts
+++ b/packages/client/src/os.ts
@@ -4,7 +4,6 @@ import { Component, defineAsyncComponent, markRaw, reactive, Ref, ref } from 'vu
 import { EventEmitter } from 'eventemitter3';
 import insertTextAtCursor from 'insert-text-at-cursor';
 import * as Misskey from 'misskey-js';
-import * as Sentry from '@sentry/browser';
 import { apiUrl, debug, url } from '@/config';
 import MkPostFormDialog from '@/components/post-form-dialog.vue';
 import MkWaitingDialog from '@/components/waiting-dialog.vue';
@@ -70,19 +69,6 @@ export const api = ((endpoint: string, data: Record<string, any> = {}, token?: s
 					log!.res = markRaw(body.error);
 					log!.state = 'failed';
 				}
-
-				if (defaultStore.state.reportError && !_DEV_) {
-					Sentry.withScope((scope) => {
-						scope.setTag('api_endpoint', endpoint);
-						scope.setContext('api params', data);
-						scope.setContext('api error info', body.info);
-						scope.setTag('api_error_id', body.id);
-						scope.setTag('api_error_code', body.code);
-						scope.setTag('api_error_kind', body.kind);
-						scope.setLevel(Sentry.Severity.Error);
-						Sentry.captureMessage('API error');
-					});
-				}
 			}
 		}).catch(reject);
 	});
diff --git a/packages/client/src/pages/admin/index.vue b/packages/client/src/pages/admin/index.vue
index 56b6b25a7..935b785b0 100644
--- a/packages/client/src/pages/admin/index.vue
+++ b/packages/client/src/pages/admin/index.vue
@@ -29,9 +29,6 @@
 import { computed, defineAsyncComponent, defineComponent, isRef, nextTick, onMounted, reactive, ref, watch } from 'vue';
 import { i18n } from '@/i18n';
 import MkSuperMenu from '@/components/ui/super-menu.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormButton from '@/components/debobigego/button.vue';
 import MkInfo from '@/components/ui/info.vue';
 import { scroll } from '@/scripts/scroll';
 import { instance } from '@/instance';
@@ -41,10 +38,7 @@ import { lookupUser } from '@/scripts/lookup-user';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		MkSuperMenu,
-		FormGroup,
-		FormButton,
 		MkInfo,
 	},
 
diff --git a/packages/client/src/pages/admin/overview.vue b/packages/client/src/pages/admin/overview.vue
index 59a428159..3dcfce01e 100644
--- a/packages/client/src/pages/admin/overview.vue
+++ b/packages/client/src/pages/admin/overview.vue
@@ -67,7 +67,6 @@
 
 <script lang="ts">
 import { computed, defineComponent, markRaw, version as vueVersion } from 'vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
 import MkInstanceStats from '@/components/instance-stats.vue';
 import MkButton from '@/components/ui/button.vue';
 import MkSelect from '@/components/form/select.vue';
@@ -87,7 +86,6 @@ import * as symbols from '@/symbols';
 export default defineComponent({
 	components: {
 		MkNumberDiff,
-		FormKeyValueView,
 		MkInstanceStats,
 		MkContainer,
 		MkFolder,
diff --git a/packages/client/src/pages/reset-password.vue b/packages/client/src/pages/reset-password.vue
index f9a250084..e0608654c 100644
--- a/packages/client/src/pages/reset-password.vue
+++ b/packages/client/src/pages/reset-password.vue
@@ -1,29 +1,25 @@
 <template>
-<FormBase v-if="token">
-	<FormInput v-model="password" type="password">
-		<template #prefix><i class="fas fa-lock"></i></template>
-		<span>{{ $ts.newPassword }}</span>
-	</FormInput>
-	
-	<FormButton primary @click="save">{{ $ts.save }}</FormButton>
-</FormBase>
+<MkSpacer v-if="token" :content-max="700" :margin-min="16" :margin-max="32">
+	<div class="_formRoot">
+		<FormInput v-model="password" type="password" class="_formBlock">
+			<template #prefix><i class="fas fa-lock"></i></template>
+			<template #label>{{ $ts.newPassword }}</template>
+		</FormInput>
+		
+		<FormButton primary class="_formBlock" @click="save">{{ $ts.save }}</FormButton>
+	</div>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
+import FormInput from '@/components/form/input.vue';
+import FormButton from '@/components/ui/button.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
-		FormGroup,
-		FormLink,
 		FormInput,
 		FormButton,
 	},
@@ -39,7 +35,8 @@ export default defineComponent({
 		return {
 			[symbols.PAGE_INFO]: {
 				title: this.$ts.resetPassword,
-				icon: 'fas fa-lock'
+				icon: 'fas fa-lock',
+				bg: 'var(--bg)',
 			},
 			password: '',
 		}
diff --git a/packages/client/src/pages/settings/2fa.vue b/packages/client/src/pages/settings/2fa.vue
index cffd10a0e..10599d99f 100644
--- a/packages/client/src/pages/settings/2fa.vue
+++ b/packages/client/src/pages/settings/2fa.vue
@@ -71,9 +71,6 @@ import MkButton from '@/components/ui/button.vue';
 import MkInfo from '@/components/ui/info.vue';
 import MkInput from '@/components/form/input.vue';
 import MkSwitch from '@/components/form/switch.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 
diff --git a/packages/client/src/pages/settings/email.vue b/packages/client/src/pages/settings/email.vue
index b04295cce..e9010fbe4 100644
--- a/packages/client/src/pages/settings/email.vue
+++ b/packages/client/src/pages/settings/email.vue
@@ -41,8 +41,6 @@
 
 <script lang="ts">
 import { defineComponent, onMounted, ref, watch } from 'vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormLink from '@/components/debobigego/link.vue';
 import FormSection from '@/components/form/section.vue';
 import FormInput from '@/components/form/input.vue';
 import FormSwitch from '@/components/form/switch.vue';
@@ -54,8 +52,6 @@ import { i18n } from '@/i18n';
 export default defineComponent({
 	components: {
 		FormSection,
-		FormLink,
-		FormButton,
 		FormSwitch,
 		FormInput,
 	},
diff --git a/packages/client/src/pages/settings/experimental-features.vue b/packages/client/src/pages/settings/experimental-features.vue
deleted file mode 100644
index 5a7bcb3b4..000000000
--- a/packages/client/src/pages/settings/experimental-features.vue
+++ /dev/null
@@ -1,52 +0,0 @@
-<template>
-<FormBase>
-	<FormButton @click="error()">error test</FormButton>
-</FormBase>
-</template>
-
-<script lang="ts">
-import { defineAsyncComponent, defineComponent } from 'vue';
-import FormSwitch from '@/components/form/switch.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import * as os from '@/os';
-import * as symbols from '@/symbols';
-
-export default defineComponent({
-	components: {
-		FormBase,
-		FormSelect,
-		FormSwitch,
-		FormButton,
-		FormLink,
-		FormGroup,
-		FormKeyValueView,
-	},
-
-	emits: ['info'],
-	
-	data() {
-		return {
-			[symbols.PAGE_INFO]: {
-				title: this.$ts.experimentalFeatures,
-				icon: 'fas fa-flask'
-			},
-			stats: null
-		}
-	},
-
-	mounted() {
-		this.$emit('info', this[symbols.PAGE_INFO]);
-	},
-
-	methods: {
-		error() {
-			throw new Error('Test error');
-		}
-	}
-});
-</script>
diff --git a/packages/client/src/pages/settings/index.vue b/packages/client/src/pages/settings/index.vue
index 8ffff8670..fa135c417 100644
--- a/packages/client/src/pages/settings/index.vue
+++ b/packages/client/src/pages/settings/index.vue
@@ -218,10 +218,8 @@ export default defineComponent({
 				case 'plugin/manage': return defineAsyncComponent(() => import('./plugin.manage.vue'));
 				case 'import-export': return defineAsyncComponent(() => import('./import-export.vue'));
 				case 'account-info': return defineAsyncComponent(() => import('./account-info.vue'));
-				case 'update': return defineAsyncComponent(() => import('./update.vue'));
 				case 'registry': return defineAsyncComponent(() => import('./registry.vue'));
 				case 'delete-account': return defineAsyncComponent(() => import('./delete-account.vue'));
-				case 'experimental-features': return defineAsyncComponent(() => import('./experimental-features.vue'));
 			}
 			if (page.value.startsWith('registry/keys/system/')) {
 				return defineAsyncComponent(() => import('./registry.keys.vue'));
diff --git a/packages/client/src/pages/settings/other.vue b/packages/client/src/pages/settings/other.vue
index 0d9e60e21..5e45abf6e 100644
--- a/packages/client/src/pages/settings/other.vue
+++ b/packages/client/src/pages/settings/other.vue
@@ -1,7 +1,5 @@
 <template>
 <div class="_formRoot">
-	<FormLink to="/settings/update" class="_formBlock">Misskey Update</FormLink>
-
 	<FormSwitch :value="$i.injectFeaturedNote" @update:modelValue="onChangeInjectFeaturedNote" class="_formBlock">
 		{{ $ts.showFeaturedNotesInTimeline }}
 	</FormSwitch>
@@ -9,7 +7,6 @@
 	<FormSwitch v-model="reportError" class="_formBlock">{{ $ts.sendErrorReports }}<template #desc>{{ $ts.sendErrorReportsDescription }}</template></FormSwitch>
 
 	<FormLink to="/settings/account-info" class="_formBlock">{{ $ts.accountInfo }}</FormLink>
-	<FormLink to="/settings/experimental-features" class="_formBlock">{{ $ts.experimentalFeatures }}</FormLink>
 
 	<FormSection>
 		<template #label>{{ $ts.developer }}</template>
diff --git a/packages/client/src/pages/settings/security.vue b/packages/client/src/pages/settings/security.vue
index 069f9d964..82a21d5b1 100644
--- a/packages/client/src/pages/settings/security.vue
+++ b/packages/client/src/pages/settings/security.vue
@@ -40,7 +40,6 @@
 <script lang="ts">
 import { defineComponent } from 'vue';
 import FormSection from '@/components/form/section.vue';
-import FormLink from '@/components/debobigego/link.vue';
 import FormSlot from '@/components/form/slot.vue';
 import FormButton from '@/components/ui/button.vue';
 import FormPagination from '@/components/form/pagination.vue';
@@ -51,7 +50,6 @@ import * as symbols from '@/symbols';
 export default defineComponent({
 	components: {
 		FormSection,
-		FormLink,
 		FormButton,
 		FormPagination,
 		FormSlot,
diff --git a/packages/client/src/pages/settings/theme.install.vue b/packages/client/src/pages/settings/theme.install.vue
index c3e531afb..52935c75d 100644
--- a/packages/client/src/pages/settings/theme.install.vue
+++ b/packages/client/src/pages/settings/theme.install.vue
@@ -1,40 +1,29 @@
 <template>
-<FormBase>
-	<FormGroup>
-		<FormTextarea v-model="installThemeCode">
-			<span>{{ $ts._theme.code }}</span>
-		</FormTextarea>
-		<FormButton :disabled="installThemeCode == null" inline @click="() => preview(installThemeCode)"><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton>
-	</FormGroup>
+<div class="_formRoot">
+	<FormTextarea v-model="installThemeCode" class="_formBlock">
+		<template #label>{{ $ts._theme.code }}</template>
+	</FormTextarea>
 
-	<FormButton :disabled="installThemeCode == null" primary inline @click="() => install(installThemeCode)"><i class="fas fa-check"></i> {{ $ts.install }}</FormButton>
-</FormBase>
+	<div class="_formBlock" style="display: flex; gap: var(--margin); flex-wrap: wrap;">
+		<FormButton :disabled="installThemeCode == null" inline @click="() => preview(installThemeCode)"><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton>
+		<FormButton :disabled="installThemeCode == null" primary inline @click="() => install(installThemeCode)"><i class="fas fa-check"></i> {{ $ts.install }}</FormButton>
+	</div>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
 import * as JSON5 from 'json5';
 import FormTextarea from '@/components/form/textarea.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormRadios from '@/components/form/radios.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormButton from '@/components/debobigego/button.vue';
+import FormButton from '@/components/ui/button.vue';
 import { applyTheme, validateTheme } from '@/scripts/theme';
 import * as os from '@/os';
-import { ColdDeviceStorage } from '@/store';
 import { addTheme, getThemes } from '@/theme-store';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
 		FormTextarea,
-		FormSelect,
-		FormRadios,
-		FormBase,
-		FormGroup,
-		FormLink,
 		FormButton,
 	},
 
diff --git a/packages/client/src/pages/settings/theme.manage.vue b/packages/client/src/pages/settings/theme.manage.vue
index c605b1eb6..a913ba474 100644
--- a/packages/client/src/pages/settings/theme.manage.vue
+++ b/packages/client/src/pages/settings/theme.manage.vue
@@ -30,9 +30,6 @@ import { defineComponent } from 'vue';
 import * as JSON5 from 'json5';
 import FormTextarea from '@/components/form/textarea.vue';
 import FormSelect from '@/components/form/select.vue';
-import FormRadios from '@/components/form/radios.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
 import FormInput from '@/components/form/input.vue';
 import FormButton from '@/components/ui/button.vue';
 import { Theme, builtinThemes } from '@/scripts/theme';
@@ -46,9 +43,6 @@ export default defineComponent({
 	components: {
 		FormTextarea,
 		FormSelect,
-		FormRadios,
-		FormBase,
-		FormGroup,
 		FormInput,
 		FormButton,
 	},
diff --git a/packages/client/src/pages/settings/update.vue b/packages/client/src/pages/settings/update.vue
deleted file mode 100644
index e0d8f6d15..000000000
--- a/packages/client/src/pages/settings/update.vue
+++ /dev/null
@@ -1,95 +0,0 @@
-<template>
-<FormBase>
-	<template v-if="meta">
-		<FormInfo v-if="version === meta.version">{{ $ts.youAreRunningUpToDateClient }}</FormInfo>
-		<FormInfo v-else warn>{{ $ts.newVersionOfClientAvailable }}</FormInfo>
-	</template>
-	<FormGroup>
-		<template #label>{{ instanceName }}</template>
-		<FormKeyValueView>
-			<template #key>{{ $ts.currentVersion }}</template>
-			<template #value>{{ version }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
-			<template #key>{{ $ts.latestVersion }}</template>
-			<template v-if="meta" #value>{{ meta.version }}</template>
-			<template v-else #value><MkEllipsis/></template>
-		</FormKeyValueView>
-	</FormGroup>
-	<FormGroup>
-		<template #label>Misskey</template>
-		<FormKeyValueView>
-			<template #key>{{ $ts.latestVersion }}</template>
-			<template v-if="releases" #value>{{ releases[0].tag_name }}</template>
-			<template v-else #value><MkEllipsis/></template>
-		</FormKeyValueView>
-		<template v-if="releases" #caption><MkTime :time="releases[0].published_at" mode="detail"/></template>
-	</FormGroup>
-</FormBase>
-</template>
-
-<script lang="ts">
-import { defineAsyncComponent, defineComponent } from 'vue';
-import FormSwitch from '@/components/form/switch.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import * as os from '@/os';
-import { version, instanceName } from '@/config';
-import * as symbols from '@/symbols';
-
-export default defineComponent({
-	components: {
-		FormBase,
-		FormSelect,
-		FormSwitch,
-		FormButton,
-		FormLink,
-		FormGroup,
-		FormKeyValueView,
-		FormInfo,
-	},
-
-	emits: ['info'],
-	
-	data() {
-		return {
-			[symbols.PAGE_INFO]: {
-				title: 'Misskey Update',
-				icon: 'fas fa-sync-alt',
-				bg: 'var(--bg)',
-			},
-			version,
-			instanceName,
-			releases: null,
-			meta: null
-		}
-	},
-
-	mounted() {
-		this.$emit('info', this[symbols.PAGE_INFO]);
-
-		os.api('meta', {
-			detail: false
-		}).then(meta => {
-			this.meta = meta;
-			localStorage.setItem('v', meta.version);
-		});
-
-		fetch('https://api.github.com/repos/misskey-dev/misskey/releases', {
-			method: 'GET',
-		})
-		.then(res => res.json())
-		.then(res => {
-			this.releases = res;
-		});
-	},
-
-	methods: {
-	}
-});
-</script>
diff --git a/packages/client/src/pages/settings/word-mute.vue b/packages/client/src/pages/settings/word-mute.vue
index 068f88740..34edd0492 100644
--- a/packages/client/src/pages/settings/word-mute.vue
+++ b/packages/client/src/pages/settings/word-mute.vue
@@ -31,7 +31,6 @@
 <script lang="ts">
 import { defineComponent } from 'vue';
 import FormTextarea from '@/components/form/textarea.vue';
-import FormBase from '@/components/debobigego/base.vue';
 import MkKeyValue from '@/components/key-value.vue';
 import MkButton from '@/components/ui/button.vue';
 import MkInfo from '@/components/ui/info.vue';
@@ -42,7 +41,6 @@ import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		MkButton,
 		FormTextarea,
 		MkKeyValue,
diff --git a/packages/client/yarn.lock b/packages/client/yarn.lock
index 1b9c9585e..80cf1fc98 100644
--- a/packages/client/yarn.lock
+++ b/packages/client/yarn.lock
@@ -202,69 +202,6 @@
     node-fetch "^2.6.1"
     yaml-ast-parser "0.0.43"
 
-"@sentry/browser@5.29.2":
-  version "5.29.2"
-  resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-5.29.2.tgz#51adb4005511b1a4a70e4571880fc6653d651f91"
-  integrity sha512-uxZ7y7rp85tJll+RZtXRhXPbnFnOaxZqJEv05vJlXBtBNLQtlczV5iCtU9mZRLVHDtmZ5VVKUV8IKXntEqqDpQ==
-  dependencies:
-    "@sentry/core" "5.29.2"
-    "@sentry/types" "5.29.2"
-    "@sentry/utils" "5.29.2"
-    tslib "^1.9.3"
-
-"@sentry/core@5.29.2":
-  version "5.29.2"
-  resolved "https://registry.yarnpkg.com/@sentry/core/-/core-5.29.2.tgz#9e05fe197234161d57aabaf52fab336a7c520d81"
-  integrity sha512-7WYkoxB5IdlNEbwOwqSU64erUKH4laavPsM0/yQ+jojM76ErxlgEF0u//p5WaLPRzh3iDSt6BH+9TL45oNZeZw==
-  dependencies:
-    "@sentry/hub" "5.29.2"
-    "@sentry/minimal" "5.29.2"
-    "@sentry/types" "5.29.2"
-    "@sentry/utils" "5.29.2"
-    tslib "^1.9.3"
-
-"@sentry/hub@5.29.2":
-  version "5.29.2"
-  resolved "https://registry.yarnpkg.com/@sentry/hub/-/hub-5.29.2.tgz#208f10fe6674695575ad74182a1151f71d6df00a"
-  integrity sha512-LaAIo2hwUk9ykeh9RF0cwLy6IRw+DjEee8l1HfEaDFUM6TPGlNNGObMJNXb9/95jzWp7jWwOpQjoIE3jepdQJQ==
-  dependencies:
-    "@sentry/types" "5.29.2"
-    "@sentry/utils" "5.29.2"
-    tslib "^1.9.3"
-
-"@sentry/minimal@5.29.2":
-  version "5.29.2"
-  resolved "https://registry.yarnpkg.com/@sentry/minimal/-/minimal-5.29.2.tgz#420bebac8d03d30980fdb05c72d7b253d8aa541b"
-  integrity sha512-0aINSm8fGA1KyM7PavOBe1GDZDxrvnKt+oFnU0L+bTcw8Lr+of+v6Kwd97rkLRNOLw621xP076dL/7LSIzMuhw==
-  dependencies:
-    "@sentry/hub" "5.29.2"
-    "@sentry/types" "5.29.2"
-    tslib "^1.9.3"
-
-"@sentry/tracing@5.29.2":
-  version "5.29.2"
-  resolved "https://registry.yarnpkg.com/@sentry/tracing/-/tracing-5.29.2.tgz#6012788547d2ab7893799d82c4941bda145dcd47"
-  integrity sha512-iumYbVRpvoU3BUuIooxibydeaOOjl5ysc+mzsqhRs2NGW/C3uKAsFXdvyNfqt3bxtRQwJEhwJByLP2u3pLThpw==
-  dependencies:
-    "@sentry/hub" "5.29.2"
-    "@sentry/minimal" "5.29.2"
-    "@sentry/types" "5.29.2"
-    "@sentry/utils" "5.29.2"
-    tslib "^1.9.3"
-
-"@sentry/types@5.29.2":
-  version "5.29.2"
-  resolved "https://registry.yarnpkg.com/@sentry/types/-/types-5.29.2.tgz#ac87383df1222c2d9b9f8f9ed7a6b86ea41a098a"
-  integrity sha512-dM9wgt8wy4WRty75QkqQgrw9FV9F+BOMfmc0iaX13Qos7i6Qs2Q0dxtJ83SoR4YGtW8URaHzlDtWlGs5egBiMA==
-
-"@sentry/utils@5.29.2":
-  version "5.29.2"
-  resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-5.29.2.tgz#99a5cdda2ea19d34a41932f138d470adcb3ee673"
-  integrity sha512-nEwQIDjtFkeE4k6yIk4Ka5XjGRklNLThWLs2xfXlL7uwrYOH2B9UBBOOIRUraBm/g/Xrra3xsam/kRxuiwtXZQ==
-  dependencies:
-    "@sentry/types" "5.29.2"
-    tslib "^1.9.3"
-
 "@sideway/address@^4.1.0":
   version "4.1.2"
   resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.2.tgz#811b84333a335739d3969cfc434736268170cad1"
@@ -5961,11 +5898,6 @@ tslib@^1.8.1, tslib@^1.9.0:
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35"
   integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA==
 
-tslib@^1.9.3:
-  version "1.14.1"
-  resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
-  integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
-
 tslib@~2.1.0:
   version "2.1.0"
   resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.1.0.tgz#da60860f1c2ecaa5703ab7d39bc05b6bf988b97a"

From 408142647cf7b48f1b7b5e9b5f4c47fc12eb9728 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 3 Jan 2022 00:41:01 +0900
Subject: [PATCH 02/19] tweak ui

---
 .../src/pages/settings/delete-account.vue     |  20 +--
 packages/client/src/pages/settings/index.vue  |  18 ---
 packages/client/src/pages/settings/other.vue  |  21 +--
 .../src/pages/settings/registry.keys.vue      | 114 --------------
 .../src/pages/settings/registry.value.vue     | 147 ------------------
 .../client/src/pages/settings/registry.vue    |  90 -----------
 6 files changed, 8 insertions(+), 402 deletions(-)
 delete mode 100644 packages/client/src/pages/settings/registry.keys.vue
 delete mode 100644 packages/client/src/pages/settings/registry.value.vue
 delete mode 100644 packages/client/src/pages/settings/registry.vue

diff --git a/packages/client/src/pages/settings/delete-account.vue b/packages/client/src/pages/settings/delete-account.vue
index 6ce8d6509..17501d951 100644
--- a/packages/client/src/pages/settings/delete-account.vue
+++ b/packages/client/src/pages/settings/delete-account.vue
@@ -1,28 +1,23 @@
 <template>
-<FormBase>
-	<FormInfo warn>{{ $ts._accountDelete.mayTakeTime }}</FormInfo>
-	<FormInfo>{{ $ts._accountDelete.sendEmail }}</FormInfo>
-	<FormButton v-if="!$i.isDeleted" danger @click="deleteAccount">{{ $ts._accountDelete.requestAccountDelete }}</FormButton>
+<div class="_formRoot">
+	<FormInfo warn class="_formBlock">{{ $ts._accountDelete.mayTakeTime }}</FormInfo>
+	<FormInfo class="_formBlock">{{ $ts._accountDelete.sendEmail }}</FormInfo>
+	<FormButton v-if="!$i.isDeleted" danger class="_formBlock" @click="deleteAccount">{{ $ts._accountDelete.requestAccountDelete }}</FormButton>
 	<FormButton v-else disabled>{{ $ts._accountDelete.inProgress }}</FormButton>
-</FormBase>
+</div>
 </template>
 
 <script lang="ts">
 import { defineAsyncComponent, defineComponent } from 'vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
+import FormInfo from '@/components/ui/info.vue';
+import FormButton from '@/components/ui/button.vue';
 import * as os from '@/os';
-import { debug } from '@/config';
 import { signout } from '@/account';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		FormButton,
-		FormGroup,
 		FormInfo,
 	},
 
@@ -35,7 +30,6 @@ export default defineComponent({
 				icon: 'fas fa-exclamation-triangle',
 				bg: 'var(--bg)',
 			},
-			debug,
 		}
 	},
 
diff --git a/packages/client/src/pages/settings/index.vue b/packages/client/src/pages/settings/index.vue
index fa135c417..60ed21786 100644
--- a/packages/client/src/pages/settings/index.vue
+++ b/packages/client/src/pages/settings/index.vue
@@ -218,32 +218,14 @@ export default defineComponent({
 				case 'plugin/manage': return defineAsyncComponent(() => import('./plugin.manage.vue'));
 				case 'import-export': return defineAsyncComponent(() => import('./import-export.vue'));
 				case 'account-info': return defineAsyncComponent(() => import('./account-info.vue'));
-				case 'registry': return defineAsyncComponent(() => import('./registry.vue'));
 				case 'delete-account': return defineAsyncComponent(() => import('./delete-account.vue'));
 			}
-			if (page.value.startsWith('registry/keys/system/')) {
-				return defineAsyncComponent(() => import('./registry.keys.vue'));
-			}
-			if (page.value.startsWith('registry/value/system/')) {
-				return defineAsyncComponent(() => import('./registry.value.vue'));
-			}
 			return null;
 		});
 
 		watch(component, () => {
 			pageProps.value = {};
 
-			if (page.value) {
-				if (page.value.startsWith('registry/keys/system/')) {
-					pageProps.value.scope = page.value.replace('registry/keys/system/', '').split('/');
-				}
-				if (page.value.startsWith('registry/value/system/')) {
-					const path = page.value.replace('registry/value/system/', '').split('/');
-					pageProps.value.xKey = path.pop();
-					pageProps.value.scope = path;
-				}
-			}
-
 			nextTick(() => {
 				scroll(el.value, { top: 0 });
 			});
diff --git a/packages/client/src/pages/settings/other.vue b/packages/client/src/pages/settings/other.vue
index 5e45abf6e..b941c07c6 100644
--- a/packages/client/src/pages/settings/other.vue
+++ b/packages/client/src/pages/settings/other.vue
@@ -8,21 +8,6 @@
 
 	<FormLink to="/settings/account-info" class="_formBlock">{{ $ts.accountInfo }}</FormLink>
 
-	<FormSection>
-		<template #label>{{ $ts.developer }}</template>
-		<FormSwitch v-model="debug" @update:modelValue="changeDebug" class="_formBlock">
-			DEBUG MODE
-		</FormSwitch>
-		<template v-if="debug">
-			<FormButton @click="taskmanager">Task Manager</FormButton>
-		</template>
-	</FormSection>
-
-	<FormLink to="/settings/registry" class="_formBlock"><template #icon><i class="fas fa-cogs"></i></template>{{ $ts.registry }}</FormLink>
-
-	<FormLink to="/bios" behavior="browser" class="_formBlock"><template #icon><i class="fas fa-door-open"></i></template>BIOS</FormLink>
-	<FormLink to="/cli" behavior="browser" class="_formBlock"><template #icon><i class="fas fa-door-open"></i></template>CLI</FormLink>
-
 	<FormLink to="/settings/delete-account" class="_formBlock"><template #icon><i class="fas fa-exclamation-triangle"></i></template>{{ $ts.closeAccount }}</FormLink>
 </div>
 </template>
@@ -30,10 +15,8 @@
 <script lang="ts">
 import { defineAsyncComponent, defineComponent } from 'vue';
 import FormSwitch from '@/components/form/switch.vue';
-import FormSelect from '@/components/form/select.vue';
 import FormSection from '@/components/form/section.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormButton from '@/components/debobigego/button.vue';
+import FormLink from '@/components/form/link.vue';
 import * as os from '@/os';
 import { debug } from '@/config';
 import { defaultStore } from '@/store';
@@ -42,10 +25,8 @@ import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormSelect,
 		FormSection,
 		FormSwitch,
-		FormButton,
 		FormLink,
 	},
 
diff --git a/packages/client/src/pages/settings/registry.keys.vue b/packages/client/src/pages/settings/registry.keys.vue
deleted file mode 100644
index 89953ebea..000000000
--- a/packages/client/src/pages/settings/registry.keys.vue
+++ /dev/null
@@ -1,114 +0,0 @@
-<template>
-<FormBase>
-	<FormGroup>
-		<FormKeyValueView>
-			<template #key>{{ $ts._registry.domain }}</template>
-			<template #value>{{ $ts.system }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
-			<template #key>{{ $ts._registry.scope }}</template>
-			<template #value>{{ scope.join('/') }}</template>
-		</FormKeyValueView>
-	</FormGroup>
-	
-	<FormGroup v-if="keys">
-		<template #label>{{ $ts._registry.keys }}</template>
-		<FormLink v-for="key in keys" :to="`/settings/registry/value/system/${scope.join('/')}/${key[0]}`" class="_monospace">{{ key[0] }}<template #suffix>{{ key[1].toUpperCase() }}</template></FormLink>
-	</FormGroup>
-
-	<FormButton primary @click="createKey">{{ $ts._registry.createKey }}</FormButton>
-</FormBase>
-</template>
-
-<script lang="ts">
-import { defineAsyncComponent, defineComponent } from 'vue';
-import * as JSON5 from 'json5';
-import FormSwitch from '@/components/form/switch.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import * as os from '@/os';
-import * as symbols from '@/symbols';
-
-export default defineComponent({
-	components: {
-		FormBase,
-		FormSelect,
-		FormSwitch,
-		FormButton,
-		FormLink,
-		FormGroup,
-		FormKeyValueView,
-	},
-
-	props: {
-		scope: {
-			required: true
-		}
-	},
-
-	emits: ['info'],
-	
-	data() {
-		return {
-			[symbols.PAGE_INFO]: {
-				title: this.$ts.registry,
-				icon: 'fas fa-cogs',
-				bg: 'var(--bg)',
-			},
-			keys: null,
-		}
-	},
-
-	watch: {
-		scope() {
-			this.fetch();
-		}
-	},
-
-	mounted() {
-		this.$emit('info', this[symbols.PAGE_INFO]);
-		this.fetch();
-	},
-
-	methods: {
-		fetch() {
-			os.api('i/registry/keys-with-type', {
-				scope: this.scope
-			}).then(keys => {
-				this.keys = Object.entries(keys).sort((a, b) => a[0].localeCompare(b[0]));
-			});
-		},
-
-		async createKey() {
-			const { canceled, result } = await os.form(this.$ts._registry.createKey, {
-				key: {
-					type: 'string',
-					label: this.$ts._registry.key,
-				},
-				value: {
-					type: 'string',
-					multiline: true,
-					label: this.$ts.value,
-				},
-				scope: {
-					type: 'string',
-					label: this.$ts._registry.scope,
-					default: this.scope.join('/')
-				}
-			});
-			if (canceled) return;
-			os.apiWithDialog('i/registry/set', {
-				scope: result.scope.split('/'),
-				key: result.key,
-				value: JSON5.parse(result.value),
-			}).then(() => {
-				this.fetch();
-			});
-		}
-	}
-});
-</script>
diff --git a/packages/client/src/pages/settings/registry.value.vue b/packages/client/src/pages/settings/registry.value.vue
deleted file mode 100644
index 6acd3f604..000000000
--- a/packages/client/src/pages/settings/registry.value.vue
+++ /dev/null
@@ -1,147 +0,0 @@
-<template>
-<FormBase>
-	<FormInfo warn>{{ $ts.editTheseSettingsMayBreakAccount }}</FormInfo>
-
-	<template v-if="value">
-		<FormGroup>
-			<FormKeyValueView>
-				<template #key>{{ $ts._registry.domain }}</template>
-				<template #value>{{ $ts.system }}</template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>{{ $ts._registry.scope }}</template>
-				<template #value>{{ scope.join('/') }}</template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>{{ $ts._registry.key }}</template>
-				<template #value>{{ xKey }}</template>
-			</FormKeyValueView>
-		</FormGroup>
-
-		<FormGroup>
-			<FormTextarea v-model="valueForEditor" tall class="_monospace" style="tab-size: 2;">
-				<span>{{ $ts.value }} (JSON)</span>
-			</FormTextarea>
-			<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
-		</FormGroup>
-
-		<FormKeyValueView>
-			<template #key>{{ $ts.updatedAt }}</template>
-			<template #value><MkTime :time="value.updatedAt" mode="detail"/></template>
-		</FormKeyValueView>
-
-		<FormButton danger @click="del"><i class="fas fa-trash"></i> {{ $ts.delete }}</FormButton>
-	</template>
-</FormBase>
-</template>
-
-<script lang="ts">
-import { defineAsyncComponent, defineComponent } from 'vue';
-import * as JSON5 from 'json5';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormSwitch from '@/components/form/switch.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormTextarea from '@/components/form/textarea.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import * as os from '@/os';
-import * as symbols from '@/symbols';
-
-export default defineComponent({
-	components: {
-		FormInfo,
-		FormBase,
-		FormSelect,
-		FormSwitch,
-		FormButton,
-		FormTextarea,
-		FormGroup,
-		FormKeyValueView,
-	},
-
-	props: {
-		scope: {
-			required: true
-		},
-		xKey: {
-			required: true
-		},
-	},
-
-	emits: ['info'],
-	
-	data() {
-		return {
-			[symbols.PAGE_INFO]: {
-				title: this.$ts.registry,
-				icon: 'fas fa-cogs',
-				bg: 'var(--bg)',
-			},
-			value: null,
-			valueForEditor: null,
-		}
-	},
-
-	watch: {
-		key() {
-			this.fetch();
-		},
-	},
-
-	mounted() {
-		this.$emit('info', this[symbols.PAGE_INFO]);
-		this.fetch();
-	},
-
-	methods: {
-		fetch() {
-			os.api('i/registry/get-detail', {
-				scope: this.scope,
-				key: this.xKey
-			}).then(value => {
-				this.value = value;
-				this.valueForEditor = JSON5.stringify(this.value.value, null, '\t');
-			});
-		},
-
-		save() {
-			try {
-				JSON5.parse(this.valueForEditor);
-			} catch (e) {
-				os.alert({
-					type: 'error',
-					text: this.$ts.invalidValue
-				});
-				return;
-			}
-
-			os.confirm({
-				type: 'warning',
-				text: this.$ts.saveConfirm,
-			}).then(({ canceled }) => {
-				if (canceled) return;
-				os.apiWithDialog('i/registry/set', {
-					scope: this.scope,
-					key: this.xKey,
-					value: JSON5.parse(this.valueForEditor)
-				});
-			});
-		},
-
-		del() {
-			os.confirm({
-				type: 'warning',
-				text: this.$ts.deleteConfirm,
-			}).then(({ canceled }) => {
-				if (canceled) return;
-				os.apiWithDialog('i/registry/remove', {
-					scope: this.scope,
-					key: this.xKey
-				});
-			});
-		}
-	}
-});
-</script>
diff --git a/packages/client/src/pages/settings/registry.vue b/packages/client/src/pages/settings/registry.vue
deleted file mode 100644
index 6faff5d2a..000000000
--- a/packages/client/src/pages/settings/registry.vue
+++ /dev/null
@@ -1,90 +0,0 @@
-<template>
-<FormBase>
-	<FormGroup v-if="scopes">
-		<template #label>{{ $ts.system }}</template>
-		<FormLink v-for="scope in scopes" :to="`/settings/registry/keys/system/${scope.join('/')}`" class="_monospace">{{ scope.join('/') }}</FormLink>
-	</FormGroup>
-	<FormButton primary @click="createKey">{{ $ts._registry.createKey }}</FormButton>
-</FormBase>
-</template>
-
-<script lang="ts">
-import { defineAsyncComponent, defineComponent } from 'vue';
-import * as JSON5 from 'json5';
-import FormSwitch from '@/components/form/switch.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import * as os from '@/os';
-import * as symbols from '@/symbols';
-
-export default defineComponent({
-	components: {
-		FormBase,
-		FormSelect,
-		FormSwitch,
-		FormButton,
-		FormLink,
-		FormGroup,
-		FormKeyValueView,
-	},
-
-	emits: ['info'],
-	
-	data() {
-		return {
-			[symbols.PAGE_INFO]: {
-				title: this.$ts.registry,
-				icon: 'fas fa-cogs',
-				bg: 'var(--bg)',
-			},
-			scopes: null,
-		}
-	},
-
-	created() {
-		this.fetch();
-	},
-
-	mounted() {
-		this.$emit('info', this[symbols.PAGE_INFO]);
-	},
-
-	methods: {
-		fetch() {
-			os.api('i/registry/scopes').then(scopes => {
-				this.scopes = scopes.slice().sort((a, b) => a.join('/').localeCompare(b.join('/')));
-			});
-		},
-
-		async createKey() {
-			const { canceled, result } = await os.form(this.$ts._registry.createKey, {
-				key: {
-					type: 'string',
-					label: this.$ts._registry.key,
-				},
-				value: {
-					type: 'string',
-					multiline: true,
-					label: this.$ts.value,
-				},
-				scope: {
-					type: 'string',
-					label: this.$ts._registry.scope,
-				}
-			});
-			if (canceled) return;
-			os.apiWithDialog('i/registry/set', {
-				scope: result.scope.split('/'),
-				key: result.key,
-				value: JSON5.parse(result.value),
-			}).then(() => {
-				this.fetch();
-			});
-		}
-	}
-});
-</script>

From 4a64280a7c8723fc9e15b7411e1e404d4054af78 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 3 Jan 2022 02:12:50 +0900
Subject: [PATCH 03/19] lint

---
 .../backend/src/server/api/endpoints/admin/abuse-user-reports.ts | 1 +
 .../backend/src/server/api/endpoints/admin/accounts/create.ts    | 1 +
 .../backend/src/server/api/endpoints/admin/accounts/delete.ts    | 1 +
 packages/backend/src/server/api/endpoints/admin/ad/create.ts     | 1 +
 packages/backend/src/server/api/endpoints/admin/ad/delete.ts     | 1 +
 packages/backend/src/server/api/endpoints/admin/ad/list.ts       | 1 +
 packages/backend/src/server/api/endpoints/admin/ad/update.ts     | 1 +
 .../src/server/api/endpoints/admin/announcements/create.ts       | 1 +
 .../src/server/api/endpoints/admin/announcements/delete.ts       | 1 +
 .../backend/src/server/api/endpoints/admin/announcements/list.ts | 1 +
 .../src/server/api/endpoints/admin/announcements/update.ts       | 1 +
 .../src/server/api/endpoints/admin/delete-all-files-of-a-user.ts | 1 +
 packages/backend/src/server/api/endpoints/admin/delete-logs.ts   | 1 +
 .../src/server/api/endpoints/admin/drive/clean-remote-files.ts   | 1 +
 packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts | 1 +
 packages/backend/src/server/api/endpoints/admin/drive/files.ts   | 1 +
 .../backend/src/server/api/endpoints/admin/drive/show-file.ts    | 1 +
 packages/backend/src/server/api/endpoints/admin/emoji/add.ts     | 1 +
 packages/backend/src/server/api/endpoints/admin/emoji/copy.ts    | 1 +
 .../backend/src/server/api/endpoints/admin/emoji/list-remote.ts  | 1 +
 packages/backend/src/server/api/endpoints/admin/emoji/list.ts    | 1 +
 packages/backend/src/server/api/endpoints/admin/emoji/remove.ts  | 1 +
 packages/backend/src/server/api/endpoints/admin/emoji/update.ts  | 1 +
 .../server/api/endpoints/admin/federation/delete-all-files.ts    | 1 +
 .../admin/federation/refresh-remote-instance-metadata.ts         | 1 +
 .../api/endpoints/admin/federation/remove-all-following.ts       | 1 +
 .../src/server/api/endpoints/admin/federation/update-instance.ts | 1 +
 .../backend/src/server/api/endpoints/admin/get-index-stats.ts    | 1 +
 .../backend/src/server/api/endpoints/admin/get-table-stats.ts    | 1 +
 packages/backend/src/server/api/endpoints/admin/invite.ts        | 1 +
 .../backend/src/server/api/endpoints/admin/moderators/add.ts     | 1 +
 .../backend/src/server/api/endpoints/admin/moderators/remove.ts  | 1 +
 packages/backend/src/server/api/endpoints/admin/promo/create.ts  | 1 +
 packages/backend/src/server/api/endpoints/admin/queue/clear.ts   | 1 +
 .../src/server/api/endpoints/admin/queue/deliver-delayed.ts      | 1 +
 .../src/server/api/endpoints/admin/queue/inbox-delayed.ts        | 1 +
 packages/backend/src/server/api/endpoints/admin/queue/jobs.ts    | 1 +
 packages/backend/src/server/api/endpoints/admin/queue/stats.ts   | 1 +
 packages/backend/src/server/api/endpoints/admin/relays/add.ts    | 1 +
 packages/backend/src/server/api/endpoints/admin/relays/list.ts   | 1 +
 packages/backend/src/server/api/endpoints/admin/relays/remove.ts | 1 +
 .../backend/src/server/api/endpoints/admin/reset-password.ts     | 1 +
 .../src/server/api/endpoints/admin/resolve-abuse-user-report.ts  | 1 +
 packages/backend/src/server/api/endpoints/admin/resync-chart.ts  | 1 +
 packages/backend/src/server/api/endpoints/admin/send-email.ts    | 1 +
 packages/backend/src/server/api/endpoints/admin/server-info.ts   | 1 +
 .../src/server/api/endpoints/admin/show-moderation-logs.ts       | 1 +
 packages/backend/src/server/api/endpoints/admin/show-user.ts     | 1 +
 packages/backend/src/server/api/endpoints/admin/show-users.ts    | 1 +
 packages/backend/src/server/api/endpoints/admin/silence-user.ts  | 1 +
 packages/backend/src/server/api/endpoints/admin/suspend-user.ts  | 1 +
 .../backend/src/server/api/endpoints/admin/unsilence-user.ts     | 1 +
 .../backend/src/server/api/endpoints/admin/unsuspend-user.ts     | 1 +
 packages/backend/src/server/api/endpoints/admin/update-meta.ts   | 1 +
 packages/backend/src/server/api/endpoints/admin/vacuum.ts        | 1 +
 packages/backend/src/server/api/endpoints/announcements.ts       | 1 +
 packages/backend/src/server/api/endpoints/antennas/create.ts     | 1 +
 packages/backend/src/server/api/endpoints/antennas/delete.ts     | 1 +
 packages/backend/src/server/api/endpoints/antennas/list.ts       | 1 +
 packages/backend/src/server/api/endpoints/antennas/notes.ts      | 1 +
 packages/backend/src/server/api/endpoints/antennas/show.ts       | 1 +
 packages/backend/src/server/api/endpoints/antennas/update.ts     | 1 +
 packages/backend/src/server/api/endpoints/ap/get.ts              | 1 +
 packages/backend/src/server/api/endpoints/ap/show.ts             | 1 +
 packages/backend/src/server/api/endpoints/app/create.ts          | 1 +
 packages/backend/src/server/api/endpoints/app/show.ts            | 1 +
 packages/backend/src/server/api/endpoints/auth/accept.ts         | 1 +
 .../backend/src/server/api/endpoints/auth/session/generate.ts    | 1 +
 packages/backend/src/server/api/endpoints/auth/session/show.ts   | 1 +
 .../backend/src/server/api/endpoints/auth/session/userkey.ts     | 1 +
 packages/backend/src/server/api/endpoints/blocking/create.ts     | 1 +
 packages/backend/src/server/api/endpoints/blocking/delete.ts     | 1 +
 packages/backend/src/server/api/endpoints/blocking/list.ts       | 1 +
 packages/backend/src/server/api/endpoints/channels/create.ts     | 1 +
 packages/backend/src/server/api/endpoints/channels/featured.ts   | 1 +
 packages/backend/src/server/api/endpoints/channels/follow.ts     | 1 +
 packages/backend/src/server/api/endpoints/channels/followed.ts   | 1 +
 packages/backend/src/server/api/endpoints/channels/owned.ts      | 1 +
 packages/backend/src/server/api/endpoints/channels/show.ts       | 1 +
 packages/backend/src/server/api/endpoints/channels/timeline.ts   | 1 +
 packages/backend/src/server/api/endpoints/channels/unfollow.ts   | 1 +
 packages/backend/src/server/api/endpoints/channels/update.ts     | 1 +
 packages/backend/src/server/api/endpoints/charts/active-users.ts | 1 +
 packages/backend/src/server/api/endpoints/charts/drive.ts        | 1 +
 packages/backend/src/server/api/endpoints/charts/federation.ts   | 1 +
 packages/backend/src/server/api/endpoints/charts/hashtag.ts      | 1 +
 packages/backend/src/server/api/endpoints/charts/instance.ts     | 1 +
 packages/backend/src/server/api/endpoints/charts/network.ts      | 1 +
 packages/backend/src/server/api/endpoints/charts/notes.ts        | 1 +
 packages/backend/src/server/api/endpoints/charts/user/drive.ts   | 1 +
 .../backend/src/server/api/endpoints/charts/user/following.ts    | 1 +
 packages/backend/src/server/api/endpoints/charts/user/notes.ts   | 1 +
 .../backend/src/server/api/endpoints/charts/user/reactions.ts    | 1 +
 packages/backend/src/server/api/endpoints/charts/users.ts        | 1 +
 packages/backend/src/server/api/endpoints/clips/add-note.ts      | 1 +
 packages/backend/src/server/api/endpoints/clips/create.ts        | 1 +
 packages/backend/src/server/api/endpoints/clips/delete.ts        | 1 +
 packages/backend/src/server/api/endpoints/clips/list.ts          | 1 +
 packages/backend/src/server/api/endpoints/clips/notes.ts         | 1 +
 packages/backend/src/server/api/endpoints/clips/show.ts          | 1 +
 packages/backend/src/server/api/endpoints/clips/update.ts        | 1 +
 packages/backend/src/server/api/endpoints/drive.ts               | 1 +
 packages/backend/src/server/api/endpoints/drive/files.ts         | 1 +
 .../src/server/api/endpoints/drive/files/attached-notes.ts       | 1 +
 .../src/server/api/endpoints/drive/files/check-existence.ts      | 1 +
 packages/backend/src/server/api/endpoints/drive/files/create.ts  | 1 +
 packages/backend/src/server/api/endpoints/drive/files/delete.ts  | 1 +
 .../backend/src/server/api/endpoints/drive/files/find-by-hash.ts | 1 +
 packages/backend/src/server/api/endpoints/drive/files/find.ts    | 1 +
 packages/backend/src/server/api/endpoints/drive/files/show.ts    | 1 +
 packages/backend/src/server/api/endpoints/drive/files/update.ts  | 1 +
 .../src/server/api/endpoints/drive/files/upload-from-url.ts      | 1 +
 packages/backend/src/server/api/endpoints/drive/folders.ts       | 1 +
 .../backend/src/server/api/endpoints/drive/folders/create.ts     | 1 +
 .../backend/src/server/api/endpoints/drive/folders/delete.ts     | 1 +
 packages/backend/src/server/api/endpoints/drive/folders/find.ts  | 1 +
 packages/backend/src/server/api/endpoints/drive/folders/show.ts  | 1 +
 .../backend/src/server/api/endpoints/drive/folders/update.ts     | 1 +
 packages/backend/src/server/api/endpoints/drive/stream.ts        | 1 +
 .../backend/src/server/api/endpoints/email-address/available.ts  | 1 +
 packages/backend/src/server/api/endpoints/endpoint.ts            | 1 +
 packages/backend/src/server/api/endpoints/endpoints.ts           | 1 +
 .../backend/src/server/api/endpoints/export-custom-emojis.ts     | 1 +
 packages/backend/src/server/api/endpoints/federation/dns.ts      | 1 +
 .../backend/src/server/api/endpoints/federation/followers.ts     | 1 +
 .../backend/src/server/api/endpoints/federation/following.ts     | 1 +
 .../backend/src/server/api/endpoints/federation/instances.ts     | 1 +
 .../backend/src/server/api/endpoints/federation/show-instance.ts | 1 +
 .../src/server/api/endpoints/federation/update-remote-user.ts    | 1 +
 packages/backend/src/server/api/endpoints/federation/users.ts    | 1 +
 packages/backend/src/server/api/endpoints/following/create.ts    | 1 +
 packages/backend/src/server/api/endpoints/following/delete.ts    | 1 +
 .../backend/src/server/api/endpoints/following/invalidate.ts     | 1 +
 .../src/server/api/endpoints/following/requests/accept.ts        | 1 +
 .../src/server/api/endpoints/following/requests/cancel.ts        | 1 +
 .../backend/src/server/api/endpoints/following/requests/list.ts  | 1 +
 .../src/server/api/endpoints/following/requests/reject.ts        | 1 +
 packages/backend/src/server/api/endpoints/gallery/featured.ts    | 1 +
 packages/backend/src/server/api/endpoints/gallery/popular.ts     | 1 +
 packages/backend/src/server/api/endpoints/gallery/posts.ts       | 1 +
 .../backend/src/server/api/endpoints/gallery/posts/create.ts     | 1 +
 .../backend/src/server/api/endpoints/gallery/posts/delete.ts     | 1 +
 packages/backend/src/server/api/endpoints/gallery/posts/like.ts  | 1 +
 packages/backend/src/server/api/endpoints/gallery/posts/show.ts  | 1 +
 .../backend/src/server/api/endpoints/gallery/posts/unlike.ts     | 1 +
 .../backend/src/server/api/endpoints/gallery/posts/update.ts     | 1 +
 packages/backend/src/server/api/endpoints/games/reversi/games.ts | 1 +
 .../backend/src/server/api/endpoints/games/reversi/games/show.ts | 1 +
 .../src/server/api/endpoints/games/reversi/games/surrender.ts    | 1 +
 .../src/server/api/endpoints/games/reversi/invitations.ts        | 1 +
 packages/backend/src/server/api/endpoints/games/reversi/match.ts | 1 +
 .../src/server/api/endpoints/games/reversi/match/cancel.ts       | 1 +
 .../backend/src/server/api/endpoints/get-online-users-count.ts   | 1 +
 packages/backend/src/server/api/endpoints/hashtags/list.ts       | 1 +
 packages/backend/src/server/api/endpoints/hashtags/search.ts     | 1 +
 packages/backend/src/server/api/endpoints/hashtags/show.ts       | 1 +
 packages/backend/src/server/api/endpoints/hashtags/trend.ts      | 1 +
 packages/backend/src/server/api/endpoints/hashtags/users.ts      | 1 +
 packages/backend/src/server/api/endpoints/i.ts                   | 1 +
 packages/backend/src/server/api/endpoints/i/2fa/done.ts          | 1 +
 packages/backend/src/server/api/endpoints/i/2fa/key-done.ts      | 1 +
 packages/backend/src/server/api/endpoints/i/2fa/password-less.ts | 1 +
 packages/backend/src/server/api/endpoints/i/2fa/register-key.ts  | 1 +
 packages/backend/src/server/api/endpoints/i/2fa/register.ts      | 1 +
 packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts    | 1 +
 packages/backend/src/server/api/endpoints/i/2fa/unregister.ts    | 1 +
 packages/backend/src/server/api/endpoints/i/apps.ts              | 1 +
 packages/backend/src/server/api/endpoints/i/authorized-apps.ts   | 1 +
 packages/backend/src/server/api/endpoints/i/change-password.ts   | 1 +
 packages/backend/src/server/api/endpoints/i/delete-account.ts    | 1 +
 packages/backend/src/server/api/endpoints/i/export-blocking.ts   | 1 +
 packages/backend/src/server/api/endpoints/i/export-following.ts  | 1 +
 packages/backend/src/server/api/endpoints/i/export-mute.ts       | 1 +
 packages/backend/src/server/api/endpoints/i/export-notes.ts      | 1 +
 packages/backend/src/server/api/endpoints/i/export-user-lists.ts | 1 +
 packages/backend/src/server/api/endpoints/i/favorites.ts         | 1 +
 packages/backend/src/server/api/endpoints/i/gallery/likes.ts     | 1 +
 packages/backend/src/server/api/endpoints/i/gallery/posts.ts     | 1 +
 .../src/server/api/endpoints/i/get-word-muted-notes-count.ts     | 1 +
 packages/backend/src/server/api/endpoints/i/import-blocking.ts   | 1 +
 packages/backend/src/server/api/endpoints/i/import-following.ts  | 1 +
 packages/backend/src/server/api/endpoints/i/import-muting.ts     | 1 +
 packages/backend/src/server/api/endpoints/i/import-user-lists.ts | 1 +
 packages/backend/src/server/api/endpoints/i/notifications.ts     | 1 +
 packages/backend/src/server/api/endpoints/i/page-likes.ts        | 1 +
 packages/backend/src/server/api/endpoints/i/pages.ts             | 1 +
 packages/backend/src/server/api/endpoints/i/pin.ts               | 1 +
 .../src/server/api/endpoints/i/read-all-messaging-messages.ts    | 1 +
 .../backend/src/server/api/endpoints/i/read-all-unread-notes.ts  | 1 +
 packages/backend/src/server/api/endpoints/i/read-announcement.ts | 1 +
 packages/backend/src/server/api/endpoints/i/regenerate-token.ts  | 1 +
 packages/backend/src/server/api/endpoints/i/registry/get-all.ts  | 1 +
 .../backend/src/server/api/endpoints/i/registry/get-detail.ts    | 1 +
 packages/backend/src/server/api/endpoints/i/registry/get.ts      | 1 +
 .../src/server/api/endpoints/i/registry/keys-with-type.ts        | 1 +
 packages/backend/src/server/api/endpoints/i/registry/keys.ts     | 1 +
 packages/backend/src/server/api/endpoints/i/registry/remove.ts   | 1 +
 packages/backend/src/server/api/endpoints/i/registry/scopes.ts   | 1 +
 packages/backend/src/server/api/endpoints/i/registry/set.ts      | 1 +
 packages/backend/src/server/api/endpoints/i/revoke-token.ts      | 1 +
 packages/backend/src/server/api/endpoints/i/signin-history.ts    | 1 +
 packages/backend/src/server/api/endpoints/i/unpin.ts             | 1 +
 packages/backend/src/server/api/endpoints/i/update-email.ts      | 1 +
 packages/backend/src/server/api/endpoints/i/update.ts            | 1 +
 .../backend/src/server/api/endpoints/i/user-group-invites.ts     | 1 +
 packages/backend/src/server/api/endpoints/messaging/history.ts   | 1 +
 packages/backend/src/server/api/endpoints/messaging/messages.ts  | 1 +
 .../src/server/api/endpoints/messaging/messages/create.ts        | 1 +
 .../src/server/api/endpoints/messaging/messages/delete.ts        | 1 +
 .../backend/src/server/api/endpoints/messaging/messages/read.ts  | 1 +
 packages/backend/src/server/api/endpoints/meta.ts                | 1 +
 packages/backend/src/server/api/endpoints/miauth/gen-token.ts    | 1 +
 packages/backend/src/server/api/endpoints/mute/create.ts         | 1 +
 packages/backend/src/server/api/endpoints/mute/delete.ts         | 1 +
 packages/backend/src/server/api/endpoints/mute/list.ts           | 1 +
 packages/backend/src/server/api/endpoints/my/apps.ts             | 1 +
 packages/backend/src/server/api/endpoints/notes.ts               | 1 +
 packages/backend/src/server/api/endpoints/notes/children.ts      | 1 +
 packages/backend/src/server/api/endpoints/notes/clips.ts         | 1 +
 packages/backend/src/server/api/endpoints/notes/conversation.ts  | 1 +
 packages/backend/src/server/api/endpoints/notes/create.ts        | 1 +
 packages/backend/src/server/api/endpoints/notes/delete.ts        | 1 +
 .../backend/src/server/api/endpoints/notes/favorites/create.ts   | 1 +
 .../backend/src/server/api/endpoints/notes/favorites/delete.ts   | 1 +
 packages/backend/src/server/api/endpoints/notes/featured.ts      | 1 +
 .../backend/src/server/api/endpoints/notes/global-timeline.ts    | 1 +
 .../backend/src/server/api/endpoints/notes/hybrid-timeline.ts    | 1 +
 .../backend/src/server/api/endpoints/notes/local-timeline.ts     | 1 +
 packages/backend/src/server/api/endpoints/notes/mentions.ts      | 1 +
 .../src/server/api/endpoints/notes/polls/recommendation.ts       | 1 +
 packages/backend/src/server/api/endpoints/notes/polls/vote.ts    | 1 +
 packages/backend/src/server/api/endpoints/notes/reactions.ts     | 1 +
 .../backend/src/server/api/endpoints/notes/reactions/create.ts   | 1 +
 .../backend/src/server/api/endpoints/notes/reactions/delete.ts   | 1 +
 packages/backend/src/server/api/endpoints/notes/renotes.ts       | 1 +
 packages/backend/src/server/api/endpoints/notes/replies.ts       | 1 +
 packages/backend/src/server/api/endpoints/notes/search-by-tag.ts | 1 +
 packages/backend/src/server/api/endpoints/notes/search.ts        | 1 +
 packages/backend/src/server/api/endpoints/notes/show.ts          | 1 +
 packages/backend/src/server/api/endpoints/notes/state.ts         | 1 +
 .../src/server/api/endpoints/notes/thread-muting/create.ts       | 1 +
 .../src/server/api/endpoints/notes/thread-muting/delete.ts       | 1 +
 packages/backend/src/server/api/endpoints/notes/timeline.ts      | 1 +
 packages/backend/src/server/api/endpoints/notes/translate.ts     | 1 +
 packages/backend/src/server/api/endpoints/notes/unrenote.ts      | 1 +
 .../backend/src/server/api/endpoints/notes/user-list-timeline.ts | 1 +
 .../backend/src/server/api/endpoints/notes/watching/create.ts    | 1 +
 .../backend/src/server/api/endpoints/notes/watching/delete.ts    | 1 +
 .../backend/src/server/api/endpoints/notifications/create.ts     | 1 +
 .../src/server/api/endpoints/notifications/mark-all-as-read.ts   | 1 +
 packages/backend/src/server/api/endpoints/notifications/read.ts  | 1 +
 packages/backend/src/server/api/endpoints/page-push.ts           | 1 +
 packages/backend/src/server/api/endpoints/pages/create.ts        | 1 +
 packages/backend/src/server/api/endpoints/pages/delete.ts        | 1 +
 packages/backend/src/server/api/endpoints/pages/featured.ts      | 1 +
 packages/backend/src/server/api/endpoints/pages/like.ts          | 1 +
 packages/backend/src/server/api/endpoints/pages/show.ts          | 1 +
 packages/backend/src/server/api/endpoints/pages/unlike.ts        | 1 +
 packages/backend/src/server/api/endpoints/pages/update.ts        | 1 +
 packages/backend/src/server/api/endpoints/ping.ts                | 1 +
 packages/backend/src/server/api/endpoints/pinned-users.ts        | 1 +
 packages/backend/src/server/api/endpoints/promo/read.ts          | 1 +
 .../backend/src/server/api/endpoints/request-reset-password.ts   | 1 +
 packages/backend/src/server/api/endpoints/reset-db.ts            | 1 +
 packages/backend/src/server/api/endpoints/reset-password.ts      | 1 +
 packages/backend/src/server/api/endpoints/room/show.ts           | 1 +
 packages/backend/src/server/api/endpoints/room/update.ts         | 1 +
 packages/backend/src/server/api/endpoints/server-info.ts         | 1 +
 packages/backend/src/server/api/endpoints/stats.ts               | 1 +
 packages/backend/src/server/api/endpoints/sw/register.ts         | 1 +
 packages/backend/src/server/api/endpoints/sw/unregister.ts       | 1 +
 packages/backend/src/server/api/endpoints/username/available.ts  | 1 +
 packages/backend/src/server/api/endpoints/users.ts               | 1 +
 packages/backend/src/server/api/endpoints/users/clips.ts         | 1 +
 packages/backend/src/server/api/endpoints/users/followers.ts     | 1 +
 packages/backend/src/server/api/endpoints/users/following.ts     | 1 +
 packages/backend/src/server/api/endpoints/users/gallery/posts.ts | 1 +
 .../server/api/endpoints/users/get-frequently-replied-users.ts   | 1 +
 packages/backend/src/server/api/endpoints/users/groups/create.ts | 1 +
 packages/backend/src/server/api/endpoints/users/groups/delete.ts | 1 +
 .../src/server/api/endpoints/users/groups/invitations/accept.ts  | 1 +
 .../src/server/api/endpoints/users/groups/invitations/reject.ts  | 1 +
 packages/backend/src/server/api/endpoints/users/groups/invite.ts | 1 +
 packages/backend/src/server/api/endpoints/users/groups/joined.ts | 1 +
 packages/backend/src/server/api/endpoints/users/groups/leave.ts  | 1 +
 packages/backend/src/server/api/endpoints/users/groups/owned.ts  | 1 +
 packages/backend/src/server/api/endpoints/users/groups/pull.ts   | 1 +
 packages/backend/src/server/api/endpoints/users/groups/show.ts   | 1 +
 .../backend/src/server/api/endpoints/users/groups/transfer.ts    | 1 +
 packages/backend/src/server/api/endpoints/users/groups/update.ts | 1 +
 packages/backend/src/server/api/endpoints/users/lists/create.ts  | 1 +
 packages/backend/src/server/api/endpoints/users/lists/delete.ts  | 1 +
 packages/backend/src/server/api/endpoints/users/lists/list.ts    | 1 +
 packages/backend/src/server/api/endpoints/users/lists/pull.ts    | 1 +
 packages/backend/src/server/api/endpoints/users/lists/push.ts    | 1 +
 packages/backend/src/server/api/endpoints/users/lists/show.ts    | 1 +
 packages/backend/src/server/api/endpoints/users/lists/update.ts  | 1 +
 packages/backend/src/server/api/endpoints/users/notes.ts         | 1 +
 packages/backend/src/server/api/endpoints/users/pages.ts         | 1 +
 packages/backend/src/server/api/endpoints/users/reactions.ts     | 1 +
 .../backend/src/server/api/endpoints/users/recommendation.ts     | 1 +
 packages/backend/src/server/api/endpoints/users/relation.ts      | 1 +
 .../server/api/endpoints/users/search-by-username-and-host.ts    | 1 +
 packages/backend/src/server/api/endpoints/users/search.ts        | 1 +
 packages/backend/src/server/api/endpoints/users/show.ts          | 1 +
 packages/backend/src/server/api/endpoints/users/stats.ts         | 1 +
 306 files changed, 306 insertions(+)

diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts b/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts
index 774506bf0..5d4cc2c04 100644
--- a/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts
+++ b/packages/backend/src/server/api/endpoints/admin/abuse-user-reports.ts
@@ -110,6 +110,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const query = makePaginationQuery(AbuseUserReports.createQueryBuilder('report'), ps.sinceId, ps.untilId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/create.ts b/packages/backend/src/server/api/endpoints/admin/accounts/create.ts
index b1cdb29a5..edfac244f 100644
--- a/packages/backend/src/server/api/endpoints/admin/accounts/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/accounts/create.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, _me) => {
 	const me = _me ? await Users.findOneOrFail(_me.id) : null;
 	const noUsers = (await Users.count({
diff --git a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
index 3881e02bb..3ed6ac2f3 100644
--- a/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/accounts/delete.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/ad/create.ts b/packages/backend/src/server/api/endpoints/admin/ad/create.ts
index e41d01564..3388ef272 100644
--- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/ad/create.ts
@@ -34,6 +34,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	await Ads.insert({
 		id: genId(),
diff --git a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts
index ab5cd96d0..ab0458af6 100644
--- a/packages/backend/src/server/api/endpoints/admin/ad/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/ad/delete.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const ad = await Ads.findOne(ps.id);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/ad/list.ts b/packages/backend/src/server/api/endpoints/admin/ad/list.ts
index f22dd0e96..04597ec7b 100644
--- a/packages/backend/src/server/api/endpoints/admin/ad/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/ad/list.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const query = makePaginationQuery(Ads.createQueryBuilder('ad'), ps.sinceId, ps.untilId)
 		.andWhere('ad.expiresAt > :now', { now: new Date() });
diff --git a/packages/backend/src/server/api/endpoints/admin/ad/update.ts b/packages/backend/src/server/api/endpoints/admin/ad/update.ts
index 1d91cfd16..7fab745ef 100644
--- a/packages/backend/src/server/api/endpoints/admin/ad/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/ad/update.ts
@@ -46,6 +46,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const ad = await Ads.findOne(ps.id);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
index 886cacff7..feb874db7 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
@@ -57,6 +57,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const announcement = await Announcements.save({
 		id: genId(),
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts
index ade9ef581..81dd8cfc5 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/delete.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const announcement = await Announcements.findOne(ps.id);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
index f25b5e8ef..f6ad6d36f 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
@@ -69,6 +69,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts
index 3fa8440eb..6fb4b571a 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/update.ts
@@ -34,6 +34,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const announcement = await Announcements.findOne(ps.id);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts b/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts
index 50979d53e..82cbe7b19 100644
--- a/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/delete-all-files-of-a-user.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const files = await DriveFiles.find({
 		userId: ps.userId,
diff --git a/packages/backend/src/server/api/endpoints/admin/delete-logs.ts b/packages/backend/src/server/api/endpoints/admin/delete-logs.ts
index 9d37ceb43..197ad01cb 100644
--- a/packages/backend/src/server/api/endpoints/admin/delete-logs.ts
+++ b/packages/backend/src/server/api/endpoints/admin/delete-logs.ts
@@ -8,6 +8,7 @@ export const meta = {
 	requireModerator: true,
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	await Logs.clear();	// TRUNCATE
 });
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts b/packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts
index 76a6acff5..518535fdd 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/clean-remote-files.ts
@@ -8,6 +8,7 @@ export const meta = {
 	requireModerator: true,
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	createCleanRemoteFilesJob();
 });
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts b/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts
index ae0e396b4..a523c5b39 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/cleanup.ts
@@ -10,6 +10,7 @@ export const meta = {
 	requireModerator: true,
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const files = await DriveFiles.find({
 		userId: IsNull(),
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/files.ts b/packages/backend/src/server/api/endpoints/admin/drive/files.ts
index ee07245db..b90ad9044 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/files.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/files.ts
@@ -54,6 +54,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
index ab8e3d68e..bc0857588 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
@@ -161,6 +161,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const file = ps.fileId ? await DriveFiles.findOne(ps.fileId) : await DriveFiles.findOne({
 		where: [{
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
index 407d9920d..bafa658a5 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
@@ -30,6 +30,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const file = await DriveFiles.findOne(ps.fileId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
index ae02df65e..6dc7d1bd9 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/copy.ts
@@ -42,6 +42,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const emoji = await Emojis.findOne(ps.emojiId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts
index 090ba2b64..42b6cb1fc 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/list-remote.ts
@@ -77,6 +77,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts
index 89cb60aca..5026af914 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/list.ts
@@ -72,6 +72,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const q = makePaginationQuery(Emojis.createQueryBuilder('emoji'), ps.sinceId, ps.untilId)
 		.andWhere(`emoji.host IS NULL`);
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/remove.ts b/packages/backend/src/server/api/endpoints/admin/emoji/remove.ts
index 78085470a..440c1008c 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/remove.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/remove.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const emoji = await Emojis.findOne(ps.id);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
index c61d8cb32..391887257 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/update.ts
@@ -38,6 +38,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const emoji = await Emojis.findOne(ps.id);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts b/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts
index d9e003d35..904619683 100644
--- a/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts
+++ b/packages/backend/src/server/api/endpoints/admin/federation/delete-all-files.ts
@@ -16,6 +16,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const files = await DriveFiles.find({
 		userHost: ps.host,
diff --git a/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts b/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts
index 9e7a8ec47..d9e3900a2 100644
--- a/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts
+++ b/packages/backend/src/server/api/endpoints/admin/federation/refresh-remote-instance-metadata.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const instance = await Instances.findOne({ host: toPuny(ps.host) });
 
diff --git a/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts b/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts
index 8fc964fd2..485bbe7d5 100644
--- a/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts
+++ b/packages/backend/src/server/api/endpoints/admin/federation/remove-all-following.ts
@@ -16,6 +16,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const followings = await Followings.find({
 		followerHost: ps.host,
diff --git a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts
index 4ea1275f7..3ddccecc6 100644
--- a/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts
+++ b/packages/backend/src/server/api/endpoints/admin/federation/update-instance.ts
@@ -20,6 +20,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const instance = await Instances.findOne({ host: toPuny(ps.host) });
 
diff --git a/packages/backend/src/server/api/endpoints/admin/get-index-stats.ts b/packages/backend/src/server/api/endpoints/admin/get-index-stats.ts
index f2b06d0ef..877e67aa7 100644
--- a/packages/backend/src/server/api/endpoints/admin/get-index-stats.ts
+++ b/packages/backend/src/server/api/endpoints/admin/get-index-stats.ts
@@ -11,6 +11,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	const stats = await
 		getConnection().query(`SELECT * FROM pg_indexes;`)
diff --git a/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts b/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts
index 64f029294..5d4ea9c44 100644
--- a/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts
+++ b/packages/backend/src/server/api/endpoints/admin/get-table-stats.ts
@@ -22,6 +22,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	const sizes = await
 		getConnection().query(`
diff --git a/packages/backend/src/server/api/endpoints/admin/invite.ts b/packages/backend/src/server/api/endpoints/admin/invite.ts
index b9452c83d..1c8c51434 100644
--- a/packages/backend/src/server/api/endpoints/admin/invite.ts
+++ b/packages/backend/src/server/api/endpoints/admin/invite.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	const code = rndstr({
 		length: 8,
diff --git a/packages/backend/src/server/api/endpoints/admin/moderators/add.ts b/packages/backend/src/server/api/endpoints/admin/moderators/add.ts
index 8e3419bf6..ea795895f 100644
--- a/packages/backend/src/server/api/endpoints/admin/moderators/add.ts
+++ b/packages/backend/src/server/api/endpoints/admin/moderators/add.ts
@@ -16,6 +16,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const user = await Users.findOne(ps.userId as string);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/moderators/remove.ts b/packages/backend/src/server/api/endpoints/admin/moderators/remove.ts
index 5a5a91e9c..25f237d81 100644
--- a/packages/backend/src/server/api/endpoints/admin/moderators/remove.ts
+++ b/packages/backend/src/server/api/endpoints/admin/moderators/remove.ts
@@ -16,6 +16,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const user = await Users.findOne(ps.userId as string);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/promo/create.ts b/packages/backend/src/server/api/endpoints/admin/promo/create.ts
index 245780c2d..1bd54ba89 100644
--- a/packages/backend/src/server/api/endpoints/admin/promo/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/promo/create.ts
@@ -36,6 +36,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/admin/queue/clear.ts b/packages/backend/src/server/api/endpoints/admin/queue/clear.ts
index 3a7ae6b4b..8a91168ec 100644
--- a/packages/backend/src/server/api/endpoints/admin/queue/clear.ts
+++ b/packages/backend/src/server/api/endpoints/admin/queue/clear.ts
@@ -11,6 +11,7 @@ export const meta = {
 	params: {},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	destroy();
 
diff --git a/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts b/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts
index cb2d1d0d7..2c867463e 100644
--- a/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts
+++ b/packages/backend/src/server/api/endpoints/admin/queue/deliver-delayed.ts
@@ -35,6 +35,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const jobs = await deliverQueue.getJobs(['delayed']);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts b/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts
index d524002fa..974e68012 100644
--- a/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts
+++ b/packages/backend/src/server/api/endpoints/admin/queue/inbox-delayed.ts
@@ -35,6 +35,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const jobs = await inboxQueue.getJobs(['delayed']);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts b/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts
index ece1d46f3..70649e067 100644
--- a/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts
+++ b/packages/backend/src/server/api/endpoints/admin/queue/jobs.ts
@@ -56,6 +56,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const queue =
 		ps.domain === 'deliver' ? deliverQueue :
diff --git a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts
index 1fc42ea0b..5de871a60 100644
--- a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts
+++ b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts
@@ -29,6 +29,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const deliverJobCounts = await deliverQueue.getJobCounts();
 	const inboxJobCounts = await inboxQueue.getJobCounts();
diff --git a/packages/backend/src/server/api/endpoints/admin/relays/add.ts b/packages/backend/src/server/api/endpoints/admin/relays/add.ts
index 80609aee9..c4a0f1302 100644
--- a/packages/backend/src/server/api/endpoints/admin/relays/add.ts
+++ b/packages/backend/src/server/api/endpoints/admin/relays/add.ts
@@ -52,6 +52,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	try {
 		if (new URL(ps.inbox).protocol !== 'https:') throw 'https only';
diff --git a/packages/backend/src/server/api/endpoints/admin/relays/list.ts b/packages/backend/src/server/api/endpoints/admin/relays/list.ts
index ef103fbb3..1e8afd783 100644
--- a/packages/backend/src/server/api/endpoints/admin/relays/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/relays/list.ts
@@ -42,6 +42,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	return await listRelay();
 });
diff --git a/packages/backend/src/server/api/endpoints/admin/relays/remove.ts b/packages/backend/src/server/api/endpoints/admin/relays/remove.ts
index e7ddef30f..293de2b91 100644
--- a/packages/backend/src/server/api/endpoints/admin/relays/remove.ts
+++ b/packages/backend/src/server/api/endpoints/admin/relays/remove.ts
@@ -15,6 +15,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	return await removeRelay(ps.inbox);
 });
diff --git a/packages/backend/src/server/api/endpoints/admin/reset-password.ts b/packages/backend/src/server/api/endpoints/admin/reset-password.ts
index bdd7ef27b..227bcbab9 100644
--- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts
+++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts
@@ -31,6 +31,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const user = await Users.findOne(ps.userId as string);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
index 94158ecfd..a189c3e99 100644
--- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
+++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
@@ -16,6 +16,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const report = await AbuseUserReports.findOne(ps.reportId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/resync-chart.ts b/packages/backend/src/server/api/endpoints/admin/resync-chart.ts
index e01dfce1b..49d41cd8c 100644
--- a/packages/backend/src/server/api/endpoints/admin/resync-chart.ts
+++ b/packages/backend/src/server/api/endpoints/admin/resync-chart.ts
@@ -9,6 +9,7 @@ export const meta = {
 	requireModerator: true,
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	insertModerationLog(me, 'chartResync');
 
diff --git a/packages/backend/src/server/api/endpoints/admin/send-email.ts b/packages/backend/src/server/api/endpoints/admin/send-email.ts
index 4797aa7a2..74ec98f75 100644
--- a/packages/backend/src/server/api/endpoints/admin/send-email.ts
+++ b/packages/backend/src/server/api/endpoints/admin/send-email.ts
@@ -21,6 +21,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	await sendEmail(ps.to, ps.subject, ps.text, ps.text);
 });
diff --git a/packages/backend/src/server/api/endpoints/admin/server-info.ts b/packages/backend/src/server/api/endpoints/admin/server-info.ts
index 4ddc39deb..9346c5dd2 100644
--- a/packages/backend/src/server/api/endpoints/admin/server-info.ts
+++ b/packages/backend/src/server/api/endpoints/admin/server-info.ts
@@ -90,6 +90,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	const memStats = await si.mem();
 	const fsStats = await si.fsSize();
diff --git a/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts b/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts
index 19d4be973..0d3759a84 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-moderation-logs.ts
@@ -65,6 +65,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const query = makePaginationQuery(ModerationLogs.createQueryBuilder('report'), ps.sinceId, ps.untilId);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/show-user.ts b/packages/backend/src/server/api/endpoints/admin/show-user.ts
index 21cc9e5ab..7ac922ca7 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-user.ts
@@ -159,6 +159,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId as string);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/show-users.ts b/packages/backend/src/server/api/endpoints/admin/show-users.ts
index 9c57917cb..507183e87 100644
--- a/packages/backend/src/server/api/endpoints/admin/show-users.ts
+++ b/packages/backend/src/server/api/endpoints/admin/show-users.ts
@@ -74,6 +74,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = Users.createQueryBuilder('user');
 
diff --git a/packages/backend/src/server/api/endpoints/admin/silence-user.ts b/packages/backend/src/server/api/endpoints/admin/silence-user.ts
index 9f5135b1a..b4a1ddcc0 100644
--- a/packages/backend/src/server/api/endpoints/admin/silence-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/silence-user.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId as string);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
index c062dcc93..95771e0c3 100644
--- a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
@@ -21,6 +21,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId as string);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/unsilence-user.ts b/packages/backend/src/server/api/endpoints/admin/unsilence-user.ts
index bc081c848..e04960a4e 100644
--- a/packages/backend/src/server/api/endpoints/admin/unsilence-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/unsilence-user.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId as string);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
index 73a5bc739..0a6ceadab 100644
--- a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
@@ -18,6 +18,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId as string);
 
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index e67088e0a..0d5455cd3 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -299,6 +299,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const set = {} as Partial<Meta>;
 
diff --git a/packages/backend/src/server/api/endpoints/admin/vacuum.ts b/packages/backend/src/server/api/endpoints/admin/vacuum.ts
index d08dfdd9e..798a51acc 100644
--- a/packages/backend/src/server/api/endpoints/admin/vacuum.ts
+++ b/packages/backend/src/server/api/endpoints/admin/vacuum.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const params: string[] = [];
 
diff --git a/packages/backend/src/server/api/endpoints/announcements.ts b/packages/backend/src/server/api/endpoints/announcements.ts
index 32ef49d88..122d04f17 100644
--- a/packages/backend/src/server/api/endpoints/announcements.ts
+++ b/packages/backend/src/server/api/endpoints/announcements.ts
@@ -73,6 +73,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(Announcements.createQueryBuilder('announcement'), ps.sinceId, ps.untilId);
 
diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts
index 83c7d3e0a..b3276bd9c 100644
--- a/packages/backend/src/server/api/endpoints/antennas/create.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/create.ts
@@ -80,6 +80,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	let userList;
 	let userGroupJoining;
diff --git a/packages/backend/src/server/api/endpoints/antennas/delete.ts b/packages/backend/src/server/api/endpoints/antennas/delete.ts
index 721932f31..c6da54540 100644
--- a/packages/backend/src/server/api/endpoints/antennas/delete.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/delete.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const antenna = await Antennas.findOne({
 		id: ps.antennaId,
diff --git a/packages/backend/src/server/api/endpoints/antennas/list.ts b/packages/backend/src/server/api/endpoints/antennas/list.ts
index 4a9eed856..1f24e0fb9 100644
--- a/packages/backend/src/server/api/endpoints/antennas/list.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/list.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const antennas = await Antennas.find({
 		userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/antennas/notes.ts b/packages/backend/src/server/api/endpoints/antennas/notes.ts
index 968924831..09500a38d 100644
--- a/packages/backend/src/server/api/endpoints/antennas/notes.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/notes.ts
@@ -62,6 +62,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const antenna = await Antennas.findOne({
 		id: ps.antennaId,
diff --git a/packages/backend/src/server/api/endpoints/antennas/show.ts b/packages/backend/src/server/api/endpoints/antennas/show.ts
index 79e988497..a02c44ac2 100644
--- a/packages/backend/src/server/api/endpoints/antennas/show.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/show.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the antenna
 	const antenna = await Antennas.findOne({
diff --git a/packages/backend/src/server/api/endpoints/antennas/update.ts b/packages/backend/src/server/api/endpoints/antennas/update.ts
index d5400a792..968f761a3 100644
--- a/packages/backend/src/server/api/endpoints/antennas/update.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/update.ts
@@ -89,6 +89,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch the antenna
 	const antenna = await Antennas.findOne({
diff --git a/packages/backend/src/server/api/endpoints/ap/get.ts b/packages/backend/src/server/api/endpoints/ap/get.ts
index 000ed2d2d..0acce9bdb 100644
--- a/packages/backend/src/server/api/endpoints/ap/get.ts
+++ b/packages/backend/src/server/api/endpoints/ap/get.ts
@@ -29,6 +29,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const resolver = new Resolver();
 	const object = await resolver.resolve(ps.uri);
diff --git a/packages/backend/src/server/api/endpoints/ap/show.ts b/packages/backend/src/server/api/endpoints/ap/show.ts
index 709349262..e4e13117e 100644
--- a/packages/backend/src/server/api/endpoints/ap/show.ts
+++ b/packages/backend/src/server/api/endpoints/ap/show.ts
@@ -54,6 +54,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const object = await fetchAny(ps.uri);
 	if (object) {
diff --git a/packages/backend/src/server/api/endpoints/app/create.ts b/packages/backend/src/server/api/endpoints/app/create.ts
index 78586cbcf..88e5d866c 100644
--- a/packages/backend/src/server/api/endpoints/app/create.ts
+++ b/packages/backend/src/server/api/endpoints/app/create.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Generate secret
 	const secret = secureRndstr(32, true);
diff --git a/packages/backend/src/server/api/endpoints/app/show.ts b/packages/backend/src/server/api/endpoints/app/show.ts
index c83d576b4..701a23b22 100644
--- a/packages/backend/src/server/api/endpoints/app/show.ts
+++ b/packages/backend/src/server/api/endpoints/app/show.ts
@@ -34,6 +34,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user, token) => {
 	const isSecure = user != null && token == null;
 
diff --git a/packages/backend/src/server/api/endpoints/auth/accept.ts b/packages/backend/src/server/api/endpoints/auth/accept.ts
index 989ebf8f2..6b2b0bc70 100644
--- a/packages/backend/src/server/api/endpoints/auth/accept.ts
+++ b/packages/backend/src/server/api/endpoints/auth/accept.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch token
 	const session = await AuthSessions
diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts
index 39ba5a972..2b46c4828 100644
--- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts
+++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts
@@ -42,6 +42,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	// Lookup app
 	const app = await Apps.findOne({
diff --git a/packages/backend/src/server/api/endpoints/auth/session/show.ts b/packages/backend/src/server/api/endpoints/auth/session/show.ts
index e890dd95a..3a32b5e54 100644
--- a/packages/backend/src/server/api/endpoints/auth/session/show.ts
+++ b/packages/backend/src/server/api/endpoints/auth/session/show.ts
@@ -44,6 +44,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Lookup session
 	const session = await AuthSessions.findOne({
diff --git a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts
index 241b13d4d..131cdf3df 100644
--- a/packages/backend/src/server/api/endpoints/auth/session/userkey.ts
+++ b/packages/backend/src/server/api/endpoints/auth/session/userkey.ts
@@ -56,6 +56,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	// Lookup app
 	const app = await Apps.findOne({
diff --git a/packages/backend/src/server/api/endpoints/blocking/create.ts b/packages/backend/src/server/api/endpoints/blocking/create.ts
index cb92589d1..f718bcd20 100644
--- a/packages/backend/src/server/api/endpoints/blocking/create.ts
+++ b/packages/backend/src/server/api/endpoints/blocking/create.ts
@@ -52,6 +52,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const blocker = await Users.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/blocking/delete.ts b/packages/backend/src/server/api/endpoints/blocking/delete.ts
index 7a99fe0f4..e56311741 100644
--- a/packages/backend/src/server/api/endpoints/blocking/delete.ts
+++ b/packages/backend/src/server/api/endpoints/blocking/delete.ts
@@ -52,6 +52,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const blocker = await Users.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/blocking/list.ts b/packages/backend/src/server/api/endpoints/blocking/list.ts
index 901403d14..f1f4b1699 100644
--- a/packages/backend/src/server/api/endpoints/blocking/list.ts
+++ b/packages/backend/src/server/api/endpoints/blocking/list.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(Blockings.createQueryBuilder('blocking'), ps.sinceId, ps.untilId)
 		.andWhere(`blocking.blockerId = :meId`, { meId: me.id });
diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts
index 0176f86e0..9c88231dd 100644
--- a/packages/backend/src/server/api/endpoints/channels/create.ts
+++ b/packages/backend/src/server/api/endpoints/channels/create.ts
@@ -42,6 +42,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	let banner = null;
 	if (ps.bannerId != null) {
diff --git a/packages/backend/src/server/api/endpoints/channels/featured.ts b/packages/backend/src/server/api/endpoints/channels/featured.ts
index 8eab2402b..cec14cda1 100644
--- a/packages/backend/src/server/api/endpoints/channels/featured.ts
+++ b/packages/backend/src/server/api/endpoints/channels/featured.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = Channels.createQueryBuilder('channel')
 		.where('channel.lastNotedAt IS NOT NULL')
diff --git a/packages/backend/src/server/api/endpoints/channels/follow.ts b/packages/backend/src/server/api/endpoints/channels/follow.ts
index d30593acd..3f4904f71 100644
--- a/packages/backend/src/server/api/endpoints/channels/follow.ts
+++ b/packages/backend/src/server/api/endpoints/channels/follow.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const channel = await Channels.findOne({
 		id: ps.channelId,
diff --git a/packages/backend/src/server/api/endpoints/channels/followed.ts b/packages/backend/src/server/api/endpoints/channels/followed.ts
index 28454c97f..82ae1a3af 100644
--- a/packages/backend/src/server/api/endpoints/channels/followed.ts
+++ b/packages/backend/src/server/api/endpoints/channels/followed.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(ChannelFollowings.createQueryBuilder(), ps.sinceId, ps.untilId)
 		.andWhere({ followerId: me.id });
diff --git a/packages/backend/src/server/api/endpoints/channels/owned.ts b/packages/backend/src/server/api/endpoints/channels/owned.ts
index 44024b158..128ea4115 100644
--- a/packages/backend/src/server/api/endpoints/channels/owned.ts
+++ b/packages/backend/src/server/api/endpoints/channels/owned.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(Channels.createQueryBuilder(), ps.sinceId, ps.untilId)
 		.andWhere({ userId: me.id });
diff --git a/packages/backend/src/server/api/endpoints/channels/show.ts b/packages/backend/src/server/api/endpoints/channels/show.ts
index e7ce4f22e..28cb92764 100644
--- a/packages/backend/src/server/api/endpoints/channels/show.ts
+++ b/packages/backend/src/server/api/endpoints/channels/show.ts
@@ -30,6 +30,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const channel = await Channels.findOne({
 		id: ps.channelId,
diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts
index 56c205cae..ec60e5f23 100644
--- a/packages/backend/src/server/api/endpoints/channels/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts
@@ -57,6 +57,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const channel = await Channels.findOne({
 		id: ps.channelId,
diff --git a/packages/backend/src/server/api/endpoints/channels/unfollow.ts b/packages/backend/src/server/api/endpoints/channels/unfollow.ts
index 8ce9a7e64..1472aa045 100644
--- a/packages/backend/src/server/api/endpoints/channels/unfollow.ts
+++ b/packages/backend/src/server/api/endpoints/channels/unfollow.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const channel = await Channels.findOne({
 		id: ps.channelId,
diff --git a/packages/backend/src/server/api/endpoints/channels/update.ts b/packages/backend/src/server/api/endpoints/channels/update.ts
index 0e6863ac7..fee79df2f 100644
--- a/packages/backend/src/server/api/endpoints/channels/update.ts
+++ b/packages/backend/src/server/api/endpoints/channels/update.ts
@@ -56,6 +56,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const channel = await Channels.findOne({
 		id: ps.channelId,
diff --git a/packages/backend/src/server/api/endpoints/charts/active-users.ts b/packages/backend/src/server/api/endpoints/charts/active-users.ts
index c4878f7d6..ac77f8f1d 100644
--- a/packages/backend/src/server/api/endpoints/charts/active-users.ts
+++ b/packages/backend/src/server/api/endpoints/charts/active-users.ts
@@ -25,6 +25,7 @@ export const meta = {
 	res: convertLog(activeUsersChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await activeUsersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/drive.ts b/packages/backend/src/server/api/endpoints/charts/drive.ts
index 07bff82cf..7f15467e7 100644
--- a/packages/backend/src/server/api/endpoints/charts/drive.ts
+++ b/packages/backend/src/server/api/endpoints/charts/drive.ts
@@ -25,6 +25,7 @@ export const meta = {
 	res: convertLog(driveChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await driveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/federation.ts b/packages/backend/src/server/api/endpoints/charts/federation.ts
index 9575f9a7b..677c28c1e 100644
--- a/packages/backend/src/server/api/endpoints/charts/federation.ts
+++ b/packages/backend/src/server/api/endpoints/charts/federation.ts
@@ -25,6 +25,7 @@ export const meta = {
 	res: convertLog(federationChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await federationChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/hashtag.ts b/packages/backend/src/server/api/endpoints/charts/hashtag.ts
index 53dc61e51..aa41bcf90 100644
--- a/packages/backend/src/server/api/endpoints/charts/hashtag.ts
+++ b/packages/backend/src/server/api/endpoints/charts/hashtag.ts
@@ -29,6 +29,7 @@ export const meta = {
 	res: convertLog(hashtagChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await hashtagChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.tag);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/instance.ts b/packages/backend/src/server/api/endpoints/charts/instance.ts
index 4e96304d8..2ac415464 100644
--- a/packages/backend/src/server/api/endpoints/charts/instance.ts
+++ b/packages/backend/src/server/api/endpoints/charts/instance.ts
@@ -29,6 +29,7 @@ export const meta = {
 	res: convertLog(instanceChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await instanceChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.host);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/network.ts b/packages/backend/src/server/api/endpoints/charts/network.ts
index b524df93b..4056becad 100644
--- a/packages/backend/src/server/api/endpoints/charts/network.ts
+++ b/packages/backend/src/server/api/endpoints/charts/network.ts
@@ -25,6 +25,7 @@ export const meta = {
 	res: convertLog(networkChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await networkChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/notes.ts b/packages/backend/src/server/api/endpoints/charts/notes.ts
index 676f30293..00d6e0aa6 100644
--- a/packages/backend/src/server/api/endpoints/charts/notes.ts
+++ b/packages/backend/src/server/api/endpoints/charts/notes.ts
@@ -25,6 +25,7 @@ export const meta = {
 	res: convertLog(notesChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await notesChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/user/drive.ts b/packages/backend/src/server/api/endpoints/charts/user/drive.ts
index 4fc12b330..462fb5879 100644
--- a/packages/backend/src/server/api/endpoints/charts/user/drive.ts
+++ b/packages/backend/src/server/api/endpoints/charts/user/drive.ts
@@ -30,6 +30,7 @@ export const meta = {
 	res: convertLog(perUserDriveChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await perUserDriveChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/user/following.ts b/packages/backend/src/server/api/endpoints/charts/user/following.ts
index 9207760a3..3aee237d8 100644
--- a/packages/backend/src/server/api/endpoints/charts/user/following.ts
+++ b/packages/backend/src/server/api/endpoints/charts/user/following.ts
@@ -30,6 +30,7 @@ export const meta = {
 	res: convertLog(perUserFollowingChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await perUserFollowingChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/user/notes.ts b/packages/backend/src/server/api/endpoints/charts/user/notes.ts
index f54392057..3536e7b77 100644
--- a/packages/backend/src/server/api/endpoints/charts/user/notes.ts
+++ b/packages/backend/src/server/api/endpoints/charts/user/notes.ts
@@ -30,6 +30,7 @@ export const meta = {
 	res: convertLog(perUserNotesChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await perUserNotesChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/user/reactions.ts b/packages/backend/src/server/api/endpoints/charts/user/reactions.ts
index 4ceb79f7f..9c5515f0b 100644
--- a/packages/backend/src/server/api/endpoints/charts/user/reactions.ts
+++ b/packages/backend/src/server/api/endpoints/charts/user/reactions.ts
@@ -30,6 +30,7 @@ export const meta = {
 	res: convertLog(perUserReactionsChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await perUserReactionsChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null, ps.userId);
 });
diff --git a/packages/backend/src/server/api/endpoints/charts/users.ts b/packages/backend/src/server/api/endpoints/charts/users.ts
index deac89b59..d8bbb8300 100644
--- a/packages/backend/src/server/api/endpoints/charts/users.ts
+++ b/packages/backend/src/server/api/endpoints/charts/users.ts
@@ -25,6 +25,7 @@ export const meta = {
 	res: convertLog(usersChart.schema),
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await usersChart.getChart(ps.span as any, ps.limit!, ps.offset ? new Date(ps.offset) : null);
 });
diff --git a/packages/backend/src/server/api/endpoints/clips/add-note.ts b/packages/backend/src/server/api/endpoints/clips/add-note.ts
index 99312a71b..992ba0edd 100644
--- a/packages/backend/src/server/api/endpoints/clips/add-note.ts
+++ b/packages/backend/src/server/api/endpoints/clips/add-note.ts
@@ -44,6 +44,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const clip = await Clips.findOne({
 		id: ps.clipId,
diff --git a/packages/backend/src/server/api/endpoints/clips/create.ts b/packages/backend/src/server/api/endpoints/clips/create.ts
index cb4ff56ab..e9900247a 100644
--- a/packages/backend/src/server/api/endpoints/clips/create.ts
+++ b/packages/backend/src/server/api/endpoints/clips/create.ts
@@ -31,6 +31,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const clip = await Clips.insert({
 		id: genId(),
diff --git a/packages/backend/src/server/api/endpoints/clips/delete.ts b/packages/backend/src/server/api/endpoints/clips/delete.ts
index 9ec6bc7ea..b7d16322d 100644
--- a/packages/backend/src/server/api/endpoints/clips/delete.ts
+++ b/packages/backend/src/server/api/endpoints/clips/delete.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const clip = await Clips.findOne({
 		id: ps.clipId,
diff --git a/packages/backend/src/server/api/endpoints/clips/list.ts b/packages/backend/src/server/api/endpoints/clips/list.ts
index 3b32c0289..8388438bd 100644
--- a/packages/backend/src/server/api/endpoints/clips/list.ts
+++ b/packages/backend/src/server/api/endpoints/clips/list.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const clips = await Clips.find({
 		userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/clips/notes.ts b/packages/backend/src/server/api/endpoints/clips/notes.ts
index 90ddd66a1..c8871cd3f 100644
--- a/packages/backend/src/server/api/endpoints/clips/notes.ts
+++ b/packages/backend/src/server/api/endpoints/clips/notes.ts
@@ -53,6 +53,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const clip = await Clips.findOne({
 		id: ps.clipId,
diff --git a/packages/backend/src/server/api/endpoints/clips/show.ts b/packages/backend/src/server/api/endpoints/clips/show.ts
index 8e9409fad..ce65abd65 100644
--- a/packages/backend/src/server/api/endpoints/clips/show.ts
+++ b/packages/backend/src/server/api/endpoints/clips/show.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the clip
 	const clip = await Clips.findOne({
diff --git a/packages/backend/src/server/api/endpoints/clips/update.ts b/packages/backend/src/server/api/endpoints/clips/update.ts
index 9cf12499a..44e8fe33e 100644
--- a/packages/backend/src/server/api/endpoints/clips/update.ts
+++ b/packages/backend/src/server/api/endpoints/clips/update.ts
@@ -44,6 +44,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch the clip
 	const clip = await Clips.findOne({
diff --git a/packages/backend/src/server/api/endpoints/drive.ts b/packages/backend/src/server/api/endpoints/drive.ts
index b9741ba87..35ac98bdf 100644
--- a/packages/backend/src/server/api/endpoints/drive.ts
+++ b/packages/backend/src/server/api/endpoints/drive.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const instance = await fetchMeta(true);
 
diff --git a/packages/backend/src/server/api/endpoints/drive/files.ts b/packages/backend/src/server/api/endpoints/drive/files.ts
index 00ebb51e3..7a577bce6 100644
--- a/packages/backend/src/server/api/endpoints/drive/files.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files.ts
@@ -46,6 +46,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId)
 		.andWhere('file.userId = :userId', { userId: user.id });
diff --git a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts
index c8317c1cc..a02ac3eef 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/attached-notes.ts
@@ -36,6 +36,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch file
 	const file = await DriveFiles.findOne({
diff --git a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts
index a6db160d2..14517ab4b 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/check-existence.ts
@@ -21,6 +21,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const file = await DriveFiles.findOne({
 		md5: ps.md5,
diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts
index 5523ae196..640b62c6e 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/create.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts
@@ -60,6 +60,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user, _, file, cleanup) => {
 	// Get 'name' parameter
 	let name = ps.name || file.originalname;
diff --git a/packages/backend/src/server/api/endpoints/drive/files/delete.ts b/packages/backend/src/server/api/endpoints/drive/files/delete.ts
index 3a8e4b11f..2e32e6879 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/delete.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/delete.ts
@@ -34,6 +34,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const file = await DriveFiles.findOne(ps.fileId);
 
diff --git a/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts b/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts
index 16717149a..5617769a9 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/find-by-hash.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const files = await DriveFiles.find({
 		md5: ps.md5,
diff --git a/packages/backend/src/server/api/endpoints/drive/files/find.ts b/packages/backend/src/server/api/endpoints/drive/files/find.ts
index 108e08593..415ab7961 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/find.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/find.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const files = await DriveFiles.find({
 		name: ps.name,
diff --git a/packages/backend/src/server/api/endpoints/drive/files/show.ts b/packages/backend/src/server/api/endpoints/drive/files/show.ts
index 96f8e5c03..4a8830e9c 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/show.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/show.ts
@@ -49,6 +49,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	let file: DriveFile | undefined;
 
diff --git a/packages/backend/src/server/api/endpoints/drive/files/update.ts b/packages/backend/src/server/api/endpoints/drive/files/update.ts
index 04b2db9cf..329e959c5 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/update.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/update.ts
@@ -66,6 +66,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const file = await DriveFiles.findOne(ps.fileId);
 
diff --git a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts
index 8a2fbc36b..7e3ffd881 100644
--- a/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts
+++ b/packages/backend/src/server/api/endpoints/drive/files/upload-from-url.ts
@@ -52,6 +52,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	uploadFromUrl(ps.url, user, ps.folderId, null, ps.isSensitive, ps.force, false, ps.comment).then(file => {
 		DriveFiles.pack(file, { self: true }).then(packedFile => {
diff --git a/packages/backend/src/server/api/endpoints/drive/folders.ts b/packages/backend/src/server/api/endpoints/drive/folders.ts
index cd2d1743c..85938e7b5 100644
--- a/packages/backend/src/server/api/endpoints/drive/folders.ts
+++ b/packages/backend/src/server/api/endpoints/drive/folders.ts
@@ -42,6 +42,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(DriveFolders.createQueryBuilder('folder'), ps.sinceId, ps.untilId)
 		.andWhere('folder.userId = :userId', { userId: user.id });
diff --git a/packages/backend/src/server/api/endpoints/drive/folders/create.ts b/packages/backend/src/server/api/endpoints/drive/folders/create.ts
index 9ae59d4b4..401b59152 100644
--- a/packages/backend/src/server/api/endpoints/drive/folders/create.ts
+++ b/packages/backend/src/server/api/endpoints/drive/folders/create.ts
@@ -39,6 +39,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// If the parent folder is specified
 	let parent = null;
diff --git a/packages/backend/src/server/api/endpoints/drive/folders/delete.ts b/packages/backend/src/server/api/endpoints/drive/folders/delete.ts
index bfd3361e7..2360a3abf 100644
--- a/packages/backend/src/server/api/endpoints/drive/folders/delete.ts
+++ b/packages/backend/src/server/api/endpoints/drive/folders/delete.ts
@@ -33,6 +33,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Get folder
 	const folder = await DriveFolders.findOne({
diff --git a/packages/backend/src/server/api/endpoints/drive/folders/find.ts b/packages/backend/src/server/api/endpoints/drive/folders/find.ts
index 872eabef9..47e45a23f 100644
--- a/packages/backend/src/server/api/endpoints/drive/folders/find.ts
+++ b/packages/backend/src/server/api/endpoints/drive/folders/find.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const folders = await DriveFolders.find({
 		name: ps.name,
diff --git a/packages/backend/src/server/api/endpoints/drive/folders/show.ts b/packages/backend/src/server/api/endpoints/drive/folders/show.ts
index 63b5bc9e7..d6eac59fe 100644
--- a/packages/backend/src/server/api/endpoints/drive/folders/show.ts
+++ b/packages/backend/src/server/api/endpoints/drive/folders/show.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Get folder
 	const folder = await DriveFolders.findOne({
diff --git a/packages/backend/src/server/api/endpoints/drive/folders/update.ts b/packages/backend/src/server/api/endpoints/drive/folders/update.ts
index e54780886..5ae5424fb 100644
--- a/packages/backend/src/server/api/endpoints/drive/folders/update.ts
+++ b/packages/backend/src/server/api/endpoints/drive/folders/update.ts
@@ -53,6 +53,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch folder
 	const folder = await DriveFolders.findOne({
diff --git a/packages/backend/src/server/api/endpoints/drive/stream.ts b/packages/backend/src/server/api/endpoints/drive/stream.ts
index e3031f75b..675e3225f 100644
--- a/packages/backend/src/server/api/endpoints/drive/stream.ts
+++ b/packages/backend/src/server/api/endpoints/drive/stream.ts
@@ -41,6 +41,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(DriveFiles.createQueryBuilder('file'), ps.sinceId, ps.untilId)
 		.andWhere('file.userId = :userId', { userId: user.id });
diff --git a/packages/backend/src/server/api/endpoints/email-address/available.ts b/packages/backend/src/server/api/endpoints/email-address/available.ts
index f2254e148..5e8f1706f 100644
--- a/packages/backend/src/server/api/endpoints/email-address/available.ts
+++ b/packages/backend/src/server/api/endpoints/email-address/available.ts
@@ -29,6 +29,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	return await validateEmailForAccount(ps.emailAddress);
 });
diff --git a/packages/backend/src/server/api/endpoints/endpoint.ts b/packages/backend/src/server/api/endpoints/endpoint.ts
index eacee689d..597911da8 100644
--- a/packages/backend/src/server/api/endpoints/endpoint.ts
+++ b/packages/backend/src/server/api/endpoints/endpoint.ts
@@ -14,6 +14,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const ep = endpoints.find(x => x.name === ps.endpoint);
 	if (ep == null) return null;
diff --git a/packages/backend/src/server/api/endpoints/endpoints.ts b/packages/backend/src/server/api/endpoints/endpoints.ts
index 6d4588383..4e304dbeb 100644
--- a/packages/backend/src/server/api/endpoints/endpoints.ts
+++ b/packages/backend/src/server/api/endpoints/endpoints.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	return endpoints.map(x => x.name);
 });
diff --git a/packages/backend/src/server/api/endpoints/export-custom-emojis.ts b/packages/backend/src/server/api/endpoints/export-custom-emojis.ts
index 92738c828..8b7e8a049 100644
--- a/packages/backend/src/server/api/endpoints/export-custom-emojis.ts
+++ b/packages/backend/src/server/api/endpoints/export-custom-emojis.ts
@@ -12,6 +12,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	createExportCustomEmojisJob(user);
 });
diff --git a/packages/backend/src/server/api/endpoints/federation/dns.ts b/packages/backend/src/server/api/endpoints/federation/dns.ts
index 19e3ef805..76084ad08 100644
--- a/packages/backend/src/server/api/endpoints/federation/dns.ts
+++ b/packages/backend/src/server/api/endpoints/federation/dns.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const instance = await Instances.findOneOrFail({ host: toPuny(ps.host) });
 
diff --git a/packages/backend/src/server/api/endpoints/federation/followers.ts b/packages/backend/src/server/api/endpoints/federation/followers.ts
index 9cb4082bb..a44b0aecf 100644
--- a/packages/backend/src/server/api/endpoints/federation/followers.ts
+++ b/packages/backend/src/server/api/endpoints/federation/followers.ts
@@ -39,6 +39,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId)
 		.andWhere(`following.followeeHost = :host`, { host: ps.host });
diff --git a/packages/backend/src/server/api/endpoints/federation/following.ts b/packages/backend/src/server/api/endpoints/federation/following.ts
index 4a42550f9..c10e25864 100644
--- a/packages/backend/src/server/api/endpoints/federation/following.ts
+++ b/packages/backend/src/server/api/endpoints/federation/following.ts
@@ -39,6 +39,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(Followings.createQueryBuilder('following'), ps.sinceId, ps.untilId)
 		.andWhere(`following.followerHost = :host`, { host: ps.host });
diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts
index 50d9ff3fd..e73d0e5ad 100644
--- a/packages/backend/src/server/api/endpoints/federation/instances.ts
+++ b/packages/backend/src/server/api/endpoints/federation/instances.ts
@@ -64,6 +64,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = Instances.createQueryBuilder('instance');
 
diff --git a/packages/backend/src/server/api/endpoints/federation/show-instance.ts b/packages/backend/src/server/api/endpoints/federation/show-instance.ts
index 9d5d9bc9f..15b4f3151 100644
--- a/packages/backend/src/server/api/endpoints/federation/show-instance.ts
+++ b/packages/backend/src/server/api/endpoints/federation/show-instance.ts
@@ -21,6 +21,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const instance = await Instances
 		.findOne({ host: toPuny(ps.host) });
diff --git a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts
index 2ba09b136..371859345 100644
--- a/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts
+++ b/packages/backend/src/server/api/endpoints/federation/update-remote-user.ts
@@ -16,6 +16,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const user = await getRemoteUser(ps.userId);
 	await updatePerson(user.uri!);
diff --git a/packages/backend/src/server/api/endpoints/federation/users.ts b/packages/backend/src/server/api/endpoints/federation/users.ts
index 730dbd74c..8372169d6 100644
--- a/packages/backend/src/server/api/endpoints/federation/users.ts
+++ b/packages/backend/src/server/api/endpoints/federation/users.ts
@@ -39,6 +39,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(Users.createQueryBuilder('user'), ps.sinceId, ps.untilId)
 		.andWhere(`user.host = :host`, { host: ps.host });
diff --git a/packages/backend/src/server/api/endpoints/following/create.ts b/packages/backend/src/server/api/endpoints/following/create.ts
index 096b1f605..951cf8fa2 100644
--- a/packages/backend/src/server/api/endpoints/following/create.ts
+++ b/packages/backend/src/server/api/endpoints/following/create.ts
@@ -64,6 +64,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const follower = user;
 
diff --git a/packages/backend/src/server/api/endpoints/following/delete.ts b/packages/backend/src/server/api/endpoints/following/delete.ts
index 5a0e44ad0..de43fa438 100644
--- a/packages/backend/src/server/api/endpoints/following/delete.ts
+++ b/packages/backend/src/server/api/endpoints/following/delete.ts
@@ -52,6 +52,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const follower = user;
 
diff --git a/packages/backend/src/server/api/endpoints/following/invalidate.ts b/packages/backend/src/server/api/endpoints/following/invalidate.ts
index 050199bfa..388ddda79 100644
--- a/packages/backend/src/server/api/endpoints/following/invalidate.ts
+++ b/packages/backend/src/server/api/endpoints/following/invalidate.ts
@@ -52,6 +52,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const followee = user;
 
diff --git a/packages/backend/src/server/api/endpoints/following/requests/accept.ts b/packages/backend/src/server/api/endpoints/following/requests/accept.ts
index 9c0724856..29f0ace2a 100644
--- a/packages/backend/src/server/api/endpoints/following/requests/accept.ts
+++ b/packages/backend/src/server/api/endpoints/following/requests/accept.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch follower
 	const follower = await getUser(ps.userId).catch(e => {
diff --git a/packages/backend/src/server/api/endpoints/following/requests/cancel.ts b/packages/backend/src/server/api/endpoints/following/requests/cancel.ts
index d65aa436a..d5281c468 100644
--- a/packages/backend/src/server/api/endpoints/following/requests/cancel.ts
+++ b/packages/backend/src/server/api/endpoints/following/requests/cancel.ts
@@ -40,6 +40,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch followee
 	const followee = await getUser(ps.userId).catch(e => {
diff --git a/packages/backend/src/server/api/endpoints/following/requests/list.ts b/packages/backend/src/server/api/endpoints/following/requests/list.ts
index 2dadd0d60..bfd793faf 100644
--- a/packages/backend/src/server/api/endpoints/following/requests/list.ts
+++ b/packages/backend/src/server/api/endpoints/following/requests/list.ts
@@ -35,6 +35,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const reqs = await FollowRequests.find({
 		followeeId: user.id,
diff --git a/packages/backend/src/server/api/endpoints/following/requests/reject.ts b/packages/backend/src/server/api/endpoints/following/requests/reject.ts
index c385b3238..77a14af1f 100644
--- a/packages/backend/src/server/api/endpoints/following/requests/reject.ts
+++ b/packages/backend/src/server/api/endpoints/following/requests/reject.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch follower
 	const follower = await getUser(ps.userId).catch(e => {
diff --git a/packages/backend/src/server/api/endpoints/gallery/featured.ts b/packages/backend/src/server/api/endpoints/gallery/featured.ts
index dc86cf40b..a6ca95692 100644
--- a/packages/backend/src/server/api/endpoints/gallery/featured.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/featured.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = GalleryPosts.createQueryBuilder('post')
 		.andWhere('post.createdAt > :date', { date: new Date(Date.now() - (1000 * 60 * 60 * 24 * 3)) })
diff --git a/packages/backend/src/server/api/endpoints/gallery/popular.ts b/packages/backend/src/server/api/endpoints/gallery/popular.ts
index ee3fe51eb..efd1f7605 100644
--- a/packages/backend/src/server/api/endpoints/gallery/popular.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/popular.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = GalleryPosts.createQueryBuilder('post')
 		.andWhere('post.likedCount > 0')
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts.ts b/packages/backend/src/server/api/endpoints/gallery/posts.ts
index 90bd2d959..1b1368b06 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts.ts
@@ -33,6 +33,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId)
 		.innerJoinAndSelect('post.user', 'user');
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts
index dae6e27dd..1a75ba2cb 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts
@@ -50,6 +50,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const files = (await Promise.all(ps.fileIds.map(fileId =>
 		DriveFiles.findOne({
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts
index e43c12a4c..dbf7b2f9c 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/delete.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const post = await GalleryPosts.findOne({
 		id: ps.postId,
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
index d355d1e31..2f98f41fa 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/like.ts
@@ -39,6 +39,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const post = await GalleryPosts.findOne(ps.postId);
 	if (post == null) {
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts
index 7e620b2c4..7044f948f 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts
@@ -30,6 +30,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const post = await GalleryPosts.findOne({
 		id: ps.postId,
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts
index 323e7c482..8cf4f3425 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/unlike.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const post = await GalleryPosts.findOne(ps.postId);
 	if (post == null) {
diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts
index 7cd694e80..67028125d 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/update.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/update.ts
@@ -53,6 +53,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const files = (await Promise.all(ps.fileIds.map(fileId =>
 		DriveFiles.findOne({
diff --git a/packages/backend/src/server/api/endpoints/games/reversi/games.ts b/packages/backend/src/server/api/endpoints/games/reversi/games.ts
index f77f11942..8b0e812ca 100644
--- a/packages/backend/src/server/api/endpoints/games/reversi/games.ts
+++ b/packages/backend/src/server/api/endpoints/games/reversi/games.ts
@@ -136,6 +136,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(ReversiGames.createQueryBuilder('game'), ps.sinceId, ps.untilId)
 		.andWhere('game.isStarted = TRUE');
diff --git a/packages/backend/src/server/api/endpoints/games/reversi/games/show.ts b/packages/backend/src/server/api/endpoints/games/reversi/games/show.ts
index 0476a4be9..020e9e6fc 100644
--- a/packages/backend/src/server/api/endpoints/games/reversi/games/show.ts
+++ b/packages/backend/src/server/api/endpoints/games/reversi/games/show.ts
@@ -142,6 +142,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const game = await ReversiGames.findOne(ps.gameId);
 
diff --git a/packages/backend/src/server/api/endpoints/games/reversi/games/surrender.ts b/packages/backend/src/server/api/endpoints/games/reversi/games/surrender.ts
index 84b80c47a..a0eb4705b 100644
--- a/packages/backend/src/server/api/endpoints/games/reversi/games/surrender.ts
+++ b/packages/backend/src/server/api/endpoints/games/reversi/games/surrender.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const game = await ReversiGames.findOne(ps.gameId);
 
diff --git a/packages/backend/src/server/api/endpoints/games/reversi/invitations.ts b/packages/backend/src/server/api/endpoints/games/reversi/invitations.ts
index b859a2fc7..0285a2f63 100644
--- a/packages/backend/src/server/api/endpoints/games/reversi/invitations.ts
+++ b/packages/backend/src/server/api/endpoints/games/reversi/invitations.ts
@@ -48,6 +48,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Find session
 	const invitations = await ReversiMatchings.find({
diff --git a/packages/backend/src/server/api/endpoints/games/reversi/match.ts b/packages/backend/src/server/api/endpoints/games/reversi/match.ts
index c66c5a4f7..b1d958306 100644
--- a/packages/backend/src/server/api/endpoints/games/reversi/match.ts
+++ b/packages/backend/src/server/api/endpoints/games/reversi/match.ts
@@ -36,6 +36,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Myself
 	if (ps.userId === user.id) {
diff --git a/packages/backend/src/server/api/endpoints/games/reversi/match/cancel.ts b/packages/backend/src/server/api/endpoints/games/reversi/match/cancel.ts
index 8076b7c5d..3ef753bcd 100644
--- a/packages/backend/src/server/api/endpoints/games/reversi/match/cancel.ts
+++ b/packages/backend/src/server/api/endpoints/games/reversi/match/cancel.ts
@@ -7,6 +7,7 @@ export const meta = {
 	requireCredential: true as const,
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	await ReversiMatchings.delete({
 		parentId: user.id,
diff --git a/packages/backend/src/server/api/endpoints/get-online-users-count.ts b/packages/backend/src/server/api/endpoints/get-online-users-count.ts
index 0616431ab..b429eacef 100644
--- a/packages/backend/src/server/api/endpoints/get-online-users-count.ts
+++ b/packages/backend/src/server/api/endpoints/get-online-users-count.ts
@@ -12,6 +12,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	const count = await Users.count({
 		lastActiveDate: MoreThan(new Date(Date.now() - USER_ONLINE_THRESHOLD)),
diff --git a/packages/backend/src/server/api/endpoints/hashtags/list.ts b/packages/backend/src/server/api/endpoints/hashtags/list.ts
index 5f8bfee2d..3900fdcc4 100644
--- a/packages/backend/src/server/api/endpoints/hashtags/list.ts
+++ b/packages/backend/src/server/api/endpoints/hashtags/list.ts
@@ -57,6 +57,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = Hashtags.createQueryBuilder('tag');
 
diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts
index d7de1db55..8642bb39f 100644
--- a/packages/backend/src/server/api/endpoints/hashtags/search.ts
+++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts
@@ -33,6 +33,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const hashtags = await Hashtags.createQueryBuilder('tag')
 		.where('tag.name like :q', { q: ps.query.toLowerCase() + '%' })
diff --git a/packages/backend/src/server/api/endpoints/hashtags/show.ts b/packages/backend/src/server/api/endpoints/hashtags/show.ts
index 9410aea38..454b98e5a 100644
--- a/packages/backend/src/server/api/endpoints/hashtags/show.ts
+++ b/packages/backend/src/server/api/endpoints/hashtags/show.ts
@@ -30,6 +30,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const hashtag = await Hashtags.findOne({ name: normalizeForSearch(ps.tag) });
 	if (hashtag == null) {
diff --git a/packages/backend/src/server/api/endpoints/hashtags/trend.ts b/packages/backend/src/server/api/endpoints/hashtags/trend.ts
index deb8417ad..e02666a88 100644
--- a/packages/backend/src/server/api/endpoints/hashtags/trend.ts
+++ b/packages/backend/src/server/api/endpoints/hashtags/trend.ts
@@ -53,6 +53,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	const instance = await fetchMeta(true);
 	const hiddenTags = instance.hiddenTags.map(t => normalizeForSearch(t));
diff --git a/packages/backend/src/server/api/endpoints/hashtags/users.ts b/packages/backend/src/server/api/endpoints/hashtags/users.ts
index 69b17a19e..6bbe87a0d 100644
--- a/packages/backend/src/server/api/endpoints/hashtags/users.ts
+++ b/packages/backend/src/server/api/endpoints/hashtags/users.ts
@@ -58,6 +58,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = Users.createQueryBuilder('user')
 		.where(':tag = ANY(user.tags)', { tag: normalizeForSearch(ps.tag) });
diff --git a/packages/backend/src/server/api/endpoints/i.ts b/packages/backend/src/server/api/endpoints/i.ts
index 2063a55a8..e5a2c9d2f 100644
--- a/packages/backend/src/server/api/endpoints/i.ts
+++ b/packages/backend/src/server/api/endpoints/i.ts
@@ -15,6 +15,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user, token) => {
 	const isSecure = token == null;
 
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/done.ts b/packages/backend/src/server/api/endpoints/i/2fa/done.ts
index 3b772386f..f6c5ac33a 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/done.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/done.ts
@@ -15,6 +15,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const token = ps.token.replace(/\s/g, '');
 
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
index f0045fb99..cd1f16e54 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/key-done.ts
@@ -41,6 +41,7 @@ export const meta = {
 
 const rpIdHashReal = hash(Buffer.from(config.hostname, 'utf-8'));
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts
index dc2b66286..9eecbb3dc 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/password-less.ts
@@ -14,6 +14,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	await UserProfiles.update(user.id, {
 		usePasswordLessLogin: ps.value,
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts
index aa6c8fb1d..19294d15a 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/register-key.ts
@@ -21,6 +21,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/register.ts b/packages/backend/src/server/api/endpoints/i/2fa/register.ts
index 347dec0f4..0fe824a6e 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/register.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/register.ts
@@ -18,6 +18,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
index 05d63452f..b9a635423 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/remove-key.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
index a0d8b5906..0e7014d3f 100644
--- a/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
+++ b/packages/backend/src/server/api/endpoints/i/2fa/unregister.ts
@@ -15,6 +15,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/i/apps.ts b/packages/backend/src/server/api/endpoints/i/apps.ts
index 64986865b..6c71a071f 100644
--- a/packages/backend/src/server/api/endpoints/i/apps.ts
+++ b/packages/backend/src/server/api/endpoints/i/apps.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = AccessTokens.createQueryBuilder('token')
 		.where('token.userId = :userId', { userId: user.id });
diff --git a/packages/backend/src/server/api/endpoints/i/authorized-apps.ts b/packages/backend/src/server/api/endpoints/i/authorized-apps.ts
index bfe20eb98..127a272c4 100644
--- a/packages/backend/src/server/api/endpoints/i/authorized-apps.ts
+++ b/packages/backend/src/server/api/endpoints/i/authorized-apps.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Get tokens
 	const tokens = await AccessTokens.find({
diff --git a/packages/backend/src/server/api/endpoints/i/change-password.ts b/packages/backend/src/server/api/endpoints/i/change-password.ts
index 416eb6229..5ba7a2a87 100644
--- a/packages/backend/src/server/api/endpoints/i/change-password.ts
+++ b/packages/backend/src/server/api/endpoints/i/change-password.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/i/delete-account.ts b/packages/backend/src/server/api/endpoints/i/delete-account.ts
index 13a8f79df..bfbf2e5e5 100644
--- a/packages/backend/src/server/api/endpoints/i/delete-account.ts
+++ b/packages/backend/src/server/api/endpoints/i/delete-account.ts
@@ -18,6 +18,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 	const userDetailed = await Users.findOneOrFail(user.id);
diff --git a/packages/backend/src/server/api/endpoints/i/export-blocking.ts b/packages/backend/src/server/api/endpoints/i/export-blocking.ts
index e276ecf38..4f2143475 100644
--- a/packages/backend/src/server/api/endpoints/i/export-blocking.ts
+++ b/packages/backend/src/server/api/endpoints/i/export-blocking.ts
@@ -11,6 +11,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	createExportBlockingJob(user);
 });
diff --git a/packages/backend/src/server/api/endpoints/i/export-following.ts b/packages/backend/src/server/api/endpoints/i/export-following.ts
index 15c09941e..4b2f4c86a 100644
--- a/packages/backend/src/server/api/endpoints/i/export-following.ts
+++ b/packages/backend/src/server/api/endpoints/i/export-following.ts
@@ -22,6 +22,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	createExportFollowingJob(user, ps.excludeMuting, ps.excludeInactive);
 });
diff --git a/packages/backend/src/server/api/endpoints/i/export-mute.ts b/packages/backend/src/server/api/endpoints/i/export-mute.ts
index b176c7ee8..1f655c511 100644
--- a/packages/backend/src/server/api/endpoints/i/export-mute.ts
+++ b/packages/backend/src/server/api/endpoints/i/export-mute.ts
@@ -11,6 +11,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	createExportMuteJob(user);
 });
diff --git a/packages/backend/src/server/api/endpoints/i/export-notes.ts b/packages/backend/src/server/api/endpoints/i/export-notes.ts
index 8cba04552..aa3d7955f 100644
--- a/packages/backend/src/server/api/endpoints/i/export-notes.ts
+++ b/packages/backend/src/server/api/endpoints/i/export-notes.ts
@@ -11,6 +11,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	createExportNotesJob(user);
 });
diff --git a/packages/backend/src/server/api/endpoints/i/export-user-lists.ts b/packages/backend/src/server/api/endpoints/i/export-user-lists.ts
index 44d43c0be..e135ba103 100644
--- a/packages/backend/src/server/api/endpoints/i/export-user-lists.ts
+++ b/packages/backend/src/server/api/endpoints/i/export-user-lists.ts
@@ -11,6 +11,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	createExportUserListsJob(user);
 });
diff --git a/packages/backend/src/server/api/endpoints/i/favorites.ts b/packages/backend/src/server/api/endpoints/i/favorites.ts
index 49b0bcd46..2ae5aa87a 100644
--- a/packages/backend/src/server/api/endpoints/i/favorites.ts
+++ b/packages/backend/src/server/api/endpoints/i/favorites.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(NoteFavorites.createQueryBuilder('favorite'), ps.sinceId, ps.untilId)
 		.andWhere(`favorite.userId = :meId`, { meId: user.id })
diff --git a/packages/backend/src/server/api/endpoints/i/gallery/likes.ts b/packages/backend/src/server/api/endpoints/i/gallery/likes.ts
index 3ee7174f7..ebcb459c6 100644
--- a/packages/backend/src/server/api/endpoints/i/gallery/likes.ts
+++ b/packages/backend/src/server/api/endpoints/i/gallery/likes.ts
@@ -44,6 +44,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(GalleryLikes.createQueryBuilder('like'), ps.sinceId, ps.untilId)
 		.andWhere(`like.userId = :meId`, { meId: user.id })
diff --git a/packages/backend/src/server/api/endpoints/i/gallery/posts.ts b/packages/backend/src/server/api/endpoints/i/gallery/posts.ts
index c8aceb8bf..bb77484da 100644
--- a/packages/backend/src/server/api/endpoints/i/gallery/posts.ts
+++ b/packages/backend/src/server/api/endpoints/i/gallery/posts.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId)
 		.andWhere(`post.userId = :meId`, { meId: user.id });
diff --git a/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts b/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts
index 3eddc2746..93c832116 100644
--- a/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts
+++ b/packages/backend/src/server/api/endpoints/i/get-word-muted-notes-count.ts
@@ -23,6 +23,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	return {
 		count: await MutedNotes.count({
diff --git a/packages/backend/src/server/api/endpoints/i/import-blocking.ts b/packages/backend/src/server/api/endpoints/i/import-blocking.ts
index f0e3106c5..6b5100c21 100644
--- a/packages/backend/src/server/api/endpoints/i/import-blocking.ts
+++ b/packages/backend/src/server/api/endpoints/i/import-blocking.ts
@@ -48,6 +48,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const file = await DriveFiles.findOne(ps.fileId);
 
diff --git a/packages/backend/src/server/api/endpoints/i/import-following.ts b/packages/backend/src/server/api/endpoints/i/import-following.ts
index 61e500599..a0ab45b0a 100644
--- a/packages/backend/src/server/api/endpoints/i/import-following.ts
+++ b/packages/backend/src/server/api/endpoints/i/import-following.ts
@@ -47,6 +47,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const file = await DriveFiles.findOne(ps.fileId);
 
diff --git a/packages/backend/src/server/api/endpoints/i/import-muting.ts b/packages/backend/src/server/api/endpoints/i/import-muting.ts
index da26617d9..b5878f4f5 100644
--- a/packages/backend/src/server/api/endpoints/i/import-muting.ts
+++ b/packages/backend/src/server/api/endpoints/i/import-muting.ts
@@ -48,6 +48,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const file = await DriveFiles.findOne(ps.fileId);
 
diff --git a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts
index 1b850d314..563ecf38e 100644
--- a/packages/backend/src/server/api/endpoints/i/import-user-lists.ts
+++ b/packages/backend/src/server/api/endpoints/i/import-user-lists.ts
@@ -47,6 +47,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const file = await DriveFiles.findOne(ps.fileId);
 
diff --git a/packages/backend/src/server/api/endpoints/i/notifications.ts b/packages/backend/src/server/api/endpoints/i/notifications.ts
index 9083aefac..f02e94f32 100644
--- a/packages/backend/src/server/api/endpoints/i/notifications.ts
+++ b/packages/backend/src/server/api/endpoints/i/notifications.ts
@@ -65,6 +65,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// includeTypes が空の場合はクエリしない
 	if (ps.includeTypes && ps.includeTypes.length === 0) {
diff --git a/packages/backend/src/server/api/endpoints/i/page-likes.ts b/packages/backend/src/server/api/endpoints/i/page-likes.ts
index 92fc29485..7b8f4864f 100644
--- a/packages/backend/src/server/api/endpoints/i/page-likes.ts
+++ b/packages/backend/src/server/api/endpoints/i/page-likes.ts
@@ -44,6 +44,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(PageLikes.createQueryBuilder('like'), ps.sinceId, ps.untilId)
 		.andWhere(`like.userId = :meId`, { meId: user.id })
diff --git a/packages/backend/src/server/api/endpoints/i/pages.ts b/packages/backend/src/server/api/endpoints/i/pages.ts
index 5948712c3..78de9e2bf 100644
--- a/packages/backend/src/server/api/endpoints/i/pages.ts
+++ b/packages/backend/src/server/api/endpoints/i/pages.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId)
 		.andWhere(`page.userId = :meId`, { meId: user.id });
diff --git a/packages/backend/src/server/api/endpoints/i/pin.ts b/packages/backend/src/server/api/endpoints/i/pin.ts
index 5fc49d651..9fc73908a 100644
--- a/packages/backend/src/server/api/endpoints/i/pin.ts
+++ b/packages/backend/src/server/api/endpoints/i/pin.ts
@@ -45,6 +45,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	await addPinned(user, ps.noteId).catch(e => {
 		if (e.id === '70c4e51f-5bea-449c-a030-53bee3cce202') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/i/read-all-messaging-messages.ts b/packages/backend/src/server/api/endpoints/i/read-all-messaging-messages.ts
index a66d6bac7..26c1abced 100644
--- a/packages/backend/src/server/api/endpoints/i/read-all-messaging-messages.ts
+++ b/packages/backend/src/server/api/endpoints/i/read-all-messaging-messages.ts
@@ -13,6 +13,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Update documents
 	await MessagingMessages.update({
diff --git a/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts b/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts
index 90f555763..44c32a9ee 100644
--- a/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts
+++ b/packages/backend/src/server/api/endpoints/i/read-all-unread-notes.ts
@@ -13,6 +13,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Remove documents
 	await NoteUnreads.delete({
diff --git a/packages/backend/src/server/api/endpoints/i/read-announcement.ts b/packages/backend/src/server/api/endpoints/i/read-announcement.ts
index d948f3efd..5814c5c3c 100644
--- a/packages/backend/src/server/api/endpoints/i/read-announcement.ts
+++ b/packages/backend/src/server/api/endpoints/i/read-announcement.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Check if announcement exists
 	const announcement = await Announcements.findOne(ps.announcementId);
diff --git a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts
index f7e910154..13dbd7bd5 100644
--- a/packages/backend/src/server/api/endpoints/i/regenerate-token.ts
+++ b/packages/backend/src/server/api/endpoints/i/regenerate-token.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-all.ts b/packages/backend/src/server/api/endpoints/i/registry/get-all.ts
index 1599ccea6..0f36d3f50 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/get-all.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/get-all.ts
@@ -15,6 +15,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = RegistryItems.createQueryBuilder('item')
 		.where('item.domain IS NULL')
diff --git a/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts b/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts
index 4edeae9e9..36d845207 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/get-detail.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = RegistryItems.createQueryBuilder('item')
 		.where('item.domain IS NULL')
diff --git a/packages/backend/src/server/api/endpoints/i/registry/get.ts b/packages/backend/src/server/api/endpoints/i/registry/get.ts
index aa0695281..e1b80035b 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/get.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/get.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = RegistryItems.createQueryBuilder('item')
 		.where('item.domain IS NULL')
diff --git a/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts b/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts
index 9cac50353..53ff7b136 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/keys-with-type.ts
@@ -15,6 +15,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = RegistryItems.createQueryBuilder('item')
 		.where('item.domain IS NULL')
diff --git a/packages/backend/src/server/api/endpoints/i/registry/keys.ts b/packages/backend/src/server/api/endpoints/i/registry/keys.ts
index 215ccbd5b..40ae094d5 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/keys.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/keys.ts
@@ -15,6 +15,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = RegistryItems.createQueryBuilder('item')
 		.select('item.key')
diff --git a/packages/backend/src/server/api/endpoints/i/registry/remove.ts b/packages/backend/src/server/api/endpoints/i/registry/remove.ts
index 17ce5851c..bea9be73e 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/remove.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/remove.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = RegistryItems.createQueryBuilder('item')
 		.where('item.domain IS NULL')
diff --git a/packages/backend/src/server/api/endpoints/i/registry/scopes.ts b/packages/backend/src/server/api/endpoints/i/registry/scopes.ts
index 45aeb5977..c7596f48f 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/scopes.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/scopes.ts
@@ -10,6 +10,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = RegistryItems.createQueryBuilder('item')
 		.select('item.scope')
diff --git a/packages/backend/src/server/api/endpoints/i/registry/set.ts b/packages/backend/src/server/api/endpoints/i/registry/set.ts
index 7c282064c..c373b1a21 100644
--- a/packages/backend/src/server/api/endpoints/i/registry/set.ts
+++ b/packages/backend/src/server/api/endpoints/i/registry/set.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = RegistryItems.createQueryBuilder('item')
 		.where('item.domain IS NULL')
diff --git a/packages/backend/src/server/api/endpoints/i/revoke-token.ts b/packages/backend/src/server/api/endpoints/i/revoke-token.ts
index 1b6b18aa8..acef3a58e 100644
--- a/packages/backend/src/server/api/endpoints/i/revoke-token.ts
+++ b/packages/backend/src/server/api/endpoints/i/revoke-token.ts
@@ -16,6 +16,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const token = await AccessTokens.findOne(ps.tokenId);
 
diff --git a/packages/backend/src/server/api/endpoints/i/signin-history.ts b/packages/backend/src/server/api/endpoints/i/signin-history.ts
index 6f2f8fc8c..deb131547 100644
--- a/packages/backend/src/server/api/endpoints/i/signin-history.ts
+++ b/packages/backend/src/server/api/endpoints/i/signin-history.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(Signins.createQueryBuilder('signin'), ps.sinceId, ps.untilId)
 		.andWhere(`signin.userId = :meId`, { meId: user.id });
diff --git a/packages/backend/src/server/api/endpoints/i/unpin.ts b/packages/backend/src/server/api/endpoints/i/unpin.ts
index c1b753bfa..8182254ac 100644
--- a/packages/backend/src/server/api/endpoints/i/unpin.ts
+++ b/packages/backend/src/server/api/endpoints/i/unpin.ts
@@ -33,6 +33,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	await removePinned(user, ps.noteId).catch(e => {
 		if (e.id === 'b302d4cf-c050-400a-bbb3-be208681f40c') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/i/update-email.ts b/packages/backend/src/server/api/endpoints/i/update-email.ts
index d99fa2474..19bf80248 100644
--- a/packages/backend/src/server/api/endpoints/i/update-email.ts
+++ b/packages/backend/src/server/api/endpoints/i/update-email.ts
@@ -45,6 +45,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const profile = await UserProfiles.findOneOrFail(user.id);
 
diff --git a/packages/backend/src/server/api/endpoints/i/update.ts b/packages/backend/src/server/api/endpoints/i/update.ts
index 5a62b3937..3c6050efd 100644
--- a/packages/backend/src/server/api/endpoints/i/update.ts
+++ b/packages/backend/src/server/api/endpoints/i/update.ts
@@ -168,6 +168,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, _user, token) => {
 	const user = await Users.findOneOrFail(_user.id);
 	const isSecure = token == null;
diff --git a/packages/backend/src/server/api/endpoints/i/user-group-invites.ts b/packages/backend/src/server/api/endpoints/i/user-group-invites.ts
index 6949e486a..cbe3f64a2 100644
--- a/packages/backend/src/server/api/endpoints/i/user-group-invites.ts
+++ b/packages/backend/src/server/api/endpoints/i/user-group-invites.ts
@@ -48,6 +48,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(UserGroupInvitations.createQueryBuilder('invitation'), ps.sinceId, ps.untilId)
 		.andWhere(`invitation.userId = :meId`, { meId: user.id })
diff --git a/packages/backend/src/server/api/endpoints/messaging/history.ts b/packages/backend/src/server/api/endpoints/messaging/history.ts
index 4ca3d6ebe..ca5b1d06a 100644
--- a/packages/backend/src/server/api/endpoints/messaging/history.ts
+++ b/packages/backend/src/server/api/endpoints/messaging/history.ts
@@ -34,6 +34,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const mute = await Mutings.find({
 		muterId: user.id,
diff --git a/packages/backend/src/server/api/endpoints/messaging/messages.ts b/packages/backend/src/server/api/endpoints/messaging/messages.ts
index 79e776424..9332695fd 100644
--- a/packages/backend/src/server/api/endpoints/messaging/messages.ts
+++ b/packages/backend/src/server/api/endpoints/messaging/messages.ts
@@ -74,6 +74,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	if (ps.userId != null) {
 		// Fetch recipient (user)
diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts
index 02b22ead8..609274667 100644
--- a/packages/backend/src/server/api/endpoints/messaging/messages/create.ts
+++ b/packages/backend/src/server/api/endpoints/messaging/messages/create.ts
@@ -84,6 +84,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	let recipientUser: User | undefined;
 	let recipientGroup: UserGroup | undefined;
diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts
index dd1c2e8de..7362f705e 100644
--- a/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts
+++ b/packages/backend/src/server/api/endpoints/messaging/messages/delete.ts
@@ -34,6 +34,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const message = await MessagingMessages.findOne({
 		id: ps.messageId,
diff --git a/packages/backend/src/server/api/endpoints/messaging/messages/read.ts b/packages/backend/src/server/api/endpoints/messaging/messages/read.ts
index 96d68b260..c698f3979 100644
--- a/packages/backend/src/server/api/endpoints/messaging/messages/read.ts
+++ b/packages/backend/src/server/api/endpoints/messaging/messages/read.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const message = await MessagingMessages.findOne(ps.messageId);
 
diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts
index bced077c1..6b07011fd 100644
--- a/packages/backend/src/server/api/endpoints/meta.ts
+++ b/packages/backend/src/server/api/endpoints/meta.ts
@@ -448,6 +448,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const instance = await fetchMeta(true);
 
diff --git a/packages/backend/src/server/api/endpoints/miauth/gen-token.ts b/packages/backend/src/server/api/endpoints/miauth/gen-token.ts
index 29f109f36..cc739a51e 100644
--- a/packages/backend/src/server/api/endpoints/miauth/gen-token.ts
+++ b/packages/backend/src/server/api/endpoints/miauth/gen-token.ts
@@ -45,6 +45,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Generate access token
 	const accessToken = secureRndstr(32, true);
diff --git a/packages/backend/src/server/api/endpoints/mute/create.ts b/packages/backend/src/server/api/endpoints/mute/create.ts
index 703611f67..000e48dde 100644
--- a/packages/backend/src/server/api/endpoints/mute/create.ts
+++ b/packages/backend/src/server/api/endpoints/mute/create.ts
@@ -42,6 +42,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const muter = user;
 
diff --git a/packages/backend/src/server/api/endpoints/mute/delete.ts b/packages/backend/src/server/api/endpoints/mute/delete.ts
index aa8c33d04..c204add1b 100644
--- a/packages/backend/src/server/api/endpoints/mute/delete.ts
+++ b/packages/backend/src/server/api/endpoints/mute/delete.ts
@@ -40,6 +40,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const muter = user;
 
diff --git a/packages/backend/src/server/api/endpoints/mute/list.ts b/packages/backend/src/server/api/endpoints/mute/list.ts
index 48b6ddb06..a736161b9 100644
--- a/packages/backend/src/server/api/endpoints/mute/list.ts
+++ b/packages/backend/src/server/api/endpoints/mute/list.ts
@@ -37,6 +37,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(Mutings.createQueryBuilder('muting'), ps.sinceId, ps.untilId)
 		.andWhere(`muting.muterId = :meId`, { meId: me.id });
diff --git a/packages/backend/src/server/api/endpoints/my/apps.ts b/packages/backend/src/server/api/endpoints/my/apps.ts
index 1164f5f6f..d9443d38d 100644
--- a/packages/backend/src/server/api/endpoints/my/apps.ts
+++ b/packages/backend/src/server/api/endpoints/my/apps.ts
@@ -69,6 +69,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = {
 		userId: user.id,
diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts
index 37d1b03dc..c853996a4 100644
--- a/packages/backend/src/server/api/endpoints/notes.ts
+++ b/packages/backend/src/server/api/endpoints/notes.ts
@@ -53,6 +53,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
 		.andWhere(`note.visibility = 'public'`)
diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts
index acd9d6f7e..d6062f4eb 100644
--- a/packages/backend/src/server/api/endpoints/notes/children.ts
+++ b/packages/backend/src/server/api/endpoints/notes/children.ts
@@ -44,6 +44,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
 		.andWhere(new Brackets(qb => { qb
diff --git a/packages/backend/src/server/api/endpoints/notes/clips.ts b/packages/backend/src/server/api/endpoints/notes/clips.ts
index deb14da16..67bac3670 100644
--- a/packages/backend/src/server/api/endpoints/notes/clips.ts
+++ b/packages/backend/src/server/api/endpoints/notes/clips.ts
@@ -36,6 +36,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts
index 8fdbb7fde..a465b08d3 100644
--- a/packages/backend/src/server/api/endpoints/notes/conversation.ts
+++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts
@@ -46,6 +46,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/create.ts b/packages/backend/src/server/api/endpoints/notes/create.ts
index 9567374c6..ec05e5ea9 100644
--- a/packages/backend/src/server/api/endpoints/notes/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/create.ts
@@ -175,6 +175,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	let visibleUsers: User[] = [];
 	if (ps.visibleUserIds) {
diff --git a/packages/backend/src/server/api/endpoints/notes/delete.ts b/packages/backend/src/server/api/endpoints/notes/delete.ts
index 532213c72..0f6f99c7c 100644
--- a/packages/backend/src/server/api/endpoints/notes/delete.ts
+++ b/packages/backend/src/server/api/endpoints/notes/delete.ts
@@ -41,6 +41,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
index 14191eefd..d5d39c304 100644
--- a/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/favorites/create.ts
@@ -34,6 +34,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Get favoritee
 	const note = await getNote(ps.noteId).catch(e => {
diff --git a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts
index f8d3b6302..62f32633b 100644
--- a/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts
+++ b/packages/backend/src/server/api/endpoints/notes/favorites/delete.ts
@@ -33,6 +33,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Get favoritee
 	const note = await getNote(ps.noteId).catch(e => {
diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts
index 2a14c52ab..8f45b541d 100644
--- a/packages/backend/src/server/api/endpoints/notes/featured.ts
+++ b/packages/backend/src/server/api/endpoints/notes/featured.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const max = 30;
 	const day = 1000 * 60 * 60 * 24 * 3; // 3日前まで
diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
index c3be042bf..14831a127 100644
--- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts
@@ -61,6 +61,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const m = await fetchMeta();
 	if (m.disableGlobalTimeline) {
diff --git a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
index 4a0b9d49d..bac243705 100644
--- a/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/hybrid-timeline.ts
@@ -81,6 +81,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const m = await fetchMeta();
 	if (m.disableLocalTimeline && !user.isAdmin && !user.isModerator) {
diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
index 113268982..334e754d0 100644
--- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts
@@ -72,6 +72,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const m = await fetchMeta();
 	if (m.disableLocalTimeline) {
diff --git a/packages/backend/src/server/api/endpoints/notes/mentions.ts b/packages/backend/src/server/api/endpoints/notes/mentions.ts
index 916209ca7..8ae90233a 100644
--- a/packages/backend/src/server/api/endpoints/notes/mentions.ts
+++ b/packages/backend/src/server/api/endpoints/notes/mentions.ts
@@ -50,6 +50,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const followingQuery = Followings.createQueryBuilder('following')
 		.select('following.followeeId')
diff --git a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts
index 9f133c071..7562c6d7f 100644
--- a/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts
+++ b/packages/backend/src/server/api/endpoints/notes/polls/recommendation.ts
@@ -31,6 +31,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = Polls.createQueryBuilder('poll')
 		.where('poll.userHost IS NULL')
diff --git a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts
index 479034389..a08709e32 100644
--- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts
+++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts
@@ -70,6 +70,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const createdAt = new Date();
 
diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts
index dca6deb06..d29893e20 100644
--- a/packages/backend/src/server/api/endpoints/notes/reactions.ts
+++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts
@@ -59,6 +59,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/create.ts b/packages/backend/src/server/api/endpoints/notes/reactions/create.ts
index 879b32cd0..28403d821 100644
--- a/packages/backend/src/server/api/endpoints/notes/reactions/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/reactions/create.ts
@@ -43,6 +43,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts
index eb9281f7a..2b1ce1e21 100644
--- a/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts
+++ b/packages/backend/src/server/api/endpoints/notes/reactions/delete.ts
@@ -40,6 +40,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts
index d53d72516..abfd928db 100644
--- a/packages/backend/src/server/api/endpoints/notes/renotes.ts
+++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts
@@ -52,6 +52,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/replies.ts b/packages/backend/src/server/api/endpoints/notes/replies.ts
index e39878f4f..12efe94be 100644
--- a/packages/backend/src/server/api/endpoints/notes/replies.ts
+++ b/packages/backend/src/server/api/endpoints/notes/replies.ts
@@ -42,6 +42,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
 		.andWhere('note.replyId = :replyId', { replyId: ps.noteId })
diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
index 2275f7c1a..85daf7e48 100644
--- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
+++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts
@@ -66,6 +66,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId)
 		.innerJoinAndSelect('note.user', 'user')
diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts
index b49ee8719..5ff325895 100644
--- a/packages/backend/src/server/api/endpoints/notes/search.ts
+++ b/packages/backend/src/server/api/endpoints/notes/search.ts
@@ -63,6 +63,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	if (es == null) {
 		const query = makePaginationQuery(Notes.createQueryBuilder('note'), ps.sinceId, ps.untilId);
diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts
index 1f7f84cbe..b645f8679 100644
--- a/packages/backend/src/server/api/endpoints/notes/show.ts
+++ b/packages/backend/src/server/api/endpoints/notes/show.ts
@@ -31,6 +31,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/state.ts b/packages/backend/src/server/api/endpoints/notes/state.ts
index 9673b5a77..5bbe3ec86 100644
--- a/packages/backend/src/server/api/endpoints/notes/state.ts
+++ b/packages/backend/src/server/api/endpoints/notes/state.ts
@@ -34,6 +34,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await Notes.findOneOrFail(ps.noteId);
 
diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts
index dd2f887f0..0bd55f898 100644
--- a/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/create.ts
@@ -29,6 +29,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts b/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts
index d34c99f90..756f1b9fd 100644
--- a/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts
+++ b/packages/backend/src/server/api/endpoints/notes/thread-muting/delete.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/timeline.ts b/packages/backend/src/server/api/endpoints/notes/timeline.ts
index 211b8d4f4..4acfed35e 100644
--- a/packages/backend/src/server/api/endpoints/notes/timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/timeline.ts
@@ -71,6 +71,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const hasFollowing = (await Followings.count({
 		where: {
diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts
index 647ae4efe..98a45ace1 100644
--- a/packages/backend/src/server/api/endpoints/notes/translate.ts
+++ b/packages/backend/src/server/api/endpoints/notes/translate.ts
@@ -38,6 +38,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/unrenote.ts b/packages/backend/src/server/api/endpoints/notes/unrenote.ts
index 3661db4d8..2c1e1c739 100644
--- a/packages/backend/src/server/api/endpoints/notes/unrenote.ts
+++ b/packages/backend/src/server/api/endpoints/notes/unrenote.ts
@@ -35,6 +35,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
index d614ddf45..c3b273937 100644
--- a/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
+++ b/packages/backend/src/server/api/endpoints/notes/user-list-timeline.ts
@@ -78,6 +78,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const list = await UserLists.findOne({
 		id: ps.listId,
diff --git a/packages/backend/src/server/api/endpoints/notes/watching/create.ts b/packages/backend/src/server/api/endpoints/notes/watching/create.ts
index 7f724953d..d55ae2002 100644
--- a/packages/backend/src/server/api/endpoints/notes/watching/create.ts
+++ b/packages/backend/src/server/api/endpoints/notes/watching/create.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notes/watching/delete.ts b/packages/backend/src/server/api/endpoints/notes/watching/delete.ts
index 76a368c51..522ae6360 100644
--- a/packages/backend/src/server/api/endpoints/notes/watching/delete.ts
+++ b/packages/backend/src/server/api/endpoints/notes/watching/delete.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/notifications/create.ts b/packages/backend/src/server/api/endpoints/notifications/create.ts
index e285eae46..f78c6e121 100644
--- a/packages/backend/src/server/api/endpoints/notifications/create.ts
+++ b/packages/backend/src/server/api/endpoints/notifications/create.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user, token) => {
 	createNotification(user.id, 'app', {
 		appAccessTokenId: token ? token.id : null,
diff --git a/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts b/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts
index 963af6cb4..f14a91a3d 100644
--- a/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts
+++ b/packages/backend/src/server/api/endpoints/notifications/mark-all-as-read.ts
@@ -10,6 +10,7 @@ export const meta = {
 	kind: 'write:notifications',
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Update documents
 	await Notifications.update({
diff --git a/packages/backend/src/server/api/endpoints/notifications/read.ts b/packages/backend/src/server/api/endpoints/notifications/read.ts
index 9ff0bbeb8..891bfd30d 100644
--- a/packages/backend/src/server/api/endpoints/notifications/read.ts
+++ b/packages/backend/src/server/api/endpoints/notifications/read.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const notification = await Notifications.findOne({
 		notifieeId: user.id,
diff --git a/packages/backend/src/server/api/endpoints/page-push.ts b/packages/backend/src/server/api/endpoints/page-push.ts
index 421eed5ea..f5da35e78 100644
--- a/packages/backend/src/server/api/endpoints/page-push.ts
+++ b/packages/backend/src/server/api/endpoints/page-push.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const page = await Pages.findOne(ps.pageId);
 	if (page == null) {
diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts
index 441ba5426..65e579e4e 100644
--- a/packages/backend/src/server/api/endpoints/pages/create.ts
+++ b/packages/backend/src/server/api/endpoints/pages/create.ts
@@ -84,6 +84,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	let eyeCatchingImage = null;
 	if (ps.eyeCatchingImageId != null) {
diff --git a/packages/backend/src/server/api/endpoints/pages/delete.ts b/packages/backend/src/server/api/endpoints/pages/delete.ts
index 7a4523769..b3a37446d 100644
--- a/packages/backend/src/server/api/endpoints/pages/delete.ts
+++ b/packages/backend/src/server/api/endpoints/pages/delete.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const page = await Pages.findOne(ps.pageId);
 	if (page == null) {
diff --git a/packages/backend/src/server/api/endpoints/pages/featured.ts b/packages/backend/src/server/api/endpoints/pages/featured.ts
index 1dcfb8dd8..b32964c49 100644
--- a/packages/backend/src/server/api/endpoints/pages/featured.ts
+++ b/packages/backend/src/server/api/endpoints/pages/featured.ts
@@ -17,6 +17,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = Pages.createQueryBuilder('page')
 		.where('page.visibility = \'public\'')
diff --git a/packages/backend/src/server/api/endpoints/pages/like.ts b/packages/backend/src/server/api/endpoints/pages/like.ts
index f48359ab2..deff8cc02 100644
--- a/packages/backend/src/server/api/endpoints/pages/like.ts
+++ b/packages/backend/src/server/api/endpoints/pages/like.ts
@@ -39,6 +39,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const page = await Pages.findOne(ps.pageId);
 	if (page == null) {
diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts
index d94c7457d..4a98ec073 100644
--- a/packages/backend/src/server/api/endpoints/pages/show.ts
+++ b/packages/backend/src/server/api/endpoints/pages/show.ts
@@ -39,6 +39,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	let page: Page | undefined;
 
diff --git a/packages/backend/src/server/api/endpoints/pages/unlike.ts b/packages/backend/src/server/api/endpoints/pages/unlike.ts
index 5a2b68e42..f6e74dcf1 100644
--- a/packages/backend/src/server/api/endpoints/pages/unlike.ts
+++ b/packages/backend/src/server/api/endpoints/pages/unlike.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const page = await Pages.findOne(ps.pageId);
 	if (page == null) {
diff --git a/packages/backend/src/server/api/endpoints/pages/update.ts b/packages/backend/src/server/api/endpoints/pages/update.ts
index f980d9207..06c63706a 100644
--- a/packages/backend/src/server/api/endpoints/pages/update.ts
+++ b/packages/backend/src/server/api/endpoints/pages/update.ts
@@ -90,6 +90,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const page = await Pages.findOne(ps.pageId);
 	if (page == null) {
diff --git a/packages/backend/src/server/api/endpoints/ping.ts b/packages/backend/src/server/api/endpoints/ping.ts
index c8f67981f..2130ce54e 100644
--- a/packages/backend/src/server/api/endpoints/ping.ts
+++ b/packages/backend/src/server/api/endpoints/ping.ts
@@ -20,6 +20,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	return {
 		pong: Date.now(),
diff --git a/packages/backend/src/server/api/endpoints/pinned-users.ts b/packages/backend/src/server/api/endpoints/pinned-users.ts
index 9d8d3963b..548871a02 100644
--- a/packages/backend/src/server/api/endpoints/pinned-users.ts
+++ b/packages/backend/src/server/api/endpoints/pinned-users.ts
@@ -23,6 +23,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const meta = await fetchMeta();
 
diff --git a/packages/backend/src/server/api/endpoints/promo/read.ts b/packages/backend/src/server/api/endpoints/promo/read.ts
index ac3cd9cd0..271d88789 100644
--- a/packages/backend/src/server/api/endpoints/promo/read.ts
+++ b/packages/backend/src/server/api/endpoints/promo/read.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const note = await getNote(ps.noteId).catch(e => {
 		if (e.id === '9725d0ce-ba28-4dde-95a7-2cbb2c15de24') throw new ApiError(meta.errors.noSuchNote);
diff --git a/packages/backend/src/server/api/endpoints/request-reset-password.ts b/packages/backend/src/server/api/endpoints/request-reset-password.ts
index 6caf57222..2a29e5891 100644
--- a/packages/backend/src/server/api/endpoints/request-reset-password.ts
+++ b/packages/backend/src/server/api/endpoints/request-reset-password.ts
@@ -33,6 +33,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	const user = await Users.findOne({
 		usernameLower: ps.username.toLowerCase(),
diff --git a/packages/backend/src/server/api/endpoints/reset-db.ts b/packages/backend/src/server/api/endpoints/reset-db.ts
index f6fd5735d..caae137d7 100644
--- a/packages/backend/src/server/api/endpoints/reset-db.ts
+++ b/packages/backend/src/server/api/endpoints/reset-db.ts
@@ -14,6 +14,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	if (process.env.NODE_ENV !== 'test') throw 'NODE_ENV is not a test';
 
diff --git a/packages/backend/src/server/api/endpoints/reset-password.ts b/packages/backend/src/server/api/endpoints/reset-password.ts
index 706f0a32c..3cf89f375 100644
--- a/packages/backend/src/server/api/endpoints/reset-password.ts
+++ b/packages/backend/src/server/api/endpoints/reset-password.ts
@@ -23,6 +23,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const req = await PasswordResetRequests.findOneOrFail({
 		token: ps.token,
diff --git a/packages/backend/src/server/api/endpoints/room/show.ts b/packages/backend/src/server/api/endpoints/room/show.ts
index ec53982eb..a7193372f 100644
--- a/packages/backend/src/server/api/endpoints/room/show.ts
+++ b/packages/backend/src/server/api/endpoints/room/show.ts
@@ -109,6 +109,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId != null
 		? { id: ps.userId }
diff --git a/packages/backend/src/server/api/endpoints/room/update.ts b/packages/backend/src/server/api/endpoints/room/update.ts
index f9fc2b278..e2b18a8ab 100644
--- a/packages/backend/src/server/api/endpoints/room/update.ts
+++ b/packages/backend/src/server/api/endpoints/room/update.ts
@@ -33,6 +33,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	await UserProfiles.update(user.id, {
 		room: ps.room as any,
diff --git a/packages/backend/src/server/api/endpoints/server-info.ts b/packages/backend/src/server/api/endpoints/server-info.ts
index be502cf24..2613416ee 100644
--- a/packages/backend/src/server/api/endpoints/server-info.ts
+++ b/packages/backend/src/server/api/endpoints/server-info.ts
@@ -14,6 +14,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	const memStats = await si.mem();
 	const fsStats = await si.fsSize();
diff --git a/packages/backend/src/server/api/endpoints/stats.ts b/packages/backend/src/server/api/endpoints/stats.ts
index f47b0d0a2..75f7a9498 100644
--- a/packages/backend/src/server/api/endpoints/stats.ts
+++ b/packages/backend/src/server/api/endpoints/stats.ts
@@ -46,6 +46,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async () => {
 	const [
 		notesCount,
diff --git a/packages/backend/src/server/api/endpoints/sw/register.ts b/packages/backend/src/server/api/endpoints/sw/register.ts
index 973474677..8657a0b77 100644
--- a/packages/backend/src/server/api/endpoints/sw/register.ts
+++ b/packages/backend/src/server/api/endpoints/sw/register.ts
@@ -40,6 +40,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// if already subscribed
 	const exist = await SwSubscriptions.findOne({
diff --git a/packages/backend/src/server/api/endpoints/sw/unregister.ts b/packages/backend/src/server/api/endpoints/sw/unregister.ts
index 24ee861f1..67a2ed0a9 100644
--- a/packages/backend/src/server/api/endpoints/sw/unregister.ts
+++ b/packages/backend/src/server/api/endpoints/sw/unregister.ts
@@ -14,6 +14,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	await SwSubscriptions.delete({
 		userId: user.id,
diff --git a/packages/backend/src/server/api/endpoints/username/available.ts b/packages/backend/src/server/api/endpoints/username/available.ts
index f1b46a2b6..ede03eeb1 100644
--- a/packages/backend/src/server/api/endpoints/username/available.ts
+++ b/packages/backend/src/server/api/endpoints/username/available.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
 	// Get exist
 	const exist = await Users.count({
diff --git a/packages/backend/src/server/api/endpoints/users.ts b/packages/backend/src/server/api/endpoints/users.ts
index 601578de2..fdcf59f77 100644
--- a/packages/backend/src/server/api/endpoints/users.ts
+++ b/packages/backend/src/server/api/endpoints/users.ts
@@ -63,6 +63,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = Users.createQueryBuilder('user');
 	query.where('user.isExplorable = TRUE');
diff --git a/packages/backend/src/server/api/endpoints/users/clips.ts b/packages/backend/src/server/api/endpoints/users/clips.ts
index f5964c54d..91da853e6 100644
--- a/packages/backend/src/server/api/endpoints/users/clips.ts
+++ b/packages/backend/src/server/api/endpoints/users/clips.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(Clips.createQueryBuilder('clip'), ps.sinceId, ps.untilId)
 		.andWhere(`clip.userId = :userId`, { userId: ps.userId })
diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts
index 535b10412..d9c0ed762 100644
--- a/packages/backend/src/server/api/endpoints/users/followers.ts
+++ b/packages/backend/src/server/api/endpoints/users/followers.ts
@@ -63,6 +63,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId != null
 		? { id: ps.userId }
diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts
index 58c72bb95..a77fedd68 100644
--- a/packages/backend/src/server/api/endpoints/users/following.ts
+++ b/packages/backend/src/server/api/endpoints/users/following.ts
@@ -63,6 +63,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId != null
 		? { id: ps.userId }
diff --git a/packages/backend/src/server/api/endpoints/users/gallery/posts.ts b/packages/backend/src/server/api/endpoints/users/gallery/posts.ts
index 6ef884ded..bffa4a502 100644
--- a/packages/backend/src/server/api/endpoints/users/gallery/posts.ts
+++ b/packages/backend/src/server/api/endpoints/users/gallery/posts.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(GalleryPosts.createQueryBuilder('post'), ps.sinceId, ps.untilId)
 		.andWhere(`post.userId = :userId`, { userId: ps.userId });
diff --git a/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts b/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts
index a88de7ac8..5852da184 100644
--- a/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts
+++ b/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts
@@ -42,6 +42,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Lookup user
 	const user = await getUser(ps.userId).catch(e => {
diff --git a/packages/backend/src/server/api/endpoints/users/groups/create.ts b/packages/backend/src/server/api/endpoints/users/groups/create.ts
index 12ee11ba5..bbe041122 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/create.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/create.ts
@@ -25,6 +25,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const userGroup = await UserGroups.insert({
 		id: genId(),
diff --git a/packages/backend/src/server/api/endpoints/users/groups/delete.ts b/packages/backend/src/server/api/endpoints/users/groups/delete.ts
index dbc77dd8f..5a38428ca 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/delete.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/delete.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const userGroup = await UserGroups.findOne({
 		id: ps.groupId,
diff --git a/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts b/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts
index fef94c306..45b6c39dc 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/invitations/accept.ts
@@ -28,6 +28,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch the invitation
 	const invitation = await UserGroupInvitations.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts b/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts
index 33a202f02..03ce90aa3 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/invitations/reject.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch the invitation
 	const invitation = await UserGroupInvitations.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/groups/invite.ts b/packages/backend/src/server/api/endpoints/users/groups/invite.ts
index 4dee18fcb..68ce0f1ad 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/invite.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/invite.ts
@@ -52,6 +52,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the group
 	const userGroup = await UserGroups.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/groups/joined.ts b/packages/backend/src/server/api/endpoints/users/groups/joined.ts
index 1bd065ca0..ad18a2f12 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/joined.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/joined.ts
@@ -20,6 +20,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const ownedGroups = await UserGroups.find({
 		userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/users/groups/leave.ts b/packages/backend/src/server/api/endpoints/users/groups/leave.ts
index 9a41175d6..af259d28e 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/leave.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/leave.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the group
 	const userGroup = await UserGroups.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/groups/owned.ts b/packages/backend/src/server/api/endpoints/users/groups/owned.ts
index 69e4c8571..d11d04b84 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/owned.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/owned.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const userGroups = await UserGroups.find({
 		userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/users/groups/pull.ts b/packages/backend/src/server/api/endpoints/users/groups/pull.ts
index 70c1457dc..e4c5d1f9e 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/pull.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/pull.ts
@@ -43,6 +43,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the group
 	const userGroup = await UserGroups.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/groups/show.ts b/packages/backend/src/server/api/endpoints/users/groups/show.ts
index 0bb06f8df..55b86d0e5 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/show.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/show.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the group
 	const userGroup = await UserGroups.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/groups/transfer.ts b/packages/backend/src/server/api/endpoints/users/groups/transfer.ts
index 54cf8197e..6795f1dd2 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/transfer.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/transfer.ts
@@ -49,6 +49,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the group
 	const userGroup = await UserGroups.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/groups/update.ts b/packages/backend/src/server/api/endpoints/users/groups/update.ts
index d16f1ac42..0d188af73 100644
--- a/packages/backend/src/server/api/endpoints/users/groups/update.ts
+++ b/packages/backend/src/server/api/endpoints/users/groups/update.ts
@@ -36,6 +36,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the group
 	const userGroup = await UserGroups.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/lists/create.ts b/packages/backend/src/server/api/endpoints/users/lists/create.ts
index 8372139f8..4c89d1b7e 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/create.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/create.ts
@@ -24,6 +24,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const userList = await UserLists.insert({
 		id: genId(),
diff --git a/packages/backend/src/server/api/endpoints/users/lists/delete.ts b/packages/backend/src/server/api/endpoints/users/lists/delete.ts
index fac4e90db..0f2495dc2 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/delete.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/delete.ts
@@ -26,6 +26,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const userList = await UserLists.findOne({
 		id: ps.listId,
diff --git a/packages/backend/src/server/api/endpoints/users/lists/list.ts b/packages/backend/src/server/api/endpoints/users/lists/list.ts
index 222c930d0..4cf7db69a 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/list.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/list.ts
@@ -19,6 +19,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const userLists = await UserLists.find({
 		userId: me.id,
diff --git a/packages/backend/src/server/api/endpoints/users/lists/pull.ts b/packages/backend/src/server/api/endpoints/users/lists/pull.ts
index 86daa9b2e..980d90c61 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/pull.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/pull.ts
@@ -38,6 +38,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the list
 	const userList = await UserLists.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/lists/push.ts b/packages/backend/src/server/api/endpoints/users/lists/push.ts
index 77ecb4a22..a0ca314f3 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/push.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/push.ts
@@ -50,6 +50,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the list
 	const userList = await UserLists.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/lists/show.ts b/packages/backend/src/server/api/endpoints/users/lists/show.ts
index 9c985bb09..5822c0697 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/show.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/show.ts
@@ -32,6 +32,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Fetch the list
 	const userList = await UserLists.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/lists/update.ts b/packages/backend/src/server/api/endpoints/users/lists/update.ts
index 8a0f96a5d..50fcf6ff5 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/update.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/update.ts
@@ -36,6 +36,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	// Fetch the list
 	const userList = await UserLists.findOne({
diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts
index da8e85811..2069eb60a 100644
--- a/packages/backend/src/server/api/endpoints/users/notes.ts
+++ b/packages/backend/src/server/api/endpoints/users/notes.ts
@@ -84,6 +84,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	// Lookup user
 	const user = await getUser(ps.userId).catch(e => {
diff --git a/packages/backend/src/server/api/endpoints/users/pages.ts b/packages/backend/src/server/api/endpoints/users/pages.ts
index 4763303a7..9fb985dc1 100644
--- a/packages/backend/src/server/api/endpoints/users/pages.ts
+++ b/packages/backend/src/server/api/endpoints/users/pages.ts
@@ -27,6 +27,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, user) => {
 	const query = makePaginationQuery(Pages.createQueryBuilder('page'), ps.sinceId, ps.untilId)
 		.andWhere(`page.userId = :userId`, { userId: ps.userId })
diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts
index 626487176..6f68aca18 100644
--- a/packages/backend/src/server/api/endpoints/users/reactions.ts
+++ b/packages/backend/src/server/api/endpoints/users/reactions.ts
@@ -57,6 +57,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const profile = await UserProfiles.findOneOrFail(ps.userId);
 
diff --git a/packages/backend/src/server/api/endpoints/users/recommendation.ts b/packages/backend/src/server/api/endpoints/users/recommendation.ts
index 71c564c98..5e640330c 100644
--- a/packages/backend/src/server/api/endpoints/users/recommendation.ts
+++ b/packages/backend/src/server/api/endpoints/users/recommendation.ts
@@ -35,6 +35,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const query = Users.createQueryBuilder('user')
 		.where('user.isLocked = FALSE')
diff --git a/packages/backend/src/server/api/endpoints/users/relation.ts b/packages/backend/src/server/api/endpoints/users/relation.ts
index af1984fa2..629c1d0c1 100644
--- a/packages/backend/src/server/api/endpoints/users/relation.ts
+++ b/packages/backend/src/server/api/endpoints/users/relation.ts
@@ -102,6 +102,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const ids = Array.isArray(ps.userId) ? ps.userId : [ps.userId];
 
diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
index 58a8d929f..b9cf332f4 100644
--- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
+++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts
@@ -41,6 +41,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
 
diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts
index f87088688..35f1988fc 100644
--- a/packages/backend/src/server/api/endpoints/users/search.ts
+++ b/packages/backend/src/server/api/endpoints/users/search.ts
@@ -46,6 +46,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const activeThreshold = new Date(Date.now() - (1000 * 60 * 60 * 24 * 30)); // 30日
 
diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts
index eacb2aee1..e8b2a781f 100644
--- a/packages/backend/src/server/api/endpoints/users/show.ts
+++ b/packages/backend/src/server/api/endpoints/users/show.ts
@@ -53,6 +53,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	let user;
 
diff --git a/packages/backend/src/server/api/endpoints/users/stats.ts b/packages/backend/src/server/api/endpoints/users/stats.ts
index b8564218a..bd62e7fb2 100644
--- a/packages/backend/src/server/api/endpoints/users/stats.ts
+++ b/packages/backend/src/server/api/endpoints/users/stats.ts
@@ -24,6 +24,7 @@ export const meta = {
 	},
 };
 
+// eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps, me) => {
 	const user = await Users.findOne(ps.userId);
 	if (user == null) {

From 6be1db00d11aea64c984f7df74be246ebd46c10a Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 3 Jan 2022 02:20:30 +0900
Subject: [PATCH 04/19] refactor(server): use insert instead of save

---
 .../backend/src/queue/processors/db/import-user-lists.ts     | 4 ++--
 packages/backend/src/remote/activitypub/models/note.ts       | 4 ++--
 packages/backend/src/server/api/common/signin.ts             | 4 ++--
 .../src/server/api/endpoints/admin/announcements/create.ts   | 4 ++--
 packages/backend/src/server/api/endpoints/admin/emoji/add.ts | 4 ++--
 .../src/server/api/endpoints/auth/session/generate.ts        | 4 ++--
 packages/backend/src/server/api/endpoints/pages/create.ts    | 4 ++--
 .../backend/src/server/api/endpoints/users/report-abuse.ts   | 4 ++--
 packages/backend/src/services/create-notification.ts         | 5 +++--
 9 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/packages/backend/src/queue/processors/db/import-user-lists.ts b/packages/backend/src/queue/processors/db/import-user-lists.ts
index 8245010de..e060e86dd 100644
--- a/packages/backend/src/queue/processors/db/import-user-lists.ts
+++ b/packages/backend/src/queue/processors/db/import-user-lists.ts
@@ -46,13 +46,13 @@ export async function importUserLists(job: Bull.Job<DbUserImportJobData>, done:
 			});
 
 			if (list == null) {
-				list = await UserLists.save({
+				list = await UserLists.insert({
 					id: genId(),
 					createdAt: new Date(),
 					userId: user.id,
 					name: listName,
 					userIds: [],
-				});
+				}).then(x => UserLists.findOneOrFail(x.identifiers[0]));
 			}
 
 			let target = isSelfHost(host!) ? await Users.findOne({
diff --git a/packages/backend/src/remote/activitypub/models/note.ts b/packages/backend/src/remote/activitypub/models/note.ts
index cca054b52..a0fdf7f23 100644
--- a/packages/backend/src/remote/activitypub/models/note.ts
+++ b/packages/backend/src/remote/activitypub/models/note.ts
@@ -342,7 +342,7 @@ export async function extractEmojis(tags: IObject | IObject[], host: string): Pr
 
 		logger.info(`register emoji host=${host}, name=${name}`);
 
-		return await Emojis.save({
+		return await Emojis.insert({
 			id: genId(),
 			host,
 			name,
@@ -350,6 +350,6 @@ export async function extractEmojis(tags: IObject | IObject[], host: string): Pr
 			url: tag.icon!.url,
 			updatedAt: new Date(),
 			aliases: [],
-		} as Partial<Emoji>);
+		} as Partial<Emoji>).then(x => Emojis.findOneOrFail(x.identifiers[0]));
 	}));
 }
diff --git a/packages/backend/src/server/api/common/signin.ts b/packages/backend/src/server/api/common/signin.ts
index b713260ac..df986fc45 100644
--- a/packages/backend/src/server/api/common/signin.ts
+++ b/packages/backend/src/server/api/common/signin.ts
@@ -29,14 +29,14 @@ export default function(ctx: Koa.Context, user: ILocalUser, redirect = false) {
 
 	(async () => {
 		// Append signin history
-		const record = await Signins.save({
+		const record = await Signins.insert({
 			id: genId(),
 			createdAt: new Date(),
 			userId: user.id,
 			ip: ctx.ip,
 			headers: ctx.headers,
 			success: true,
-		});
+		}).then(x => Signins.findOneOrFail(x.identifiers[0]));
 
 		// Publish signin event
 		publishMainStream(user.id, 'signin', await Signins.pack(record));
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
index feb874db7..7d169d6ca 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/create.ts
@@ -59,14 +59,14 @@ export const meta = {
 
 // eslint-disable-next-line import/no-default-export
 export default define(meta, async (ps) => {
-	const announcement = await Announcements.save({
+	const announcement = await Announcements.insert({
 		id: genId(),
 		createdAt: new Date(),
 		updatedAt: null,
 		title: ps.title,
 		text: ps.text,
 		imageUrl: ps.imageUrl,
-	});
+	}).then(x => Announcements.findOneOrFail(x.identifiers[0]));
 
 	return announcement;
 });
diff --git a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
index bafa658a5..f7a0fdb87 100644
--- a/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
+++ b/packages/backend/src/server/api/endpoints/admin/emoji/add.ts
@@ -38,7 +38,7 @@ export default define(meta, async (ps, me) => {
 
 	const name = file.name.split('.')[0].match(/^[a-z0-9_]+$/) ? file.name.split('.')[0] : `_${rndstr('a-z0-9', 8)}_`;
 
-	const emoji = await Emojis.save({
+	const emoji = await Emojis.insert({
 		id: genId(),
 		updatedAt: new Date(),
 		name: name,
@@ -47,7 +47,7 @@ export default define(meta, async (ps, me) => {
 		aliases: [],
 		url: file.url,
 		type: file.type,
-	});
+	}).then(x => Emojis.findOneOrFail(x.identifiers[0]));
 
 	await getConnection().queryResultCache!.remove(['meta_emojis']);
 
diff --git a/packages/backend/src/server/api/endpoints/auth/session/generate.ts b/packages/backend/src/server/api/endpoints/auth/session/generate.ts
index 2b46c4828..b9e5e84f6 100644
--- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts
+++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts
@@ -57,12 +57,12 @@ export default define(meta, async (ps) => {
 	const token = uuid();
 
 	// Create session token document
-	const doc = await AuthSessions.save({
+	const doc = await AuthSessions.insert({
 		id: genId(),
 		createdAt: new Date(),
 		appId: app.id,
 		token: token,
-	});
+	}).then(x => AuthSessions.findOneOrFail(x.identifiers[0]));
 
 	return {
 		token: doc.token,
diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts
index 65e579e4e..dcf916909 100644
--- a/packages/backend/src/server/api/endpoints/pages/create.ts
+++ b/packages/backend/src/server/api/endpoints/pages/create.ts
@@ -107,7 +107,7 @@ export default define(meta, async (ps, user) => {
 		}
 	});
 
-	const page = await Pages.save(new Page({
+	const page = await Pages.insert(new Page({
 		id: genId(),
 		createdAt: new Date(),
 		updatedAt: new Date(),
@@ -123,7 +123,7 @@ export default define(meta, async (ps, user) => {
 		alignCenter: ps.alignCenter,
 		hideTitleWhenPinned: ps.hideTitleWhenPinned,
 		font: ps.font,
-	}));
+	})).then(x => Pages.findOneOrFail(x.identifiers[0]));
 
 	return await Pages.pack(page);
 });
diff --git a/packages/backend/src/server/api/endpoints/users/report-abuse.ts b/packages/backend/src/server/api/endpoints/users/report-abuse.ts
index a1d837665..bd80710fe 100644
--- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts
+++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts
@@ -62,7 +62,7 @@ export default define(meta, async (ps, me) => {
 		throw new ApiError(meta.errors.cannotReportAdmin);
 	}
 
-	const report = await AbuseUserReports.save({
+	const report = await AbuseUserReports.insert({
 		id: genId(),
 		createdAt: new Date(),
 		targetUserId: user.id,
@@ -70,7 +70,7 @@ export default define(meta, async (ps, me) => {
 		reporterId: me.id,
 		reporterHost: null,
 		comment: ps.comment,
-	});
+	}).then(x => AbuseUserReports.findOneOrFail(x.identifiers[0]));
 
 	// Publish event to moderators
 	setTimeout(async () => {
diff --git a/packages/backend/src/services/create-notification.ts b/packages/backend/src/services/create-notification.ts
index fc43ab29d..1c1c1fcdf 100644
--- a/packages/backend/src/services/create-notification.ts
+++ b/packages/backend/src/services/create-notification.ts
@@ -20,7 +20,7 @@ export async function createNotification(
 	const isMuted = profile?.mutingNotificationTypes.includes(type);
 
 	// Create notification
-	const notification = await Notifications.save({
+	const notification = await Notifications.insert({
 		id: genId(),
 		createdAt: new Date(),
 		notifieeId: notifieeId,
@@ -28,7 +28,8 @@ export async function createNotification(
 		// 相手がこの通知をミュートしているようなら、既読を予めつけておく
 		isRead: isMuted,
 		...data,
-	} as Partial<Notification>);
+	} as Partial<Notification>)
+		.then(x => Notifications.findOneOrFail(x.identifiers[0]));
 
 	const packed = await Notifications.pack(notification, {});
 

From f25777f2d2839b2373933644fd527af8028ff415 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 3 Jan 2022 03:17:16 +0900
Subject: [PATCH 05/19] refactor(server): use insert instead of save

---
 packages/backend/src/services/relay.ts | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/backend/src/services/relay.ts b/packages/backend/src/services/relay.ts
index 422da8884..33a5ef7f9 100644
--- a/packages/backend/src/services/relay.ts
+++ b/packages/backend/src/services/relay.ts
@@ -22,11 +22,11 @@ export async function getRelayActor(): Promise<ILocalUser> {
 }
 
 export async function addRelay(inbox: string) {
-	const relay = await Relays.save({
+	const relay = await Relays.insert({
 		id: genId(),
 		inbox,
 		status: 'requesting',
-	});
+	}).then(x => Relays.findOneOrFail(x.identifiers[0]));
 
 	const relayActor = await getRelayActor();
 	const follow = await renderFollowRelay(relay, relayActor);

From 23efba619380bd4dc5fa88b1a3d60db0018b7019 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Mon, 3 Jan 2022 03:17:28 +0900
Subject: [PATCH 06/19] tweak ui

---
 packages/client/src/pages/admin/relays.vue | 48 +++++++++++++++-------
 1 file changed, 33 insertions(+), 15 deletions(-)

diff --git a/packages/client/src/pages/admin/relays.vue b/packages/client/src/pages/admin/relays.vue
index 3e2f1c6f2..5ab02002b 100644
--- a/packages/client/src/pages/admin/relays.vue
+++ b/packages/client/src/pages/admin/relays.vue
@@ -1,32 +1,27 @@
 <template>
-<FormBase class="relaycxt">
-	<FormButton primary @click="addRelay"><i class="fas fa-plus"></i> {{ $ts.addRelay }}</FormButton>
-
-	<div v-for="relay in relays" :key="relay.inbox" class="_debobigegoItem">
-		<div class="_debobigegoPanel" style="padding: 16px;">
-			<div>{{ relay.inbox }}</div>
-			<div>{{ $t(`_relayStatus.${relay.status}`) }}</div>
-			<MkButton class="button" inline danger @click="remove(relay.inbox)"><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton>
+<MkSpacer :content-max="800">
+	<div v-for="relay in relays" :key="relay.inbox" class="relaycxt _panel _block" style="padding: 16px;">
+		<div>{{ relay.inbox }}</div>
+		<div class="status">
+			<i v-if="relay.status === 'accepted'" class="fas fa-check icon accepted"></i>
+			<i v-else-if="relay.status === 'rejected'" class="fas fa-ban icon rejected"></i>
+			<i v-else class="fas fa-clock icon requesting"></i>
+			<span>{{ $t(`_relayStatus.${relay.status}`) }}</span>
 		</div>
+		<MkButton class="button" inline danger @click="remove(relay.inbox)"><i class="fas fa-trash-alt"></i> {{ $ts.remove }}</MkButton>
 	</div>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
 import MkButton from '@/components/ui/button.vue';
-import MkInput from '@/components/form/input.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormButton from '@/components/debobigego/button.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
-		FormButton,
 		MkButton,
-		MkInput,
 	},
 
 	emits: ['info'],
@@ -37,6 +32,12 @@ export default defineComponent({
 				title: this.$ts.relays,
 				icon: 'fas fa-globe',
 				bg: 'var(--bg)',
+				actions: [{
+					asFullButton: true,
+					icon: 'fas fa-plus',
+					text: this.$ts.addRelay,
+					handler: this.addRelay,
+				}],
 			},
 			relays: [],
 			inbox: '',
@@ -94,5 +95,22 @@ export default defineComponent({
 </script>
 
 <style lang="scss" scoped>
+.relaycxt {
+	> .status {
+		margin: 8px 0;
 
+		> .icon {
+			width: 1em;
+			margin-right: 0.75em;
+
+			&.accepted {
+				color: var(--success);
+			}
+
+			&.rejected {
+				color: var(--error);
+			}
+		}
+	}
+}
 </style>

From 333ba491f10446066c076338f7cd495ac715f436 Mon Sep 17 00:00:00 2001
From: tamaina <tamaina@hotmail.co.jp>
Date: Mon, 3 Jan 2022 07:35:02 +0900
Subject: [PATCH 07/19] =?UTF-8?q?enhance:=20=E8=A8=B1=E5=8F=AF=E3=81=95?=
 =?UTF-8?q?=E3=82=8C=E3=81=A6=E3=81=84=E3=81=AA=E3=81=84=E3=83=95=E3=82=A1?=
 =?UTF-8?q?=E3=82=A4=E3=83=AB=E3=82=BF=E3=82=A4=E3=83=97=E3=81=A7=E3=81=AF?=
 =?UTF-8?q?=E3=80=81=E3=82=AA=E3=83=96=E3=82=B8=E3=82=A7=E3=82=AF=E3=83=88?=
 =?UTF-8?q?=E3=82=B9=E3=83=88=E3=83=AC=E3=83=BC=E3=82=B8=E3=81=AE=E3=83=95?=
 =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E5=90=8D=E3=81=AB=E6=8B=A1=E5=BC=B5?=
 =?UTF-8?q?=E5=AD=90=E3=82=92=E4=BB=98=E4=B8=8E=E3=81=97=E3=81=AA=E3=81=84?=
 =?UTF-8?q?=E3=82=88=E3=81=86=E3=81=AB=20(#8108)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* 許可されていないファイルタイプでは、オブジェクトストレージのファイル名に拡張子を付与しないように

* add comment
---
 packages/backend/src/services/drive/add-file.ts | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/packages/backend/src/services/drive/add-file.ts b/packages/backend/src/services/drive/add-file.ts
index 3d53fe8d3..38793412f 100644
--- a/packages/backend/src/services/drive/add-file.ts
+++ b/packages/backend/src/services/drive/add-file.ts
@@ -50,6 +50,12 @@ async function save(file: DriveFile, path: string, name: string, type: string, h
 			if (type === 'image/vnd.mozilla.apng') ext = '.apng';
 		}
 
+		// 拡張子からContent-Typeを設定してそうな挙動を示すオブジェクトストレージ (upcloud?) も存在するので、
+		// 許可されているファイル形式でしか拡張子をつけない
+		if (!FILE_TYPE_BROWSERSAFE.includes(type)) {
+			ext = '';
+		}
+
 		const baseUrl = meta.objectStorageBaseUrl
 			|| `${ meta.objectStorageUseSSL ? 'https' : 'http' }://${ meta.objectStorageEndpoint }${ meta.objectStoragePort ? `:${meta.objectStoragePort}` : '' }/${ meta.objectStorageBucket }`;
 

From 6a5713f5e54efa82a196e105c508dd83b2e726bd Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 15:36:14 +0900
Subject: [PATCH 08/19] tweak ui

---
 packages/client/src/components/chart.vue      |   8 +-
 .../client/src/components/form/section.vue    |   7 +-
 .../client/src/components/form/switch.vue     |   2 +-
 .../client/src/components/global/spacer.vue   |   2 +-
 .../client/src/components/instance-stats.vue  |  15 +-
 packages/client/src/components/key-value.vue  |  27 +-
 packages/client/src/pages/about.vue           |   3 +-
 packages/client/src/pages/admin/instance.vue  | 291 ------------------
 packages/client/src/pages/admin/metrics.vue   |   1 -
 packages/client/src/pages/admin/overview.vue  |   7 +-
 packages/client/src/pages/instance-info.vue   | 230 +++++++-------
 packages/client/src/pages/user-ap-info.vue    | 124 --------
 packages/client/src/pages/user-info.vue       | 137 +++++----
 packages/client/src/router.ts                 |   1 -
 14 files changed, 231 insertions(+), 624 deletions(-)
 delete mode 100644 packages/client/src/pages/admin/instance.vue
 delete mode 100644 packages/client/src/pages/user-ap-info.vue

diff --git a/packages/client/src/components/chart.vue b/packages/client/src/components/chart.vue
index c4d0eb85d..1959271f5 100644
--- a/packages/client/src/components/chart.vue
+++ b/packages/client/src/components/chart.vue
@@ -170,10 +170,10 @@ export default defineComponent({
 					aspectRatio: props.aspectRatio || 2.5,
 					layout: {
 						padding: {
-							left: 16,
-							right: 16,
-							top: 16,
-							bottom: 8,
+							left: 0,
+							right: 0,
+							top: 0,
+							bottom: 0,
 						},
 					},
 					scales: {
diff --git a/packages/client/src/components/form/section.vue b/packages/client/src/components/form/section.vue
index ab9fbe5fc..c6e34ef1c 100644
--- a/packages/client/src/components/form/section.vue
+++ b/packages/client/src/components/form/section.vue
@@ -1,5 +1,5 @@
 <template>
-<div v-size="{ max: [500] }" v-sticky-container class="vrtktovh _formBlock">
+<div class="vrtktovh _formBlock">
 	<div class="label"><slot name="label"></slot></div>
 	<div class="main _formRoot">
 		<slot></slot>
@@ -12,10 +12,8 @@
 
 <style lang="scss" scoped>
 .vrtktovh {
-	margin: 0;
 	border-top: solid 0.5px var(--divider);
 	border-bottom: solid 0.5px var(--divider);
-	padding: 24px 0;
 
 	& + .vrtktovh {
 		border-top: none;
@@ -31,7 +29,7 @@
 
 	> .label {
 		font-weight: bold;
-		padding: 0 0 16px 0;
+		margin: 1.5em 0 16px 0;
 
 		&:empty {
 			display: none;
@@ -39,6 +37,7 @@
 	}
 
 	> .main {
+		margin: 1.5em 0;
 	}
 }
 </style>
diff --git a/packages/client/src/components/form/switch.vue b/packages/client/src/components/form/switch.vue
index ac3284e7d..f8a07b4ca 100644
--- a/packages/client/src/components/form/switch.vue
+++ b/packages/client/src/components/form/switch.vue
@@ -111,7 +111,7 @@ export default defineComponent({
 	}
 
 	> .label {
-		margin-left: 16px;
+		margin-left: 12px;
 		margin-top: 2px;
 		display: block;
 		transition: inherit;
diff --git a/packages/client/src/components/global/spacer.vue b/packages/client/src/components/global/spacer.vue
index e2f1d1aec..8a1d7a4e8 100644
--- a/packages/client/src/components/global/spacer.vue
+++ b/packages/client/src/components/global/spacer.vue
@@ -40,7 +40,7 @@ export default defineComponent({
 				return;
 			}
 
-			if (rect.width > props.contentMax || rect.width > 500) {
+			if (rect.width > props.contentMax || (rect.width > 360 && window.innerWidth > 400)) {
 				margin.value = props.marginMax;
 			} else {
 				margin.value = props.marginMin;
diff --git a/packages/client/src/components/instance-stats.vue b/packages/client/src/components/instance-stats.vue
index bc62998a4..409c3a49c 100644
--- a/packages/client/src/components/instance-stats.vue
+++ b/packages/client/src/components/instance-stats.vue
@@ -1,5 +1,5 @@
 <template>
-<div class="zbcjwnqg" style="margin-top: -8px;">
+<div class="zbcjwnqg">
 	<div class="selects" style="display: flex;">
 		<MkSelect v-model="chartSrc" style="margin: 0; flex: 1;">
 			<optgroup :label="$ts.federation">
@@ -29,16 +29,16 @@
 			<option value="day">{{ $ts.perDay }}</option>
 		</MkSelect>
 	</div>
-	<MkChart :src="chartSrc" :span="chartSpan" :limit="chartLimit" :detailed="detailed"></MkChart>
+	<div class="chart">
+		<MkChart :src="chartSrc" :span="chartSpan" :limit="chartLimit" :detailed="detailed"></MkChart>
+	</div>
 </div>
 </template>
 
 <script lang="ts">
-import { defineComponent, onMounted, ref, watch } from 'vue';
+import { defineComponent, ref } from 'vue';
 import MkSelect from '@/components/form/select.vue';
 import MkChart from '@/components/chart.vue';
-import * as os from '@/os';
-import { defaultStore } from '@/store';
 
 export default defineComponent({
 	components: {
@@ -74,7 +74,10 @@ export default defineComponent({
 <style lang="scss" scoped>
 .zbcjwnqg {
 	> .selects {
-		padding: 8px 16px 0 16px;
+	}
+
+	> .chart {
+		padding: 8px 0 0 0;
 	}
 }
 </style>
diff --git a/packages/client/src/components/key-value.vue b/packages/client/src/components/key-value.vue
index 6a9a948ce..da98abd77 100644
--- a/packages/client/src/components/key-value.vue
+++ b/packages/client/src/components/key-value.vue
@@ -1,5 +1,5 @@
 <template>
-<div class="alqyeyti">
+<div class="alqyeyti" :class="{ oneline }">
 	<div class="key">
 		<slot name="key"></slot>
 	</div>
@@ -22,6 +22,11 @@ export default defineComponent({
 			required: false,
 			default: null,
 		},
+		oneline: {
+			type: Boolean,
+			required: false,
+			default: false,
+		},
 	},
 
 	setup(props) {
@@ -39,10 +44,30 @@ export default defineComponent({
 
 <style lang="scss" scoped>
 .alqyeyti {
+	> .key, > .value {
+		white-space: nowrap;
+		overflow: hidden;
+		text-overflow: ellipsis;
+	}
+
 	> .key {
 		font-size: 0.85em;
 		padding: 0 0 0.25em 0;
 		opacity: 0.75;
 	}
+
+	&.oneline {
+		display: flex;
+
+		> .key {
+			width: 30%;
+			font-size: 1em;
+			padding: 0 8px 0 0;
+		}
+
+		> .value {
+			width: 70%;
+		}
+	}
 }
 </style>
diff --git a/packages/client/src/pages/about.vue b/packages/client/src/pages/about.vue
index 618e56983..e9d17feec 100644
--- a/packages/client/src/pages/about.vue
+++ b/packages/client/src/pages/about.vue
@@ -93,7 +93,8 @@ export default defineComponent({
 		return {
 			[symbols.PAGE_INFO]: {
 				title: this.$ts.instanceInfo,
-				icon: 'fas fa-info-circle'
+				icon: 'fas fa-info-circle',
+				bg: 'var(--bg)',
 			},
 			host,
 			version,
diff --git a/packages/client/src/pages/admin/instance.vue b/packages/client/src/pages/admin/instance.vue
deleted file mode 100644
index 51fcb8675..000000000
--- a/packages/client/src/pages/admin/instance.vue
+++ /dev/null
@@ -1,291 +0,0 @@
-<template>
-<XModalWindow ref="dialog"
-	:width="520"
-	:height="500"
-	@close="$refs.dialog.close()"
-	@closed="$emit('closed')"
->
-	<template #header>{{ instance.host }}</template>
-	<div class="mk-instance-info">
-		<div class="_table section">
-			<div class="_row">
-				<div class="_cell">
-					<div class="_label">{{ $ts.software }}</div>
-					<div class="_data">{{ instance.softwareName || '?' }}</div>
-				</div>
-				<div class="_cell">
-					<div class="_label">{{ $ts.version }}</div>
-					<div class="_data">{{ instance.softwareVersion || '?' }}</div>
-				</div>
-			</div>
-		</div>
-		<div class="_table data section">
-			<div class="_row">
-				<div class="_cell">
-					<div class="_label">{{ $ts.registeredAt }}</div>
-					<div class="_data">{{ new Date(instance.caughtAt).toLocaleString() }} (<MkTime :time="instance.caughtAt"/>)</div>
-				</div>
-			</div>
-			<div class="_row">
-				<div class="_cell">
-					<div class="_label">{{ $ts.following }}</div>
-					<button class="_data _textButton" @click="showFollowing()">{{ number(instance.followingCount) }}</button>
-				</div>
-				<div class="_cell">
-					<div class="_label">{{ $ts.followers }}</div>
-					<button class="_data _textButton" @click="showFollowers()">{{ number(instance.followersCount) }}</button>
-				</div>
-			</div>
-			<div class="_row">
-				<div class="_cell">
-					<div class="_label">{{ $ts.users }}</div>
-					<button class="_data _textButton" @click="showUsers()">{{ number(instance.usersCount) }}</button>
-				</div>
-				<div class="_cell">
-					<div class="_label">{{ $ts.notes }}</div>
-					<div class="_data">{{ number(instance.notesCount) }}</div>
-				</div>
-			</div>
-			<div class="_row">
-				<div class="_cell">
-					<div class="_label">{{ $ts.files }}</div>
-					<div class="_data">{{ number(instance.driveFiles) }}</div>
-				</div>
-				<div class="_cell">
-					<div class="_label">{{ $ts.storageUsage }}</div>
-					<div class="_data">{{ bytes(instance.driveUsage) }}</div>
-				</div>
-			</div>
-			<div class="_row">
-				<div class="_cell">
-					<div class="_label">{{ $ts.latestRequestSentAt }}</div>
-					<div class="_data"><MkTime v-if="instance.latestRequestSentAt" :time="instance.latestRequestSentAt"/><span v-else>N/A</span></div>
-				</div>
-				<div class="_cell">
-					<div class="_label">{{ $ts.latestStatus }}</div>
-					<div class="_data">{{ instance.latestStatus ? instance.latestStatus : 'N/A' }}</div>
-				</div>
-			</div>
-			<div class="_row">
-				<div class="_cell">
-					<div class="_label">{{ $ts.latestRequestReceivedAt }}</div>
-					<div class="_data"><MkTime v-if="instance.latestRequestReceivedAt" :time="instance.latestRequestReceivedAt"/><span v-else>N/A</span></div>
-				</div>
-			</div>
-		</div>
-		<div class="chart">
-			<div class="header">
-				<span class="label">{{ $ts.charts }}</span>
-				<div class="selects">
-					<MkSelect v-model="chartSrc" style="margin: 0; flex: 1;">
-						<option value="instance-requests">{{ $ts._instanceCharts.requests }}</option>
-						<option value="instance-users">{{ $ts._instanceCharts.users }}</option>
-						<option value="instance-users-total">{{ $ts._instanceCharts.usersTotal }}</option>
-						<option value="instance-notes">{{ $ts._instanceCharts.notes }}</option>
-						<option value="instance-notes-total">{{ $ts._instanceCharts.notesTotal }}</option>
-						<option value="instance-ff">{{ $ts._instanceCharts.ff }}</option>
-						<option value="instance-ff-total">{{ $ts._instanceCharts.ffTotal }}</option>
-						<option value="instance-drive-usage">{{ $ts._instanceCharts.cacheSize }}</option>
-						<option value="instance-drive-usage-total">{{ $ts._instanceCharts.cacheSizeTotal }}</option>
-						<option value="instance-drive-files">{{ $ts._instanceCharts.files }}</option>
-						<option value="instance-drive-files-total">{{ $ts._instanceCharts.filesTotal }}</option>
-					</MkSelect>
-					<MkSelect v-model="chartSpan" style="margin: 0;">
-						<option value="hour">{{ $ts.perHour }}</option>
-						<option value="day">{{ $ts.perDay }}</option>
-					</MkSelect>
-				</div>
-			</div>
-			<div class="chart">
-				<MkChart :src="chartSrc" :span="chartSpan" :limit="90" :detailed="true"></MkChart>
-			</div>
-		</div>
-		<div class="operations section">
-			<span class="label">{{ $ts.operations }}</span>
-			<MkSwitch v-model="isSuspended" class="switch">{{ $ts.stopActivityDelivery }}</MkSwitch>
-			<MkSwitch :model-value="isBlocked" class="switch" @update:modelValue="changeBlock">{{ $ts.blockThisInstance }}</MkSwitch>
-			<details>
-				<summary>{{ $ts.deleteAllFiles }}</summary>
-				<MkButton style="margin: 0.5em 0 0.5em 0;" @click="deleteAllFiles()"><i class="fas fa-trash-alt"></i> {{ $ts.deleteAllFiles }}</MkButton>
-			</details>
-			<details>
-				<summary>{{ $ts.removeAllFollowing }}</summary>
-				<MkButton style="margin: 0.5em 0 0.5em 0;" @click="removeAllFollowing()"><i class="fas fa-minus-circle"></i> {{ $ts.removeAllFollowing }}</MkButton>
-				<MkInfo warn>{{ $t('removeAllFollowingDescription', { host: instance.host }) }}</MkInfo>
-			</details>
-		</div>
-		<details class="metadata section">
-			<summary class="label">{{ $ts.metadata }}</summary>
-			<pre><code>{{ JSON.stringify(instance, null, 2) }}</code></pre>
-		</details>
-	</div>
-</XModalWindow>
-</template>
-
-<script lang="ts">
-import { defineComponent, markRaw } from 'vue';
-import XModalWindow from '@/components/ui/modal-window.vue';
-import MkSelect from '@/components/form/select.vue';
-import MkButton from '@/components/ui/button.vue';
-import MkSwitch from '@/components/form/switch.vue';
-import MkInfo from '@/components/ui/info.vue';
-import MkChart from '@/components/chart.vue';
-import bytes from '@/filters/bytes';
-import number from '@/filters/number';
-import * as os from '@/os';
-
-export default defineComponent({
-	components: {
-		XModalWindow,
-		MkSelect,
-		MkButton,
-		MkSwitch,
-		MkInfo,
-		MkChart,
-	},
-
-	props: {
-		instance: {
-			type: Object,
-			required: true
-		}
-	},
-
-	emits: ['closed'],
-
-	data() {
-		return {
-			isSuspended: this.instance.isSuspended,
-			chartSrc: 'requests',
-			chartSpan: 'hour',
-		};
-	},
-
-	computed: {
-		meta() {
-			return this.$instance;
-		},
-
-		isBlocked() {
-			return this.meta && this.meta.blockedHosts && this.meta.blockedHosts.includes(this.instance.host);
-		}
-	},
-
-	watch: {
-		isSuspended() {
-			os.api('admin/federation/update-instance', {
-				host: this.instance.host,
-				isSuspended: this.isSuspended
-			});
-		},
-	},
-
-	methods: {
-		changeBlock(e) {
-			os.api('admin/update-meta', {
-				blockedHosts: this.isBlocked ? this.meta.blockedHosts.concat([this.instance.host]) : this.meta.blockedHosts.filter(x => x !== this.instance.host)
-			});
-		},
-
-		removeAllFollowing() {
-			os.apiWithDialog('admin/federation/remove-all-following', {
-				host: this.instance.host
-			});
-		},
-
-		deleteAllFiles() {
-			os.apiWithDialog('admin/federation/delete-all-files', {
-				host: this.instance.host
-			});
-		},
-
-		showFollowing() {
-			// TODO: ページ遷移
-		},
-
-		showFollowers() {
-			// TODO: ページ遷移
-		},
-
-		showUsers() {
-			// TODO: ページ遷移
-		},
-
-		bytes,
-
-		number
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.mk-instance-info {
-	overflow: auto;
-
-	> .section {
-		padding: 16px 32px;
-
-		@media (max-width: 500px) {
-			padding: 8px 16px;
-		}
-
-		&:not(:first-child) {
-			border-top: solid 0.5px var(--divider);
-		}
-	}
-
-	> .chart {
-		border-top: solid 0.5px var(--divider);
-		padding: 16px 0 12px 0;
-
-		> .header {
-			padding: 0 32px;
-
-			@media (max-width: 500px) {
-				padding: 0 16px;
-			}
-
-			> .label {
-				font-size: 80%;
-				opacity: 0.7;
-			}
-
-			> .selects {
-				display: flex;
-			}
-		}
-
-		> .chart {
-			padding: 0 16px;
-
-			@media (max-width: 500px) {
-				padding: 0;
-			}
-		}
-	}
-
-	> .operations {
-		> .label {
-			font-size: 80%;
-			opacity: 0.7;
-		}
-
-		> .switch {
-			margin: 16px 0;
-		}
-	}
-
-	> .metadata {
-		> .label {
-			font-size: 80%;
-			opacity: 0.7;
-		}
-
-		> pre > code {
-			display: block;
-			max-height: 200px;
-			overflow: auto;
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/pages/admin/metrics.vue b/packages/client/src/pages/admin/metrics.vue
index f566061ce..1de297fd9 100644
--- a/packages/client/src/pages/admin/metrics.vue
+++ b/packages/client/src/pages/admin/metrics.vue
@@ -76,7 +76,6 @@ import MkwFederation from '../../widgets/federation.vue';
 import { version, url } from '@/config';
 import bytes from '@/filters/bytes';
 import number from '@/filters/number';
-import MkInstanceInfo from './instance.vue';
 
 Chart.register(
   ArcElement,
diff --git a/packages/client/src/pages/admin/overview.vue b/packages/client/src/pages/admin/overview.vue
index 3dcfce01e..564a63fda 100644
--- a/packages/client/src/pages/admin/overview.vue
+++ b/packages/client/src/pages/admin/overview.vue
@@ -19,7 +19,7 @@
 
 	<MkContainer :foldable="true" class="charts">
 		<template #header><i class="fas fa-chart-bar"></i>{{ $ts.charts }}</template>
-		<div style="padding-top: 12px;">
+		<div style="padding: 12px;">
 			<MkInstanceStats :chart-limit="500" :detailed="true"/>
 		</div>
 	</MkContainer>
@@ -77,7 +77,6 @@ import MkQueueChart from '@/components/queue-chart.vue';
 import { version, url } from '@/config';
 import bytes from '@/filters/bytes';
 import number from '@/filters/number';
-import MkInstanceInfo from './instance.vue';
 import XMetrics from './metrics.vue';
 import * as os from '@/os';
 import { stream } from '@/stream';
@@ -159,9 +158,7 @@ export default defineComponent({
 					host: q
 				});
 			}
-			os.popup(MkInstanceInfo, {
-				instance: instance
-			}, {}, 'closed');
+			// TODO
 		},
 
 		bytes,
diff --git a/packages/client/src/pages/instance-info.vue b/packages/client/src/pages/instance-info.vue
index 85096d991..d6d72f660 100644
--- a/packages/client/src/pages/instance-info.vue
+++ b/packages/client/src/pages/instance-info.vue
@@ -1,70 +1,71 @@
 <template>
-<FormBase>
-	<FormGroup v-if="instance">
-		<template #label>{{ instance.host }}</template>
-		<FormGroup>
-			<div class="_debobigegoItem">
-				<div class="_debobigegoPanel fnfelxur">
-					<img :src="instance.iconUrl || instance.faviconUrl" alt="" class="icon"/>
-				</div>
-			</div>
-			<FormKeyValueView>
-				<template #key>Name</template>
-				<template #value><span class="_monospace">{{ instance.name || `(${$ts.unknown})` }}</span></template>
-			</FormKeyValueView>
-		</FormGroup>
+<MkSpacer :content-max="600" :margin-min="16" :margin-max="32">
+	<div v-if="instance" class="_formRoot">
+		<div class="fnfelxur">
+			<img :src="instance.iconUrl || instance.faviconUrl" alt="" class="icon"/>
+		</div>
+		<MkKeyValue :copy="host" oneline style="margin: 1em 0;">
+			<template #key>Host</template>
+			<template #value><span class="_monospace"><MkLink :url="`https://${host}`">{{ host }}</MkLink></span></template>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
+			<template #key>Name</template>
+			<template #value>{{ instance.name || `(${$ts.unknown})` }}</template>
+		</MkKeyValue>
+		<MkKeyValue>
+			<template #key>{{ $ts.description }}</template>
+			<template #value>{{ instance.description }}</template>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
+			<template #key>{{ $ts.software }}</template>
+			<template #value><span class="_monospace">{{ instance.softwareName || `(${$ts.unknown})` }} / {{ instance.softwareVersion || `(${$ts.unknown})` }}</span></template>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
+			<template #key>{{ $ts.administrator }}</template>
+			<template #value>{{ instance.maintainerName || `(${$ts.unknown})` }} ({{ instance.maintainerEmail || `(${$ts.unknown})` }})</template>
+		</MkKeyValue>
 
-		<FormButton v-if="$i.isAdmin || $i.isModerator" primary @click="info">{{ $ts.settings }}</FormButton>
+		<FormSection v-if="iAmModerator">
+			<template #label>Moderation</template>
+			<FormSwitch v-model="suspended" class="_formBlock" @update:modelValue="toggleSuspend">{{ $ts.stopActivityDelivery }}</FormSwitch>
+			<FormSwitch :model-value="isBlocked" class="switch" @update:modelValue="changeBlock">{{ $ts.blockThisInstance }}</FormSwitch>
+		</FormSection>
 
-		<FormTextarea readonly :value="instance.description">
-			<span>{{ $ts.description }}</span>
-		</FormTextarea>
-
-		<FormGroup>
-			<FormKeyValueView>
-				<template #key>{{ $ts.software }}</template>
-				<template #value><span class="_monospace">{{ instance.softwareName || `(${$ts.unknown})` }}</span></template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>{{ $ts.version }}</template>
-				<template #value><span class="_monospace">{{ instance.softwareVersion || `(${$ts.unknown})` }}</span></template>
-			</FormKeyValueView>
-		</FormGroup>
-		<FormGroup>
-			<FormKeyValueView>
-				<template #key>{{ $ts.administrator }}</template>
-				<template #value><span class="_monospace">{{ instance.maintainerName || `(${$ts.unknown})` }}</span></template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>{{ $ts.contact }}</template>
-				<template #value><span class="_monospace">{{ instance.maintainerEmail || `(${$ts.unknown})` }}</span></template>
-			</FormKeyValueView>
-		</FormGroup>
-		<FormGroup>
-			<FormKeyValueView>
+		<FormSection>
+			<MkKeyValue oneline style="margin: 1em 0;">
+				<template #key>{{ $ts.registeredAt }}</template>
+				<template #value><MkTime mode="detail" :time="instance.caughtAt"/></template>
+			</MkKeyValue>
+			<MkKeyValue oneline style="margin: 1em 0;">
+				<template #key>{{ $ts.updatedAt }}</template>
+				<template #value><MkTime mode="detail" :time="instance.infoUpdatedAt"/></template>
+			</MkKeyValue>
+			<MkKeyValue oneline style="margin: 1em 0;">
 				<template #key>{{ $ts.latestRequestSentAt }}</template>
 				<template #value><MkTime v-if="instance.latestRequestSentAt" :time="instance.latestRequestSentAt"/><span v-else>N/A</span></template>
-			</FormKeyValueView>
-			<FormKeyValueView>
+			</MkKeyValue>
+			<MkKeyValue oneline style="margin: 1em 0;">
 				<template #key>{{ $ts.latestStatus }}</template>
 				<template #value>{{ instance.latestStatus ? instance.latestStatus : 'N/A' }}</template>
-			</FormKeyValueView>
-			<FormKeyValueView>
+			</MkKeyValue>
+			<MkKeyValue oneline style="margin: 1em 0;">
 				<template #key>{{ $ts.latestRequestReceivedAt }}</template>
 				<template #value><MkTime v-if="instance.latestRequestReceivedAt" :time="instance.latestRequestReceivedAt"/><span v-else>N/A</span></template>
-			</FormKeyValueView>
-		</FormGroup>
-		<FormGroup>
-			<FormKeyValueView>
+			</MkKeyValue>
+		</FormSection>
+	
+		<FormSection>
+			<MkKeyValue oneline style="margin: 1em 0;">
 				<template #key>Open Registrations</template>
 				<template #value>{{ instance.openRegistrations ? $ts.yes : $ts.no }}</template>
-			</FormKeyValueView>
-		</FormGroup>
-		<div class="_debobigegoItem">
-			<div class="_debobigegoLabel">{{ $ts.statistics }}</div>
-			<div class="_debobigegoPanel cmhjzshl">
+			</MkKeyValue>
+		</FormSection>
+
+		<FormSection>
+			<template #label>{{ $ts.statistics }}</template>
+			<div class="cmhjzshl">
 				<div class="selects">
-					<MkSelect v-model="chartSrc" style="margin: 0; flex: 1;">
+					<MkSelect v-model="chartSrc" style="margin: 0 10px 0 0; flex: 1;">
 						<option value="instance-requests">{{ $ts._instanceCharts.requests }}</option>
 						<option value="instance-users">{{ $ts._instanceCharts.users }}</option>
 						<option value="instance-users-total">{{ $ts._instanceCharts.usersTotal }}</option>
@@ -83,86 +84,56 @@
 					</MkSelect>
 				</div>
 				<div class="chart">
-					<MkChart :src="chartSrc" :span="chartSpan" :limit="90" :detailed="true"></MkChart>
+					<MkChart :src="chartSrc" :span="chartSpan" :limit="90" :args="{ host: host }" :detailed="true"></MkChart>
 				</div>
 			</div>
-		</div>
-		<FormGroup>
-			<FormKeyValueView>
-				<template #key>{{ $ts.registeredAt }}</template>
-				<template #value><MkTime mode="detail" :time="instance.caughtAt"/></template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>{{ $ts.updatedAt }}</template>
-				<template #value><MkTime mode="detail" :time="instance.infoUpdatedAt"/></template>
-			</FormKeyValueView>
-		</FormGroup>
+		</FormSection>
+
 		<FormObjectView tall :value="instance">
 			<span>Raw</span>
 		</FormObjectView>
-		<FormGroup>
+
+		<FormSection>
 			<template #label>Well-known resources</template>
-			<FormLink :to="`https://${host}/.well-known/host-meta`" external>host-meta</FormLink>
-			<FormLink :to="`https://${host}/.well-known/host-meta.json`" external>host-meta.json</FormLink>
-			<FormLink :to="`https://${host}/.well-known/nodeinfo`" external>nodeinfo</FormLink>
-			<FormLink :to="`https://${host}/robots.txt`" external>robots.txt</FormLink>
-			<FormLink :to="`https://${host}/manifest.json`" external>manifest.json</FormLink>
-		</FormGroup>
-		<FormSuspense v-slot="{ result: dns }" :p="dnsPromiseFactory">
-			<FormGroup>
-				<template #label>DNS</template>
-				<FormKeyValueView v-for="record in dns.a" :key="record">
-					<template #key>A</template>
-					<template #value><span class="_monospace">{{ record }}</span></template>
-				</FormKeyValueView>
-				<FormKeyValueView v-for="record in dns.aaaa" :key="record">
-					<template #key>AAAA</template>
-					<template #value><span class="_monospace">{{ record }}</span></template>
-				</FormKeyValueView>
-				<FormKeyValueView v-for="record in dns.cname" :key="record">
-					<template #key>CNAME</template>
-					<template #value><span class="_monospace">{{ record }}</span></template>
-				</FormKeyValueView>
-				<FormKeyValueView v-for="record in dns.txt">
-					<template #key>TXT</template>
-					<template #value><span class="_monospace">{{ record[0] }}</span></template>
-				</FormKeyValueView>
-			</FormGroup>
-		</FormSuspense>
-	</FormGroup>
-</FormBase>
+			<FormLink :to="`https://${host}/.well-known/host-meta`" external style="margin-bottom: 8px;">host-meta</FormLink>
+			<FormLink :to="`https://${host}/.well-known/host-meta.json`" external style="margin-bottom: 8px;">host-meta.json</FormLink>
+			<FormLink :to="`https://${host}/.well-known/nodeinfo`" external style="margin-bottom: 8px;">nodeinfo</FormLink>
+			<FormLink :to="`https://${host}/robots.txt`" external style="margin-bottom: 8px;">robots.txt</FormLink>
+			<FormLink :to="`https://${host}/manifest.json`" external style="margin-bottom: 8px;">manifest.json</FormLink>
+		</FormSection>
+	</div>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineAsyncComponent, defineComponent } from 'vue';
 import MkChart from '@/components/chart.vue';
 import FormObjectView from '@/components/debobigego/object-view.vue';
-import FormTextarea from '@/components/debobigego/textarea.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormTextarea from '@/components/form/textarea.vue';
+import FormLink from '@/components/form/link.vue';
+import MkLink from '@/components/link.vue';
+import FormSection from '@/components/form/section.vue';
+import FormButton from '@/components/ui/button.vue';
+import MkKeyValue from '@/components/key-value.vue';
 import MkSelect from '@/components/form/select.vue';
+import FormSwitch from '@/components/form/switch.vue';
 import * as os from '@/os';
 import number from '@/filters/number';
 import bytes from '@/filters/bytes';
 import * as symbols from '@/symbols';
-import MkInstanceInfo from '@/pages/admin/instance.vue';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		FormTextarea,
 		FormObjectView,
 		FormButton,
 		FormLink,
-		FormGroup,
-		FormKeyValueView,
-		FormSuspense,
+		FormSection,
+		FormSwitch,
+		MkKeyValue,
 		MkSelect,
 		MkChart,
+		MkLink,
 	},
 
 	props: {
@@ -175,8 +146,9 @@ export default defineComponent({
 	data() {
 		return {
 			[symbols.PAGE_INFO]: {
-				title: this.$ts.instanceInfo,
+				title: this.host,
 				icon: 'fas fa-info-circle',
+				bg: 'var(--bg)',
 				actions: [{
 					text: `https://${this.host}`,
 					icon: 'fas fa-external-link-alt',
@@ -186,14 +158,22 @@ export default defineComponent({
 				}],
 			},
 			instance: null,
-			dnsPromiseFactory: () => os.api('federation/dns', {
-				host: this.host
-			}),
+			suspended: false,
 			chartSrc: 'instance-requests',
 			chartSpan: 'hour',
 		}
 	},
 
+	computed: {
+		iAmModerator(): boolean {
+			return this.$i && (this.$i.isAdmin || this.$i.isModerator);
+		},
+
+		isBlocked() {
+			return this.instance && this.$instance && this.$instance.blockedHosts && this.$instance.blockedHosts.includes(this.instance.host);
+		}
+	},
+
 	mounted() {
 		this.fetch();
 	},
@@ -206,24 +186,30 @@ export default defineComponent({
 			this.instance = await os.api('federation/show-instance', {
 				host: this.host
 			});
+			this.suspended = this.instance.isSuspended;
 		},
 
-		info() {
-			os.popup(MkInstanceInfo, {
-				instance: this.instance
-			}, {}, 'closed');
-		}
+		changeBlock(e) {
+			os.api('admin/update-meta', {
+				blockedHosts: this.isBlocked ? this.meta.blockedHosts.concat([this.instance.host]) : this.meta.blockedHosts.filter(x => x !== this.instance.host)
+			});
+		},
+
+		async toggleSuspend(v) {
+			await os.api('admin/federation/update-instance', {
+				host: this.instance.host,
+				isSuspended: this.suspended
+			});
+		},
 	}
 });
 </script>
 
 <style lang="scss" scoped>
 .fnfelxur {
-	padding: 16px;
-
 	> .icon {
 		display: block;
-		margin: auto;
+		margin: 0;
 		height: 64px;
 		border-radius: 8px;
 	}
@@ -232,7 +218,7 @@ export default defineComponent({
 .cmhjzshl {
 	> .selects {
 		display: flex;
-		padding: 16px;
+		margin: 0 0 16px 0;
 	}
 }
 </style>
diff --git a/packages/client/src/pages/user-ap-info.vue b/packages/client/src/pages/user-ap-info.vue
deleted file mode 100644
index 0027381f5..000000000
--- a/packages/client/src/pages/user-ap-info.vue
+++ /dev/null
@@ -1,124 +0,0 @@
-<template>
-<FormBase>
-	<FormSuspense v-slot="{ result: ap }" :p="apPromiseFactory">
-		<FormGroup>
-			<template #label>ActivityPub</template>
-			<FormKeyValueView>
-				<template #key>Type</template>
-				<template #value><span class="_monospace">{{ ap.type }}</span></template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>URI</template>
-				<template #value><span class="_monospace">{{ ap.id }}</span></template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>URL</template>
-				<template #value><span class="_monospace">{{ ap.url }}</span></template>
-			</FormKeyValueView>
-			<FormGroup>
-				<FormKeyValueView>
-					<template #key>Inbox</template>
-					<template #value><span class="_monospace">{{ ap.inbox }}</span></template>
-				</FormKeyValueView>
-				<FormKeyValueView>
-					<template #key>Shared Inbox</template>
-					<template #value><span class="_monospace">{{ ap.sharedInbox || ap.endpoints.sharedInbox }}</span></template>
-				</FormKeyValueView>
-				<FormKeyValueView>
-					<template #key>Outbox</template>
-					<template #value><span class="_monospace">{{ ap.outbox }}</span></template>
-				</FormKeyValueView>
-			</FormGroup>
-			<FormTextarea readonly tall code pre :value="ap.publicKey.publicKeyPem">
-				<span>Public Key</span>
-			</FormTextarea>
-			<FormKeyValueView>
-				<template #key>Discoverable</template>
-				<template #value>{{ ap.discoverable ? $ts.yes : $ts.no }}</template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>ManuallyApprovesFollowers</template>
-				<template #value>{{ ap.manuallyApprovesFollowers ? $ts.yes : $ts.no }}</template>
-			</FormKeyValueView>
-			<FormObjectView tall :value="ap">
-				<span>Raw</span>
-			</FormObjectView>
-			<FormGroup>
-				<FormLink :to="`https://${user.host}/.well-known/webfinger?resource=acct:${user.username}`" external>WebFinger</FormLink>
-			</FormGroup>
-			<FormLink v-if="user.host" :to="`/instance-info/${user.host}`">{{ $ts.instanceInfo }}<template #suffix>{{ user.host }}</template></FormLink>
-			<FormKeyValueView v-else>
-				<template #key>{{ $ts.instanceInfo }}</template>
-				<template #value>(Local user)</template>
-			</FormKeyValueView>
-		</FormGroup>
-	</FormSuspense>
-</FormBase>
-</template>
-
-<script lang="ts">
-import { defineAsyncComponent, defineComponent } from 'vue';
-import FormObjectView from '@/components/debobigego/object-view.vue';
-import FormTextarea from '@/components/debobigego/textarea.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
-import * as os from '@/os';
-import number from '@/filters/number';
-import bytes from '@/filters/bytes';
-import * as symbols from '@/symbols';
-import { url } from '@/config';
-
-export default defineComponent({
-	components: {
-		FormBase,
-		FormTextarea,
-		FormObjectView,
-		FormButton,
-		FormLink,
-		FormGroup,
-		FormKeyValueView,
-		FormSuspense,
-	},
-
-	props: {
-		userId: {
-			type: String,
-			required: true
-		}
-	},
-
-	data() {
-		return {
-			[symbols.PAGE_INFO]: {
-				title: this.$ts.userInfo,
-				icon: 'fas fa-info-circle'
-			},
-			user: null,
-			apPromiseFactory: null,
-		}
-	},
-
-	mounted() {
-		this.fetch();
-	},
-
-	methods: {
-		number,
-		bytes,
-
-		async fetch() {
-			this.user = await os.api('users/show', {
-				userId: this.userId
-			});
-
-			this.apPromiseFactory = () => os.api('ap/get', {
-				uri: this.user.uri || `${url}/users/${this.user.id}`
-			});
-		}
-	}
-});
-</script>
diff --git a/packages/client/src/pages/user-info.vue b/packages/client/src/pages/user-info.vue
index 0fd208a64..e3c10c6df 100644
--- a/packages/client/src/pages/user-info.vue
+++ b/packages/client/src/pages/user-info.vue
@@ -1,70 +1,76 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="500" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<div class="_debobigegoItem aeakzknw">
-			<MkAvatar class="avatar" :user="user" :show-indicator="true"/>
+		<div class="_formRoot">
+			<div class="_formBlock aeakzknw">
+				<MkAvatar class="avatar" :user="user" :show-indicator="true"/>
+			</div>
+
+			<FormLink :to="userPage(user)">Profile</FormLink>
+
+			<div class="_formBlock">
+				<MkKeyValue :copy="acct(user)" oneline style="margin: 1em 0;">
+					<template #key>Acct</template>
+					<template #value><span class="_monospace">{{ acct(user) }}</span></template>
+				</MkKeyValue>
+
+				<MkKeyValue :copy="user.id" oneline style="margin: 1em 0;">
+					<template #key>ID</template>
+					<template #value><span class="_monospace">{{ user.id }}</span></template>
+				</MkKeyValue>
+			</div>
+
+			<FormSection v-if="iAmModerator">
+				<template #label>Moderation</template>
+				<FormSwitch v-if="user.host == null && $i.isAdmin && (moderator || !user.isAdmin)" v-model="moderator" class="_formBlock" @update:modelValue="toggleModerator">{{ $ts.moderator }}</FormSwitch>
+				<FormSwitch v-model="silenced" class="_formBlock" @update:modelValue="toggleSilence">{{ $ts.silence }}</FormSwitch>
+				<FormSwitch v-model="suspended" class="_formBlock" @update:modelValue="toggleSuspend">{{ $ts.suspend }}</FormSwitch>
+				<FormButton v-if="user.host == null && iAmModerator" class="_formBlock" @click="resetPassword"><i class="fas fa-key"></i> {{ $ts.resetPassword }}</FormButton>
+			</FormSection>
+
+			<FormSection>
+				<template #label>ActivityPub</template>
+
+				<div class="_formBlock">
+					<MkKeyValue v-if="user.host" oneline style="margin: 1em 0;">
+						<template #key>{{ $ts.instanceInfo }}</template>
+						<template #value><MkA :to="`/instance-info/${user.host}`" class="_link">{{ user.host }} <i class="fas fa-angle-right"></i></MkA></template>
+					</MkKeyValue>
+					<MkKeyValue v-else oneline style="margin: 1em 0;">
+						<template #key>{{ $ts.instanceInfo }}</template>
+						<template #value>(Local user)</template>
+					</MkKeyValue>
+					<MkKeyValue oneline style="margin: 1em 0;">
+						<template #key>{{ $ts.updatedAt }}</template>
+						<template #value><MkTime v-if="user.lastFetchedAt" mode="detail" :time="user.lastFetchedAt"/><span v-else>N/A</span></template>
+					</MkKeyValue>
+					<MkKeyValue v-if="ap" oneline style="margin: 1em 0;">
+						<template #key>Type</template>
+						<template #value><span class="_monospace">{{ ap.type }}</span></template>
+					</MkKeyValue>
+				</div>
+
+				<FormButton v-if="user.host != null" class="_formBlock" @click="updateRemoteUser"><i class="fas fa-sync"></i> {{ $ts.updateRemoteUser }}</FormButton>
+			</FormSection>
+
+			<FormObjectView tall :value="user">
+				<span>Raw</span>
+			</FormObjectView>
 		</div>
-
-		<FormLink :to="userPage(user)">Profile</FormLink>
-
-		<FormGroup>
-			<FormKeyValueView>
-				<template #key>Acct</template>
-				<template #value><span class="_monospace">{{ acct(user) }}</span></template>
-			</FormKeyValueView>
-
-			<FormKeyValueView>
-				<template #key>ID</template>
-				<template #value><span class="_monospace">{{ user.id }}</span></template>
-			</FormKeyValueView>
-		</FormGroup>
-
-		<FormGroup v-if="iAmModerator">
-			<FormSwitch v-if="user.host == null && $i.isAdmin && (moderator || !user.isAdmin)" v-model="moderator" @update:modelValue="toggleModerator">{{ $ts.moderator }}</FormSwitch>
-			<FormSwitch v-model="silenced" @update:modelValue="toggleSilence">{{ $ts.silence }}</FormSwitch>
-			<FormSwitch v-model="suspended" @update:modelValue="toggleSuspend">{{ $ts.suspend }}</FormSwitch>
-		</FormGroup>
-
-		<FormGroup>
-			<FormButton v-if="user.host != null" @click="updateRemoteUser"><i class="fas fa-sync"></i> {{ $ts.updateRemoteUser }}</FormButton>
-			<FormButton v-if="user.host == null && iAmModerator" @click="resetPassword"><i class="fas fa-key"></i> {{ $ts.resetPassword }}</FormButton>
-		</FormGroup>
-
-		<FormGroup>
-			<FormLink :to="`/user-ap-info/${user.id}`">ActivityPub</FormLink>
-
-			<FormLink v-if="user.host" :to="`/instance-info/${user.host}`">{{ $ts.instanceInfo }}<template #suffix>{{ user.host }}</template></FormLink>
-			<FormKeyValueView v-else>
-				<template #key>{{ $ts.instanceInfo }}</template>
-				<template #value>(Local user)</template>
-			</FormKeyValueView>
-		</FormGroup>
-
-		<FormGroup>
-			<FormKeyValueView>
-				<template #key>{{ $ts.updatedAt }}</template>
-				<template #value><MkTime v-if="user.lastFetchedAt" mode="detail" :time="user.lastFetchedAt"/><span v-else>N/A</span></template>
-			</FormKeyValueView>
-		</FormGroup>
-
-		<FormObjectView tall :value="user">
-			<span>Raw</span>
-		</FormObjectView>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { computed, defineAsyncComponent, defineComponent } from 'vue';
 import FormObjectView from '@/components/debobigego/object-view.vue';
-import FormTextarea from '@/components/debobigego/textarea.vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormTextarea from '@/components/form/textarea.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormLink from '@/components/form/link.vue';
+import FormSection from '@/components/form/section.vue';
+import FormButton from '@/components/ui/button.vue';
+import MkKeyValue from '@/components/key-value.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import number from '@/filters/number';
 import bytes from '@/filters/bytes';
@@ -74,14 +80,13 @@ import { userPage, acct } from '@/filters/user';
 
 export default defineComponent({
 	components: {
-		FormBase,
+		FormSection,
 		FormTextarea,
 		FormSwitch,
 		FormObjectView,
 		FormButton,
 		FormLink,
-		FormGroup,
-		FormKeyValueView,
+		MkKeyValue,
 		FormSuspense,
 	},
 
@@ -97,6 +102,7 @@ export default defineComponent({
 			[symbols.PAGE_INFO]: computed(() => ({
 				title: this.user ? acct(this.user) : this.$ts.userInfo,
 				icon: 'fas fa-info-circle',
+				bg: 'var(--bg)',
 				actions: this.user ? [this.user.url ? {
 					text: this.user.url,
 					icon: 'fas fa-external-link-alt',
@@ -108,6 +114,7 @@ export default defineComponent({
 			init: null,
 			user: null,
 			info: null,
+			ap: null,
 			moderator: false,
 			silenced: false,
 			suspended: false,
@@ -126,6 +133,13 @@ export default defineComponent({
 				this.init = this.createFetcher();
 			},
 			immediate: true
+		},
+		user() {
+			os.api('ap/get', {
+				uri: this.user.uri || `${url}/users/${this.user.id}`
+			}).then(res => {
+				this.ap = res;
+			});
 		}
 	},
 
@@ -234,7 +248,6 @@ export default defineComponent({
 .aeakzknw {
 	> .avatar {
 		display: block;
-		margin: 0 auto;
 		width: 64px;
 		height: 64px;
 	}
diff --git a/packages/client/src/router.ts b/packages/client/src/router.ts
index 9b4dd162f..2a07ff37c 100644
--- a/packages/client/src/router.ts
+++ b/packages/client/src/router.ts
@@ -73,7 +73,6 @@ const defaultRoutes = [
 	{ path: '/notes/:note', name: 'note', component: page('note'), props: route => ({ noteId: route.params.note }) },
 	{ path: '/tags/:tag', component: page('tag'), props: route => ({ tag: route.params.tag }) },
 	{ path: '/user-info/:user', component: page('user-info'), props: route => ({ userId: route.params.user }) },
-	{ path: '/user-ap-info/:user', component: page('user-ap-info'), props: route => ({ userId: route.params.user }) },
 	{ path: '/instance-info/:host', component: page('instance-info'), props: route => ({ host: route.params.host }) },
 	{ path: '/games/reversi', component: page('reversi/index') },
 	{ path: '/games/reversi/:gameId', component: page('reversi/game'), props: route => ({ gameId: route.params.gameId }) },

From efa72e8d14cb2ab5c0ceba541ee992ca031db35c Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 17:52:44 +0900
Subject: [PATCH 09/19] tweak ui

---
 packages/client/src/pages/settings/index.vue  |   1 -
 .../src/pages/settings/plugin.install.vue     |  32 ++---
 .../src/pages/settings/plugin.manage.vue      | 116 ------------------
 packages/client/src/pages/settings/plugin.vue |  86 +++++++++++--
 4 files changed, 89 insertions(+), 146 deletions(-)
 delete mode 100644 packages/client/src/pages/settings/plugin.manage.vue

diff --git a/packages/client/src/pages/settings/index.vue b/packages/client/src/pages/settings/index.vue
index 60ed21786..c9acf2c63 100644
--- a/packages/client/src/pages/settings/index.vue
+++ b/packages/client/src/pages/settings/index.vue
@@ -215,7 +215,6 @@ export default defineComponent({
 				case 'deck': return defineAsyncComponent(() => import('./deck.vue'));
 				case 'plugin': return defineAsyncComponent(() => import('./plugin.vue'));
 				case 'plugin/install': return defineAsyncComponent(() => import('./plugin.install.vue'));
-				case 'plugin/manage': return defineAsyncComponent(() => import('./plugin.manage.vue'));
 				case 'import-export': return defineAsyncComponent(() => import('./import-export.vue'));
 				case 'account-info': return defineAsyncComponent(() => import('./account-info.vue'));
 				case 'delete-account': return defineAsyncComponent(() => import('./delete-account.vue'));
diff --git a/packages/client/src/pages/settings/plugin.install.vue b/packages/client/src/pages/settings/plugin.install.vue
index af93ef293..bf494fa71 100644
--- a/packages/client/src/pages/settings/plugin.install.vue
+++ b/packages/client/src/pages/settings/plugin.install.vue
@@ -1,15 +1,15 @@
 <template>
-<FormBase>
-	<FormInfo warn>{{ $ts._plugin.installWarn }}</FormInfo>
+<div class="_formRoot">
+	<FormInfo warn class="_formBlock">{{ $ts._plugin.installWarn }}</FormInfo>
 
-	<FormGroup>
-		<FormTextarea v-model="code" tall>
-			<span>{{ $ts.code }}</span>
-		</FormTextarea>
-	</FormGroup>
+	<FormTextarea v-model="code" tall class="_formBlock">
+		<template #label>{{ $ts.code }}</template>
+	</FormTextarea>
 
-	<FormButton :disabled="code == null" primary inline @click="install"><i class="fas fa-check"></i> {{ $ts.install }}</FormButton>
-</FormBase>
+	<div class="_formBlock">
+		<FormButton :disabled="code == null" primary inline @click="install"><i class="fas fa-check"></i> {{ $ts.install }}</FormButton>
+	</div>
+</div>
 </template>
 
 <script lang="ts">
@@ -18,13 +18,8 @@ import { AiScript, parse } from '@syuilo/aiscript';
 import { serialize } from '@syuilo/aiscript/built/serializer';
 import { v4 as uuid } from 'uuid';
 import FormTextarea from '@/components/form/textarea.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormRadios from '@/components/form/radios.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormInfo from '@/components/debobigego/info.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormInfo from '@/components/ui/info.vue';
 import * as os from '@/os';
 import { ColdDeviceStorage } from '@/store';
 import { unisonReload } from '@/scripts/unison-reload';
@@ -33,11 +28,6 @@ import * as symbols from '@/symbols';
 export default defineComponent({
 	components: {
 		FormTextarea,
-		FormSelect,
-		FormRadios,
-		FormBase,
-		FormGroup,
-		FormLink,
 		FormButton,
 		FormInfo,
 	},
diff --git a/packages/client/src/pages/settings/plugin.manage.vue b/packages/client/src/pages/settings/plugin.manage.vue
deleted file mode 100644
index 8b9021dc3..000000000
--- a/packages/client/src/pages/settings/plugin.manage.vue
+++ /dev/null
@@ -1,116 +0,0 @@
-<template>
-<FormBase>
-	<FormGroup v-for="plugin in plugins" :key="plugin.id">
-		<template #label><span style="display: flex;"><b>{{ plugin.name }}</b><span style="margin-left: auto;">v{{ plugin.version }}</span></span></template>
-
-		<FormSwitch :modelValue="plugin.active" @update:modelValue="changeActive(plugin, $event)">{{ $ts.makeActive }}</FormSwitch>
-		<div class="_debobigegoItem">
-			<div class="_debobigegoPanel" style="padding: 16px;">
-				<div class="_keyValue">
-					<div>{{ $ts.author }}:</div>
-					<div>{{ plugin.author }}</div>
-				</div>
-				<div class="_keyValue">
-					<div>{{ $ts.description }}:</div>
-					<div>{{ plugin.description }}</div>
-				</div>
-				<div class="_keyValue">
-					<div>{{ $ts.permission }}:</div>
-					<div>{{ plugin.permissions }}</div>
-				</div>
-			</div>
-		</div>
-		<div class="_debobigegoItem">
-			<div class="_debobigegoPanel" style="padding: 16px;">
-				<MkButton v-if="plugin.config" inline @click="config(plugin)"><i class="fas fa-cog"></i> {{ $ts.settings }}</MkButton>
-				<MkButton inline danger @click="uninstall(plugin)"><i class="fas fa-trash-alt"></i> {{ $ts.uninstall }}</MkButton>
-			</div>
-		</div>
-	</FormGroup>
-</FormBase>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import MkButton from '@/components/ui/button.vue';
-import MkTextarea from '@/components/form/textarea.vue';
-import MkSelect from '@/components/form/select.vue';
-import FormSwitch from '@/components/form/switch.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import * as os from '@/os';
-import { ColdDeviceStorage } from '@/store';
-import * as symbols from '@/symbols';
-import { unisonReload } from '@/scripts/unison-reload';
-
-export default defineComponent({
-	components: {
-		MkButton,
-		MkTextarea,
-		MkSelect,
-		FormSwitch,
-		FormBase,
-		FormGroup,
-	},
-
-	emits: ['info'],
-	
-	data() {
-		return {
-			[symbols.PAGE_INFO]: {
-				title: this.$ts._plugin.manage,
-				icon: 'fas fa-plug',
-				bg: 'var(--bg)',
-			},
-			plugins: ColdDeviceStorage.get('plugins'),
-		}
-	},
-
-	mounted() {
-		this.$emit('info', this[symbols.PAGE_INFO]);
-	},
-
-	methods: {
-		uninstall(plugin) {
-			ColdDeviceStorage.set('plugins', this.plugins.filter(x => x.id !== plugin.id));
-			os.success();
-			this.$nextTick(() => {
-				unisonReload();
-			});
-		},
-
-		// TODO: この処理をstore側にactionとして移動し、設定画面を開くAiScriptAPIを実装できるようにする
-		async config(plugin) {
-			const config = plugin.config;
-			for (const key in plugin.configData) {
-				config[key].default = plugin.configData[key];
-			}
-
-			const { canceled, result } = await os.form(plugin.name, config);
-			if (canceled) return;
-
-			const plugins = ColdDeviceStorage.get('plugins');
-			plugins.find(p => p.id === plugin.id).configData = result;
-			ColdDeviceStorage.set('plugins', plugins);
-
-			this.$nextTick(() => {
-				location.reload();
-			});
-		},
-
-		changeActive(plugin, active) {
-			const plugins = ColdDeviceStorage.get('plugins');
-			plugins.find(p => p.id === plugin.id).active = active;
-			ColdDeviceStorage.set('plugins', plugins);
-
-			this.$nextTick(() => {
-				location.reload();
-			});
-		}
-	},
-});
-</script>
-
-<style lang="scss" scoped>
-
-</style>
diff --git a/packages/client/src/pages/settings/plugin.vue b/packages/client/src/pages/settings/plugin.vue
index 50e53f459..d411ad296 100644
--- a/packages/client/src/pages/settings/plugin.vue
+++ b/packages/client/src/pages/settings/plugin.vue
@@ -1,23 +1,54 @@
 <template>
-<FormBase>
+<div class="_formRoot">
 	<FormLink to="/settings/plugin/install"><template #icon><i class="fas fa-download"></i></template>{{ $ts._plugin.install }}</FormLink>
-	<FormLink to="/settings/plugin/manage"><template #icon><i class="fas fa-folder-open"></i></template>{{ $ts._plugin.manage }}<template #suffix>{{ plugins }}</template></FormLink>
-</FormBase>
+
+	<FormSection>
+		<template #label>{{ $ts.manage }}</template>
+		<div v-for="plugin in plugins" :key="plugin.id" class="_formBlock _panel" style="padding: 20px;">
+			<span style="display: flex;"><b>{{ plugin.name }}</b><span style="margin-left: auto;">v{{ plugin.version }}</span></span>
+
+			<FormSwitch class="_formBlock" :modelValue="plugin.active" @update:modelValue="changeActive(plugin, $event)">{{ $ts.makeActive }}</FormSwitch>
+
+			<MkKeyValue class="_formBlock">
+				<template #key>{{ $ts.author }}</template>
+				<template #value>{{ plugin.author }}</template>
+			</MkKeyValue>
+			<MkKeyValue class="_formBlock">
+				<template #key>{{ $ts.description }}</template>
+				<template #value>{{ plugin.description }}</template>
+			</MkKeyValue>
+			<MkKeyValue class="_formBlock">
+				<template #key>{{ $ts.permission }}</template>
+				<template #value>{{ plugin.permission }}</template>
+			</MkKeyValue>
+
+			<div style="display: flex; gap: var(--margin); flex-wrap: wrap;">
+				<MkButton v-if="plugin.config" inline @click="config(plugin)"><i class="fas fa-cog"></i> {{ $ts.settings }}</MkButton>
+				<MkButton inline danger @click="uninstall(plugin)"><i class="fas fa-trash-alt"></i> {{ $ts.uninstall }}</MkButton>
+			</div>
+		</div>
+	</FormSection>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormLink from '@/components/debobigego/link.vue';
+import FormLink from '@/components/form/link.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormSection from '@/components/form/section.vue';
+import MkButton from '@/components/ui/button.vue';
+import MkKeyValue from '@/components/key-value.vue';
 import * as os from '@/os';
 import { ColdDeviceStorage } from '@/store';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		FormLink,
+		FormSwitch,
+		FormSection,
+		MkButton,
+		MkKeyValue,
 	},
 
 	emits: ['info'],
@@ -29,13 +60,52 @@ export default defineComponent({
 				icon: 'fas fa-plug',
 				bg: 'var(--bg)',
 			},
-			plugins: ColdDeviceStorage.get('plugins').length,
+			plugins: ColdDeviceStorage.get('plugins'),
 		}
 	},
 
 	mounted() {
 		this.$emit('info', this[symbols.PAGE_INFO]);
 	},
+
+	methods: {
+		uninstall(plugin) {
+			ColdDeviceStorage.set('plugins', this.plugins.filter(x => x.id !== plugin.id));
+			os.success();
+			this.$nextTick(() => {
+				unisonReload();
+			});
+		},
+
+		// TODO: この処理をstore側にactionとして移動し、設定画面を開くAiScriptAPIを実装できるようにする
+		async config(plugin) {
+			const config = plugin.config;
+			for (const key in plugin.configData) {
+				config[key].default = plugin.configData[key];
+			}
+
+			const { canceled, result } = await os.form(plugin.name, config);
+			if (canceled) return;
+
+			const plugins = ColdDeviceStorage.get('plugins');
+			plugins.find(p => p.id === plugin.id).configData = result;
+			ColdDeviceStorage.set('plugins', plugins);
+
+			this.$nextTick(() => {
+				location.reload();
+			});
+		},
+
+		changeActive(plugin, active) {
+			const plugins = ColdDeviceStorage.get('plugins');
+			plugins.find(p => p.id === plugin.id).active = active;
+			ColdDeviceStorage.set('plugins', plugins);
+
+			this.$nextTick(() => {
+				location.reload();
+			});
+		}
+	},
 });
 </script>
 

From 87c429b5bd63edcd4de36db519ee5e3cc4ef89a5 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 17:58:53 +0900
Subject: [PATCH 10/19] tweak ui

---
 .../client/src/pages/settings/custom-css.vue  | 25 ++++-------------
 .../client/src/pages/settings/mute-block.vue  | 28 +++++++------------
 2 files changed, 16 insertions(+), 37 deletions(-)

diff --git a/packages/client/src/pages/settings/custom-css.vue b/packages/client/src/pages/settings/custom-css.vue
index 155956923..6dbb8c2ae 100644
--- a/packages/client/src/pages/settings/custom-css.vue
+++ b/packages/client/src/pages/settings/custom-css.vue
@@ -1,25 +1,18 @@
 <template>
-<FormBase>
-	<FormInfo warn>{{ $ts.customCssWarn }}</FormInfo>
+<div class="_formRoot">
+	<FormInfo warn class="_formBlock">{{ $ts.customCssWarn }}</FormInfo>
 
-	<FormTextarea v-model="localCustomCss" manual-save tall class="_monospace" style="tab-size: 2;">
-		<span>{{ $ts.local }}</span>
+	<FormTextarea v-model="localCustomCss" manual-save tall class="_monospace _formBlock" style="tab-size: 2;">
+		<template #label>CSS</template>
 	</FormTextarea>
-</FormBase>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
 import FormTextarea from '@/components/form/textarea.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormRadios from '@/components/form/radios.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormInfo from '@/components/debobigego/info.vue';
+import FormInfo from '@/components/ui/info.vue';
 import * as os from '@/os';
-import { ColdDeviceStorage } from '@/store';
 import { unisonReload } from '@/scripts/unison-reload';
 import * as symbols from '@/symbols';
 import { defaultStore } from '@/store';
@@ -27,12 +20,6 @@ import { defaultStore } from '@/store';
 export default defineComponent({
 	components: {
 		FormTextarea,
-		FormSelect,
-		FormRadios,
-		FormBase,
-		FormGroup,
-		FormLink,
-		FormButton,
 		FormInfo,
 	},
 
diff --git a/packages/client/src/pages/settings/mute-block.vue b/packages/client/src/pages/settings/mute-block.vue
index 4f42d5e42..6a63c9eb2 100644
--- a/packages/client/src/pages/settings/mute-block.vue
+++ b/packages/client/src/pages/settings/mute-block.vue
@@ -1,5 +1,5 @@
 <template>
-<FormBase>
+<div class="_formRoot">
 	<MkTab v-model="tab" style="margin-bottom: var(--margin);">
 		<option value="mute">{{ $ts.mutedUsers }}</option>
 		<option value="block">{{ $ts.blockedUsers }}</option>
@@ -8,11 +8,9 @@
 		<MkPagination :pagination="mutingPagination" class="muting">
 			<template #empty><FormInfo>{{ $ts.noUsers }}</FormInfo></template>
 			<template v-slot="{items}">
-				<FormGroup>
-					<FormLink v-for="mute in items" :key="mute.id" :to="userPage(mute.mutee)">
-						<MkAcct :user="mute.mutee"/>
-					</FormLink>
-				</FormGroup>
+				<FormLink v-for="mute in items" :key="mute.id" :to="userPage(mute.mutee)">
+					<MkAcct :user="mute.mutee"/>
+				</FormLink>
 			</template>
 		</MkPagination>
 	</div>
@@ -20,25 +18,21 @@
 		<MkPagination :pagination="blockingPagination" class="blocking">
 			<template #empty><FormInfo>{{ $ts.noUsers }}</FormInfo></template>
 			<template v-slot="{items}">
-				<FormGroup>
-					<FormLink v-for="block in items" :key="block.id" :to="userPage(block.blockee)">
-						<MkAcct :user="block.blockee"/>
-					</FormLink>
-				</FormGroup>
+				<FormLink v-for="block in items" :key="block.id" :to="userPage(block.blockee)">
+					<MkAcct :user="block.blockee"/>
+				</FormLink>
 			</template>
 		</MkPagination>
 	</div>
-</FormBase>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
 import MkPagination from '@/components/ui/pagination.vue';
 import MkTab from '@/components/tab.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
+import FormInfo from '@/components/ui/info.vue';
+import FormLink from '@/components/form/link.vue';
 import { userPage } from '@/filters/user';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
@@ -48,8 +42,6 @@ export default defineComponent({
 		MkPagination,
 		MkTab,
 		FormInfo,
-		FormBase,
-		FormGroup,
 		FormLink,
 	},
 

From 9693b2166ac46861a00eaedc0f19912e0911bd5d Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 18:01:30 +0900
Subject: [PATCH 11/19] clean up

---
 .../server/api/endpoints/federation/dns.ts    | 44 -------------------
 1 file changed, 44 deletions(-)
 delete mode 100644 packages/backend/src/server/api/endpoints/federation/dns.ts

diff --git a/packages/backend/src/server/api/endpoints/federation/dns.ts b/packages/backend/src/server/api/endpoints/federation/dns.ts
deleted file mode 100644
index 76084ad08..000000000
--- a/packages/backend/src/server/api/endpoints/federation/dns.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { promises as dns } from 'dns';
-import $ from 'cafy';
-import define from '../../define';
-import { Instances } from '@/models/index';
-import { toPuny } from '@/misc/convert-host';
-
-const resolver = new dns.Resolver();
-resolver.setServers(['1.1.1.1']);
-
-export const meta = {
-	tags: ['federation'],
-
-	requireCredential: false as const,
-
-	params: {
-		host: {
-			validator: $.str,
-		},
-	},
-};
-
-// eslint-disable-next-line import/no-default-export
-export default define(meta, async (ps, me) => {
-	const instance = await Instances.findOneOrFail({ host: toPuny(ps.host) });
-
-	const [
-		resolved4,
-		resolved6,
-		resolvedCname,
-		resolvedTxt,
-	] = await Promise.all([
-		resolver.resolve4(instance.host).catch(() => []),
-		resolver.resolve6(instance.host).catch(() => []),
-		resolver.resolveCname(instance.host).catch(() => []),
-		resolver.resolveTxt(instance.host).catch(() => []),
-	]);
-
-	return {
-		a: resolved4,
-		aaaa: resolved6,
-		cname: resolvedCname,
-		txt: resolvedTxt,
-	};
-});

From 6c62c0681c31584c926eeb6c8929c6e5726a551f Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 18:21:00 +0900
Subject: [PATCH 12/19] tweak ui

---
 .../client/src/pages/settings/accounts.vue    | 32 +++++-------
 packages/client/src/pages/settings/api.vue    | 19 +++----
 packages/client/src/pages/settings/apps.vue   | 14 ++----
 .../client/src/pages/settings/integration.vue | 50 ++++++++-----------
 4 files changed, 46 insertions(+), 69 deletions(-)

diff --git a/packages/client/src/pages/settings/accounts.vue b/packages/client/src/pages/settings/accounts.vue
index 2d1e0eff4..9ff11adda 100644
--- a/packages/client/src/pages/settings/accounts.vue
+++ b/packages/client/src/pages/settings/accounts.vue
@@ -1,41 +1,35 @@
 <template>
-<FormBase>
+<div class="_formRoot">
 	<FormSuspense :p="init">
 		<FormButton primary @click="addAccount"><i class="fas fa-plus"></i> {{ $ts.addAccount }}</FormButton>
 
-		<div v-for="account in accounts" :key="account.id" class="_debobigegoItem _button" @click="menu(account, $event)">
-			<div class="_debobigegoPanel lcjjdxlm">
-				<div class="avatar">
-					<MkAvatar :user="account" class="avatar"/>
+		<div v-for="account in accounts" :key="account.id" class="_panel _button lcjjdxlm" @click="menu(account, $event)">
+			<div class="avatar">
+				<MkAvatar :user="account" class="avatar"/>
+			</div>
+			<div class="body">
+				<div class="name">
+					<MkUserName :user="account"/>
 				</div>
-				<div class="body">
-					<div class="name">
-						<MkUserName :user="account"/>
-					</div>
-					<div class="acct">
-						<MkAcct :user="account"/>
-					</div>
+				<div class="acct">
+					<MkAcct :user="account"/>
 				</div>
 			</div>
 		</div>
 	</FormSuspense>
-</FormBase>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
+import FormSuspense from '@/components/form/suspense.vue';
+import FormButton from '@/components/ui/button.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { getAccounts, addAccount, login } from '@/account';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		FormSuspense,
 		FormButton,
 	},
diff --git a/packages/client/src/pages/settings/api.vue b/packages/client/src/pages/settings/api.vue
index 30a4902a1..1a51b526f 100644
--- a/packages/client/src/pages/settings/api.vue
+++ b/packages/client/src/pages/settings/api.vue
@@ -1,25 +1,20 @@
 <template>
-<FormBase>
-	<FormButton primary @click="generateToken">{{ $ts.generateAccessToken }}</FormButton>
-	<FormLink to="/settings/apps">{{ $ts.manageAccessTokens }}</FormLink>
-	<FormLink to="/api-console" :behavior="isDesktop ? 'window' : null">API console</FormLink>
-</FormBase>
+<div class="_formRoot">
+	<FormButton primary class="_formBlock" @click="generateToken">{{ $ts.generateAccessToken }}</FormButton>
+	<FormLink to="/settings/apps" class="_formBlock">{{ $ts.manageAccessTokens }}</FormLink>
+	<FormLink to="/api-console" :behavior="isDesktop ? 'window' : null" class="_formBlock">API console</FormLink>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSwitch from '@/components/form/switch.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
+import FormLink from '@/components/form/link.vue';
+import FormButton from '@/components/ui/button.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		FormButton,
 		FormLink,
 	},
diff --git a/packages/client/src/pages/settings/apps.vue b/packages/client/src/pages/settings/apps.vue
index b5fe4e0ae..68952bbbd 100644
--- a/packages/client/src/pages/settings/apps.vue
+++ b/packages/client/src/pages/settings/apps.vue
@@ -1,5 +1,5 @@
 <template>
-<FormBase>
+<div class="_formRoot">
 	<FormPagination ref="list" :pagination="pagination">
 		<template #empty>
 			<div class="_fullinfo">
@@ -8,7 +8,7 @@
 			</div>
 		</template>
 		<template v-slot="{items}">
-			<div v-for="token in items" :key="token.id" class="_debobigegoPanel bfomjevm">
+			<div v-for="token in items" :key="token.id" class="_panel bfomjevm">
 				<img v-if="token.iconUrl" class="icon" :src="token.iconUrl" alt=""/>
 				<div class="body">
 					<div class="name">{{ token.name }}</div>
@@ -34,23 +34,17 @@
 			</div>
 		</template>
 	</FormPagination>
-</FormBase>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormPagination from '@/components/debobigego/pagination.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
+import FormPagination from '@/components/ui/pagination.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		FormPagination,
 	},
 
diff --git a/packages/client/src/pages/settings/integration.vue b/packages/client/src/pages/settings/integration.vue
index 3d8aaf8a6..e3dbc6fde 100644
--- a/packages/client/src/pages/settings/integration.vue
+++ b/packages/client/src/pages/settings/integration.vue
@@ -1,45 +1,39 @@
 <template>
-<FormBase>
-	<div v-if="enableTwitterIntegration" class="_debobigegoItem">
-		<div class="_debobigegoLabel"><i class="fab fa-twitter"></i> Twitter</div>
-		<div class="_debobigegoPanel" style="padding: 16px;">
-			<p v-if="integrations.twitter">{{ $ts.connectedTo }}: <a :href="`https://twitter.com/${integrations.twitter.screenName}`" rel="nofollow noopener" target="_blank">@{{ integrations.twitter.screenName }}</a></p>
-			<MkButton v-if="integrations.twitter" danger @click="disconnectTwitter">{{ $ts.disconnectService }}</MkButton>
-			<MkButton v-else primary @click="connectTwitter">{{ $ts.connectService }}</MkButton>
-		</div>
-	</div>
+<div class="_formRoot">
+	<FormSection v-if="enableTwitterIntegration">
+		<template #label><i class="fab fa-twitter"></i> Twitter</template>
+		<p v-if="integrations.twitter">{{ $ts.connectedTo }}: <a :href="`https://twitter.com/${integrations.twitter.screenName}`" rel="nofollow noopener" target="_blank">@{{ integrations.twitter.screenName }}</a></p>
+		<MkButton v-if="integrations.twitter" danger @click="disconnectTwitter">{{ $ts.disconnectService }}</MkButton>
+		<MkButton v-else primary @click="connectTwitter">{{ $ts.connectService }}</MkButton>
+	</FormSection>
 
-	<div v-if="enableDiscordIntegration" class="_debobigegoItem">
-		<div class="_debobigegoLabel"><i class="fab fa-discord"></i> Discord</div>
-		<div class="_debobigegoPanel" style="padding: 16px;">
-			<p v-if="integrations.discord">{{ $ts.connectedTo }}: <a :href="`https://discord.com/users/${integrations.discord.id}`" rel="nofollow noopener" target="_blank">@{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}</a></p>
-			<MkButton v-if="integrations.discord" danger @click="disconnectDiscord">{{ $ts.disconnectService }}</MkButton>
-			<MkButton v-else primary @click="connectDiscord">{{ $ts.connectService }}</MkButton>
-		</div>
-	</div>
+	<FormSection v-if="enableDiscordIntegration">
+		<template #label><i class="fab fa-discord"></i> Discord</template>
+		<p v-if="integrations.discord">{{ $ts.connectedTo }}: <a :href="`https://discord.com/users/${integrations.discord.id}`" rel="nofollow noopener" target="_blank">@{{ integrations.discord.username }}#{{ integrations.discord.discriminator }}</a></p>
+		<MkButton v-if="integrations.discord" danger @click="disconnectDiscord">{{ $ts.disconnectService }}</MkButton>
+		<MkButton v-else primary @click="connectDiscord">{{ $ts.connectService }}</MkButton>
+	</FormSection>
 
-	<div v-if="enableGithubIntegration" class="_debobigegoItem">
-		<div class="_debobigegoLabel"><i class="fab fa-github"></i> GitHub</div>
-		<div class="_debobigegoPanel" style="padding: 16px;">
-			<p v-if="integrations.github">{{ $ts.connectedTo }}: <a :href="`https://github.com/${integrations.github.login}`" rel="nofollow noopener" target="_blank">@{{ integrations.github.login }}</a></p>
-			<MkButton v-if="integrations.github" danger @click="disconnectGithub">{{ $ts.disconnectService }}</MkButton>
-			<MkButton v-else primary @click="connectGithub">{{ $ts.connectService }}</MkButton>
-		</div>
-	</div>
-</FormBase>
+	<FormSection v-if="enableGithubIntegration">
+		<template #label><i class="fab fa-github"></i> GitHub</template>
+		<p v-if="integrations.github">{{ $ts.connectedTo }}: <a :href="`https://github.com/${integrations.github.login}`" rel="nofollow noopener" target="_blank">@{{ integrations.github.login }}</a></p>
+		<MkButton v-if="integrations.github" danger @click="disconnectGithub">{{ $ts.disconnectService }}</MkButton>
+		<MkButton v-else primary @click="connectGithub">{{ $ts.connectService }}</MkButton>
+	</FormSection>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
 import { apiUrl } from '@/config';
-import FormBase from '@/components/debobigego/base.vue';
+import FormSection from '@/components/form/section.vue';
 import MkButton from '@/components/ui/button.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
+		FormSection,
 		MkButton
 	},
 

From 0ea5b38fb1fab7a97600abb79c80a442d81b5603 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 18:35:21 +0900
Subject: [PATCH 13/19] tweak ui

---
 .../src/pages/admin/integrations-discord.vue  | 32 +++++++++----------
 .../src/pages/admin/integrations-github.vue   | 32 +++++++++----------
 .../src/pages/admin/integrations-twitter.vue  | 32 +++++++++----------
 .../client/src/pages/admin/integrations.vue   | 28 ++++++----------
 4 files changed, 54 insertions(+), 70 deletions(-)

diff --git a/packages/client/src/pages/admin/integrations-discord.vue b/packages/client/src/pages/admin/integrations-discord.vue
index 383031f3d..9367ef04f 100644
--- a/packages/client/src/pages/admin/integrations-discord.vue
+++ b/packages/client/src/pages/admin/integrations-discord.vue
@@ -1,37 +1,36 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormSwitch v-model="enableDiscordIntegration">
-			{{ $ts.enable }}
+		<FormSwitch v-model="enableDiscordIntegration" class="_formBlock">
+			<template #label>{{ $ts.enable }}</template>
 		</FormSwitch>
 
 		<template v-if="enableDiscordIntegration">
-			<FormInfo>Callback URL: {{ `${uri}/api/dc/cb` }}</FormInfo>
+			<FormInfo class="_formBlock">Callback URL: {{ `${uri}/api/dc/cb` }}</FormInfo>
 		
-			<FormInput v-model="discordClientId">
+			<FormInput v-model="discordClientId" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				Client ID
+				<template #label>Client ID</template>
 			</FormInput>
 
-			<FormInput v-model="discordClientSecret">
+			<FormInput v-model="discordClientSecret" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				Client Secret
+				<template #label>Client Secret</template>
 			</FormInput>
 		</template>
 
-		<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+		<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormInput from '@/components/form/input.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormInfo from '@/components/ui/info.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
@@ -40,7 +39,6 @@ export default defineComponent({
 	components: {
 		FormSwitch,
 		FormInput,
-		FormBase,
 		FormInfo,
 		FormButton,
 		FormSuspense,
diff --git a/packages/client/src/pages/admin/integrations-github.vue b/packages/client/src/pages/admin/integrations-github.vue
index ecb2fd67f..7c257b6ec 100644
--- a/packages/client/src/pages/admin/integrations-github.vue
+++ b/packages/client/src/pages/admin/integrations-github.vue
@@ -1,37 +1,36 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormSwitch v-model="enableGithubIntegration">
-			{{ $ts.enable }}
+		<FormSwitch v-model="enableGithubIntegration" class="_formBlock">
+			<template #label>{{ $ts.enable }}</template>
 		</FormSwitch>
 
 		<template v-if="enableGithubIntegration">
-			<FormInfo>Callback URL: {{ `${uri}/api/gh/cb` }}</FormInfo>
+			<FormInfo class="_formBlock">Callback URL: {{ `${uri}/api/gh/cb` }}</FormInfo>
 		
-			<FormInput v-model="githubClientId">
+			<FormInput v-model="githubClientId" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				Client ID
+				<template #label>Client ID</template>
 			</FormInput>
 
-			<FormInput v-model="githubClientSecret">
+			<FormInput v-model="githubClientSecret" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				Client Secret
+				<template #label>Client Secret</template>
 			</FormInput>
 		</template>
 
-		<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+		<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormInput from '@/components/form/input.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormInfo from '@/components/ui/info.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
@@ -40,7 +39,6 @@ export default defineComponent({
 	components: {
 		FormSwitch,
 		FormInput,
-		FormBase,
 		FormInfo,
 		FormButton,
 		FormSuspense,
diff --git a/packages/client/src/pages/admin/integrations-twitter.vue b/packages/client/src/pages/admin/integrations-twitter.vue
index 1404102c5..4709103ee 100644
--- a/packages/client/src/pages/admin/integrations-twitter.vue
+++ b/packages/client/src/pages/admin/integrations-twitter.vue
@@ -1,37 +1,36 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormSwitch v-model="enableTwitterIntegration">
-			{{ $ts.enable }}
+		<FormSwitch v-model="enableTwitterIntegration" class="_formBlock">
+			<template #label>{{ $ts.enable }}</template>
 		</FormSwitch>
 
 		<template v-if="enableTwitterIntegration">
-			<FormInfo>Callback URL: {{ `${uri}/api/tw/cb` }}</FormInfo>
+			<FormInfo class="_formBlock">Callback URL: {{ `${uri}/api/tw/cb` }}</FormInfo>
 		
-			<FormInput v-model="twitterConsumerKey">
+			<FormInput v-model="twitterConsumerKey" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				Consumer Key
+				<template #label>Consumer Key</template>
 			</FormInput>
 
-			<FormInput v-model="twitterConsumerSecret">
+			<FormInput v-model="twitterConsumerSecret" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				Consumer Secret
+				<template #label>Consumer Secret</template>
 			</FormInput>
 		</template>
 
-		<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+		<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormInput from '@/components/form/input.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormInfo from '@/components/ui/info.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
@@ -40,7 +39,6 @@ export default defineComponent({
 	components: {
 		FormSwitch,
 		FormInput,
-		FormBase,
 		FormInfo,
 		FormButton,
 		FormSuspense,
diff --git a/packages/client/src/pages/admin/integrations.vue b/packages/client/src/pages/admin/integrations.vue
index c21eebc1c..6a6432d2e 100644
--- a/packages/client/src/pages/admin/integrations.vue
+++ b/packages/client/src/pages/admin/integrations.vue
@@ -1,32 +1,27 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormLink to="/admin/integrations/twitter">
+		<FormLink to="/admin/integrations/twitter" class="_formBlock">
 			<i class="fab fa-twitter"></i> Twitter
 			<template #suffix>{{ enableTwitterIntegration ? $ts.enabled : $ts.disabled }}</template>
 		</FormLink>
-		<FormLink to="/admin/integrations/github">
+		<FormLink to="/admin/integrations/github" class="_formBlock">
 			<i class="fab fa-github"></i> GitHub
 			<template #suffix>{{ enableGithubIntegration ? $ts.enabled : $ts.disabled }}</template>
 		</FormLink>
-		<FormLink to="/admin/integrations/discord">
+		<FormLink to="/admin/integrations/discord" class="_formBlock">
 			<i class="fab fa-discord"></i> Discord
 			<template #suffix>{{ enableDiscordIntegration ? $ts.enabled : $ts.disabled }}</template>
 		</FormLink>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormTextarea from '@/components/debobigego/textarea.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormLink from '@/components/form/link.vue';
+import FormSecion from '@/components/form/section.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
@@ -34,12 +29,7 @@ import { fetchInstance } from '@/instance';
 export default defineComponent({
 	components: {
 		FormLink,
-		FormInput,
-		FormBase,
-		FormGroup,
-		FormButton,
-		FormTextarea,
-		FormInfo,
+		FormSecion,
 		FormSuspense,
 	},
 

From 813f63663c034f24bffce9d3a17609bf421221ce Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 18:47:54 +0900
Subject: [PATCH 14/19] tweak ui

---
 .../client/src/pages/admin/instance-block.vue | 26 +++++----------
 .../client/src/pages/admin/service-worker.vue | 32 ++++++++-----------
 2 files changed, 22 insertions(+), 36 deletions(-)

diff --git a/packages/client/src/pages/admin/instance-block.vue b/packages/client/src/pages/admin/instance-block.vue
index 2e899de68..d1f7914ee 100644
--- a/packages/client/src/pages/admin/instance-block.vue
+++ b/packages/client/src/pages/admin/instance-block.vue
@@ -1,39 +1,29 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormTextarea v-model="blockedHosts">
+		<FormTextarea v-model="blockedHosts" class="_formBlock">
 			<span>{{ $ts.blockedInstances }}</span>
-			<template #desc>{{ $ts.blockedInstancesDescription }}</template>
+			<template #caption>{{ $ts.blockedInstancesDescription }}</template>
 		</FormTextarea>
 
-		<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+		<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormTextarea from '@/components/debobigego/textarea.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormTextarea from '@/components/form/textarea.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
 
 export default defineComponent({
 	components: {
-		FormSwitch,
-		FormInput,
-		FormBase,
-		FormGroup,
 		FormButton,
 		FormTextarea,
-		FormInfo,
 		FormSuspense,
 	},
 
diff --git a/packages/client/src/pages/admin/service-worker.vue b/packages/client/src/pages/admin/service-worker.vue
index f34cb03e4..eb4c2bb9a 100644
--- a/packages/client/src/pages/admin/service-worker.vue
+++ b/packages/client/src/pages/admin/service-worker.vue
@@ -1,36 +1,34 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormSwitch v-model="enableServiceWorker">
-			{{ $ts.enableServiceworker }}
-			<template #desc>{{ $ts.serviceworkerInfo }}</template>
+		<FormSwitch v-model="enableServiceWorker" class="_formBlock">
+			<template #label>{{ $ts.enableServiceworker }}</template>
+			<template #caption>{{ $ts.serviceworkerInfo }}</template>
 		</FormSwitch>
 
 		<template v-if="enableServiceWorker">
-			<FormInput v-model="swPublicKey">
+			<FormInput v-model="swPublicKey" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				Public key
+				<template #label>Public key</template>
 			</FormInput>
 
-			<FormInput v-model="swPrivateKey">
+			<FormInput v-model="swPrivateKey" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				Private key
+				<template #label>Private key</template>
 			</FormInput>
 		</template>
 
-		<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+		<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormInput from '@/components/form/input.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
@@ -39,8 +37,6 @@ export default defineComponent({
 	components: {
 		FormSwitch,
 		FormInput,
-		FormBase,
-		FormGroup,
 		FormButton,
 		FormSuspense,
 	},

From 89053d5747075bc6cc4ba5276167a826887fae08 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 21:16:41 +0900
Subject: [PATCH 15/19] tweak ui

---
 .../client/src/components/form/folder.vue     | 101 ++++++++++++++++++
 .../client/src/pages/admin/bot-protection.vue | 101 ++++++++----------
 packages/client/src/pages/admin/index.vue     |   6 +-
 ...s-discord.vue => integrations.discord.vue} |   8 +-
 ...ons-github.vue => integrations.github.vue} |   8 +-
 ...s-twitter.vue => integrations.twitter.vue} |   8 +-
 .../client/src/pages/admin/integrations.vue   |  34 ++++--
 .../client/src/pages/admin/other-settings.vue |  45 ++++----
 .../client/src/pages/admin/proxy-account.vue  |  38 +++----
 packages/client/src/pages/admin/queue.vue     |  10 +-
 packages/client/src/pages/admin/security.vue  |  15 ++-
 packages/client/src/pages/settings/deck.vue   |  32 +++---
 12 files changed, 244 insertions(+), 162 deletions(-)
 create mode 100644 packages/client/src/components/form/folder.vue
 rename packages/client/src/pages/admin/{integrations-discord.vue => integrations.discord.vue} (94%)
 rename packages/client/src/pages/admin/{integrations-github.vue => integrations.github.vue} (94%)
 rename packages/client/src/pages/admin/{integrations-twitter.vue => integrations.twitter.vue} (94%)

diff --git a/packages/client/src/components/form/folder.vue b/packages/client/src/components/form/folder.vue
new file mode 100644
index 000000000..fe1220201
--- /dev/null
+++ b/packages/client/src/components/form/folder.vue
@@ -0,0 +1,101 @@
+<template>
+<div class="dwzlatin" :class="{ opened }">
+	<div class="header _button" @click="toggle">
+		<span class="icon"><slot name="icon"></slot></span>
+		<span class="text"><slot name="label"></slot></span>
+		<span class="right">
+			<span class="text"><slot name="suffix"></slot></span>
+			<i v-if="opened" class="fas fa-angle-up icon"></i>
+			<i v-else class="fas fa-angle-down icon"></i>
+		</span>
+	</div>
+	<keep-alive>
+		<div v-if="openedAtLeastOnce" v-show="opened" class="body">
+			<MkSpacer :margin-min="14" :margin-max="22">
+				<slot></slot>
+			</MkSpacer>
+		</div>
+	</keep-alive>
+</div>
+</template>
+
+<script lang="ts" setup>
+let opened = $ref(false);
+let openedAtLeastOnce = $ref(false);
+
+const toggle = () => {
+	opened = !opened;
+	if (opened) {
+		openedAtLeastOnce = true;
+	}
+};
+</script>
+
+<style lang="scss" scoped>
+.dwzlatin {
+	display: block;
+
+	> .header {
+		display: flex;
+		align-items: center;
+		width: 100%;
+		box-sizing: border-box;
+		padding: 12px 14px 12px 14px;
+		background: var(--buttonBg);
+		border-radius: 6px;
+
+		&:hover {
+			text-decoration: none;
+			background: var(--buttonHoverBg);
+		}
+
+		&.active {
+			color: var(--accent);
+			background: var(--buttonHoverBg);
+		}
+
+		> .icon {
+			margin-right: 0.75em;
+			flex-shrink: 0;
+			text-align: center;
+			opacity: 0.8;
+
+			&:empty {
+				display: none;
+
+				& + .text {
+					padding-left: 4px;
+				}
+			}
+		}
+
+		> .text {
+			white-space: nowrap;
+			text-overflow: ellipsis;
+			overflow: hidden;
+			padding-right: 12px;
+		}
+
+		> .right {
+			margin-left: auto;
+			opacity: 0.7;
+			white-space: nowrap;
+
+			> .text:not(:empty) {
+				margin-right: 0.75em;
+			}
+		}
+	}
+
+	> .body {
+		background: var(--panel);
+		border-radius: 0 0 6px 6px;
+	}
+
+	&.opened {
+		> .header {
+			border-radius: 6px 6px 0 0;
+		}
+	}
+}
+</style>
diff --git a/packages/client/src/pages/admin/bot-protection.vue b/packages/client/src/pages/admin/bot-protection.vue
index 5a9708384..81b09fb4d 100644
--- a/packages/client/src/pages/admin/bot-protection.vue
+++ b/packages/client/src/pages/admin/bot-protection.vue
@@ -1,70 +1,55 @@
 <template>
-<FormBase>
+<div>
 	<FormSuspense :p="init">
-		<FormRadios v-model="provider">
-			<template #desc><i class="fas fa-shield-alt"></i> {{ $ts.botProtection }}</template>
-			<option :value="null">{{ $ts.none }} ({{ $ts.notRecommended }})</option>
-			<option value="hcaptcha">hCaptcha</option>
-			<option value="recaptcha">reCAPTCHA</option>
-		</FormRadios>
+		<div class="_formRoot">
+			<FormRadios v-model="provider" class="_formBlock">
+				<option :value="null">{{ $ts.none }} ({{ $ts.notRecommended }})</option>
+				<option value="hcaptcha">hCaptcha</option>
+				<option value="recaptcha">reCAPTCHA</option>
+			</FormRadios>
 
-		<template v-if="provider === 'hcaptcha'">
-			<div v-sticky-container class="_debobigegoItem _debobigegoNoConcat">
-				<div class="_debobigegoLabel">hCaptcha</div>
-				<div class="main">
-					<FormInput v-model="hcaptchaSiteKey">
-						<template #prefix><i class="fas fa-key"></i></template>
-						<span>{{ $ts.hcaptchaSiteKey }}</span>
-					</FormInput>
-					<FormInput v-model="hcaptchaSecretKey">
-						<template #prefix><i class="fas fa-key"></i></template>
-						<span>{{ $ts.hcaptchaSecretKey }}</span>
-					</FormInput>
-				</div>
-			</div>
-			<div v-sticky-container class="_debobigegoItem _debobigegoNoConcat">
-				<div class="_debobigegoLabel">{{ $ts.preview }}</div>
-				<div class="_debobigegoPanel" style="padding: var(--debobigegoContentHMargin);">
+			<template v-if="provider === 'hcaptcha'">
+				<FormInput v-model="hcaptchaSiteKey" class="_formBlock">
+					<template #prefix><i class="fas fa-key"></i></template>
+					<template #label>{{ $ts.hcaptchaSiteKey }}</template>
+				</FormInput>
+				<FormInput v-model="hcaptchaSecretKey" class="_formBlock">
+					<template #prefix><i class="fas fa-key"></i></template>
+					<template #label>{{ $ts.hcaptchaSecretKey }}</template>
+				</FormInput>
+				<FormSlot class="_formBlock">
+					<template #label>{{ $ts.preview }}</template>
 					<MkCaptcha provider="hcaptcha" :sitekey="hcaptchaSiteKey || '10000000-ffff-ffff-ffff-000000000001'"/>
-				</div>
-			</div>
-		</template>
-		<template v-else-if="provider === 'recaptcha'">
-			<div v-sticky-container class="_debobigegoItem _debobigegoNoConcat">
-				<div class="_debobigegoLabel">reCAPTCHA</div>
-				<div class="main">
-					<FormInput v-model="recaptchaSiteKey">
-						<template #prefix><i class="fas fa-key"></i></template>
-						<span>{{ $ts.recaptchaSiteKey }}</span>
-					</FormInput>
-					<FormInput v-model="recaptchaSecretKey">
-						<template #prefix><i class="fas fa-key"></i></template>
-						<span>{{ $ts.recaptchaSecretKey }}</span>
-					</FormInput>
-				</div>
-			</div>
-			<div v-if="recaptchaSiteKey" v-sticky-container class="_debobigegoItem _debobigegoNoConcat">
-				<div class="_debobigegoLabel">{{ $ts.preview }}</div>
-				<div class="_debobigegoPanel" style="padding: var(--debobigegoContentHMargin);">
+				</FormSlot>
+			</template>
+			<template v-else-if="provider === 'recaptcha'">
+				<FormInput v-model="recaptchaSiteKey" class="_formBlock">
+					<template #prefix><i class="fas fa-key"></i></template>
+					<template #label>{{ $ts.recaptchaSiteKey }}</template>
+				</FormInput>
+				<FormInput v-model="recaptchaSecretKey" class="_formBlock">
+					<template #prefix><i class="fas fa-key"></i></template>
+					<template #label>{{ $ts.recaptchaSecretKey }}</template>
+				</FormInput>
+				<FormSlot v-if="recaptchaSiteKey" class="_formBlock">
+					<template #label>{{ $ts.preview }}</template>
 					<MkCaptcha provider="recaptcha" :sitekey="recaptchaSiteKey"/>
-				</div>
-			</div>
-		</template>
+				</FormSlot>
+			</template>
 
-		<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+			<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+		</div>
 	</FormSuspense>
-</FormBase>
+</div>
 </template>
 
 <script lang="ts">
 import { defineAsyncComponent, defineComponent } from 'vue';
-import FormRadios from '@/components/debobigego/radios.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormRadios from '@/components/form/radios.vue';
+import FormInput from '@/components/form/input.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormSuspense from '@/components/form/suspense.vue';
+import FormSlot from '@/components/form/slot.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
@@ -73,11 +58,9 @@ export default defineComponent({
 	components: {
 		FormRadios,
 		FormInput,
-		FormBase,
-		FormGroup,
 		FormButton,
-		FormInfo,
 		FormSuspense,
+		FormSlot,
 		MkCaptcha: defineAsyncComponent(() => import('@/components/captcha.vue')),
 	},
 
diff --git a/packages/client/src/pages/admin/index.vue b/packages/client/src/pages/admin/index.vue
index 935b785b0..a628ce87a 100644
--- a/packages/client/src/pages/admin/index.vue
+++ b/packages/client/src/pages/admin/index.vue
@@ -10,7 +10,7 @@
 				</div>
 
 				<MkInfo v-if="noMaintainerInformation" warn class="info">{{ $ts.noMaintainerInformationWarning }} <MkA to="/admin/settings" class="_link">{{ $ts.configure }}</MkA></MkInfo>
-				<MkInfo v-if="noBotProtection" warn class="info">{{ $ts.noBotProtectionWarning }} <MkA to="/admin/bot-protection" class="_link">{{ $ts.configure }}</MkA></MkInfo>
+				<MkInfo v-if="noBotProtection" warn class="info">{{ $ts.noBotProtectionWarning }} <MkA to="/admin/security" class="_link">{{ $ts.configure }}</MkA></MkInfo>
 
 				<MkSuperMenu :def="menuDef" :grid="page == null"></MkSuperMenu>
 			</div>
@@ -228,13 +228,9 @@ export default defineComponent({
 				case 'email-settings': return defineAsyncComponent(() => import('./email-settings.vue'));
 				case 'object-storage': return defineAsyncComponent(() => import('./object-storage.vue'));
 				case 'security': return defineAsyncComponent(() => import('./security.vue'));
-				case 'bot-protection': return defineAsyncComponent(() => import('./bot-protection.vue'));
 				case 'service-worker': return defineAsyncComponent(() => import('./service-worker.vue'));
 				case 'relays': return defineAsyncComponent(() => import('./relays.vue'));
 				case 'integrations': return defineAsyncComponent(() => import('./integrations.vue'));
-				case 'integrations/twitter': return defineAsyncComponent(() => import('./integrations-twitter.vue'));
-				case 'integrations/github': return defineAsyncComponent(() => import('./integrations-github.vue'));
-				case 'integrations/discord': return defineAsyncComponent(() => import('./integrations-discord.vue'));
 				case 'instance-block': return defineAsyncComponent(() => import('./instance-block.vue'));
 				case 'proxy-account': return defineAsyncComponent(() => import('./proxy-account.vue'));
 				case 'other-settings': return defineAsyncComponent(() => import('./other-settings.vue'));
diff --git a/packages/client/src/pages/admin/integrations-discord.vue b/packages/client/src/pages/admin/integrations.discord.vue
similarity index 94%
rename from packages/client/src/pages/admin/integrations-discord.vue
rename to packages/client/src/pages/admin/integrations.discord.vue
index 9367ef04f..8303afa3b 100644
--- a/packages/client/src/pages/admin/integrations-discord.vue
+++ b/packages/client/src/pages/admin/integrations.discord.vue
@@ -1,6 +1,6 @@
 <template>
-<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
-	<FormSuspense :p="init">
+<FormSuspense :p="init">
+	<div class="_formRoot">
 		<FormSwitch v-model="enableDiscordIntegration" class="_formBlock">
 			<template #label>{{ $ts.enable }}</template>
 		</FormSwitch>
@@ -20,8 +20,8 @@
 		</template>
 
 		<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
-	</FormSuspense>
-</MkSpacer>
+	</div>
+</FormSuspense>
 </template>
 
 <script lang="ts">
diff --git a/packages/client/src/pages/admin/integrations-github.vue b/packages/client/src/pages/admin/integrations.github.vue
similarity index 94%
rename from packages/client/src/pages/admin/integrations-github.vue
rename to packages/client/src/pages/admin/integrations.github.vue
index 7c257b6ec..c0316c317 100644
--- a/packages/client/src/pages/admin/integrations-github.vue
+++ b/packages/client/src/pages/admin/integrations.github.vue
@@ -1,6 +1,6 @@
 <template>
-<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
-	<FormSuspense :p="init">
+<FormSuspense :p="init">
+	<div class="_formRoot">
 		<FormSwitch v-model="enableGithubIntegration" class="_formBlock">
 			<template #label>{{ $ts.enable }}</template>
 		</FormSwitch>
@@ -20,8 +20,8 @@
 		</template>
 
 		<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
-	</FormSuspense>
-</MkSpacer>
+	</div>
+</FormSuspense>
 </template>
 
 <script lang="ts">
diff --git a/packages/client/src/pages/admin/integrations-twitter.vue b/packages/client/src/pages/admin/integrations.twitter.vue
similarity index 94%
rename from packages/client/src/pages/admin/integrations-twitter.vue
rename to packages/client/src/pages/admin/integrations.twitter.vue
index 4709103ee..5feabcc39 100644
--- a/packages/client/src/pages/admin/integrations-twitter.vue
+++ b/packages/client/src/pages/admin/integrations.twitter.vue
@@ -1,6 +1,6 @@
 <template>
-<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
-	<FormSuspense :p="init">
+<FormSuspense :p="init">
+	<div class="_formRoot">
 		<FormSwitch v-model="enableTwitterIntegration" class="_formBlock">
 			<template #label>{{ $ts.enable }}</template>
 		</FormSwitch>
@@ -20,8 +20,8 @@
 		</template>
 
 		<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
-	</FormSuspense>
-</MkSpacer>
+	</div>
+</FormSuspense>
 </template>
 
 <script lang="ts">
diff --git a/packages/client/src/pages/admin/integrations.vue b/packages/client/src/pages/admin/integrations.vue
index 6a6432d2e..455fb6f4d 100644
--- a/packages/client/src/pages/admin/integrations.vue
+++ b/packages/client/src/pages/admin/integrations.vue
@@ -1,36 +1,48 @@
 <template>
 <MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormLink to="/admin/integrations/twitter" class="_formBlock">
-			<i class="fab fa-twitter"></i> Twitter
+		<FormFolder class="_formBlock">
+			<template #icon><i class="fab fa-twitter"></i></template>
+			<template #label>Twitter</template>
 			<template #suffix>{{ enableTwitterIntegration ? $ts.enabled : $ts.disabled }}</template>
-		</FormLink>
-		<FormLink to="/admin/integrations/github" class="_formBlock">
-			<i class="fab fa-github"></i> GitHub
+			<XTwitter/>
+		</FormFolder>
+		<FormFolder to="/admin/integrations/github" class="_formBlock">
+			<template #icon><i class="fab fa-github"></i></template>
+			<template #label>GitHub</template>
 			<template #suffix>{{ enableGithubIntegration ? $ts.enabled : $ts.disabled }}</template>
-		</FormLink>
-		<FormLink to="/admin/integrations/discord" class="_formBlock">
-			<i class="fab fa-discord"></i> Discord
+			<XGithub/>
+		</FormFolder>
+		<FormFolder to="/admin/integrations/discord" class="_formBlock">
+			<template #icon><i class="fab fa-discord"></i></template>
+			<template #label>Discord</template>
 			<template #suffix>{{ enableDiscordIntegration ? $ts.enabled : $ts.disabled }}</template>
-		</FormLink>
+			<XDiscord/>
+		</FormFolder>
 	</FormSuspense>
 </MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormLink from '@/components/form/link.vue';
+import FormFolder from '@/components/form/folder.vue';
 import FormSecion from '@/components/form/section.vue';
 import FormSuspense from '@/components/form/suspense.vue';
+import XTwitter from './integrations.twitter.vue';
+import XGithub from './integrations.github.vue';
+import XDiscord from './integrations.discord.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
 
 export default defineComponent({
 	components: {
-		FormLink,
+		FormFolder,
 		FormSecion,
 		FormSuspense,
+		XTwitter,
+		XGithub,
+		XDiscord,
 	},
 
 	emits: ['info'],
diff --git a/packages/client/src/pages/admin/other-settings.vue b/packages/client/src/pages/admin/other-settings.vue
index eb214a21c..eb47a3fa1 100644
--- a/packages/client/src/pages/admin/other-settings.vue
+++ b/packages/client/src/pages/admin/other-settings.vue
@@ -1,34 +1,31 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormGroup>
-			<FormInput v-model="summalyProxy">
+		<FormSection>
+			<FormInput v-model="summalyProxy" class="_formBlock">
 				<template #prefix><i class="fas fa-link"></i></template>
-				Summaly Proxy URL
+				<template #label>Summaly Proxy URL</template>
 			</FormInput>
-		</FormGroup>
-		<FormGroup>
-			<FormInput v-model="deeplAuthKey">
+		</FormSection>
+		<FormSection>
+			<FormInput v-model="deeplAuthKey" class="_formBlock">
 				<template #prefix><i class="fas fa-key"></i></template>
-				DeepL Auth Key
+				<template #label>DeepL Auth Key</template>
 			</FormInput>
-			<FormSwitch v-model="deeplIsPro">
-				Pro account
+			<FormSwitch v-model="deeplIsPro" class="_formBlock">
+				<template #label>Pro account</template>
 			</FormSwitch>
-		</FormGroup>
-		<FormButton primary @click="save"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
+		</FormSection>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormInput from '@/components/form/input.vue';
+import FormSection from '@/components/form/section.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
@@ -37,9 +34,7 @@ export default defineComponent({
 	components: {
 		FormSwitch,
 		FormInput,
-		FormBase,
-		FormGroup,
-		FormButton,
+		FormSection,
 		FormSuspense,
 	},
 
@@ -51,6 +46,12 @@ export default defineComponent({
 				title: this.$ts.other,
 				icon: 'fas fa-cogs',
 				bg: 'var(--bg)',
+				actions: [{
+					asFullButton: true,
+					icon: 'fas fa-check',
+					text: this.$ts.save,
+					handler: this.save,
+				}],
 			},
 			summalyProxy: '',
 			deeplAuthKey: '',
diff --git a/packages/client/src/pages/admin/proxy-account.vue b/packages/client/src/pages/admin/proxy-account.vue
index 14ef92a74..9878df912 100644
--- a/packages/client/src/pages/admin/proxy-account.vue
+++ b/packages/client/src/pages/admin/proxy-account.vue
@@ -1,42 +1,32 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
-		<FormGroup>
-			<FormKeyValueView>
-				<template #key>{{ $ts.proxyAccount }}</template>
-				<template #value>{{ proxyAccount ? `@${proxyAccount.username}` : $ts.none }}</template>
-			</FormKeyValueView>
-			<template #caption>{{ $ts.proxyAccountDescription }}</template>
-		</FormGroup>
+		<MkInfo class="_formBlock">{{ $ts.proxyAccountDescription }}</MkInfo>
+		<MkKeyValue class="_formBlock">
+			<template #key>{{ $ts.proxyAccount }}</template>
+			<template #value>{{ proxyAccount ? `@${proxyAccount.username}` : $ts.none }}</template>
+		</MkKeyValue>
 
-		<FormButton primary @click="chooseProxyAccount">{{ $ts.selectAccount }}</FormButton>
+		<FormButton primary class="_formBlock" @click="chooseProxyAccount">{{ $ts.selectAccount }}</FormButton>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormTextarea from '@/components/debobigego/textarea.vue';
-import FormInfo from '@/components/debobigego/info.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import MkKeyValue from '@/components/key-value.vue';
+import FormButton from '@/components/ui/button.vue';
+import MkInfo from '@/components/ui/info.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
 
 export default defineComponent({
 	components: {
-		FormKeyValueView,
-		FormInput,
-		FormBase,
-		FormGroup,
+		MkKeyValue,
 		FormButton,
-		FormTextarea,
-		FormInfo,
+		MkInfo,
 		FormSuspense,
 	},
 
diff --git a/packages/client/src/pages/admin/queue.vue b/packages/client/src/pages/admin/queue.vue
index 49f3c63e8..719a3c265 100644
--- a/packages/client/src/pages/admin/queue.vue
+++ b/packages/client/src/pages/admin/queue.vue
@@ -1,29 +1,25 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="800">
 	<XQueue :connection="connection" domain="inbox">
 		<template #title>In</template>
 	</XQueue>
 	<XQueue :connection="connection" domain="deliver">
 		<template #title>Out</template>
 	</XQueue>
-	<FormButton danger @click="clear()"><i class="fas fa-trash-alt"></i> {{ $ts.clearQueue }}</FormButton>
-</FormBase>
+	<MkButton danger @click="clear()"><i class="fas fa-trash-alt"></i> {{ $ts.clearQueue }}</MkButton>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent, markRaw } from 'vue';
 import MkButton from '@/components/ui/button.vue';
 import XQueue from './queue.chart.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormButton from '@/components/debobigego/button.vue';
 import * as os from '@/os';
 import { stream } from '@/stream';
 import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
-		FormButton,
 		MkButton,
 		XQueue,
 	},
diff --git a/packages/client/src/pages/admin/security.vue b/packages/client/src/pages/admin/security.vue
index 91b10b68c..d6ca9e0cb 100644
--- a/packages/client/src/pages/admin/security.vue
+++ b/packages/client/src/pages/admin/security.vue
@@ -2,12 +2,15 @@
 <MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense :p="init">
 		<div class="_formRoot">
-			<FormLink to="/admin/bot-protection" class="_formBlock">
-				<i class="fas fa-shield-alt"></i> {{ $ts.botProtection }}
+			<FormFolder class="_formBlock">
+				<template #icon><i class="fas fa-shield-alt"></i></template>
+				<template #label>{{ $ts.botProtection }}</template>
 				<template v-if="enableHcaptcha" #suffix>hCaptcha</template>
 				<template v-else-if="enableRecaptcha" #suffix>reCAPTCHA</template>
 				<template v-else #suffix>{{ $ts.none }} ({{ $ts.notRecommended }})</template>
-			</FormLink>
+
+				<XBotProtection/>
+			</FormFolder>
 		</div>
 	</FormSuspense>
 </MkSpacer>
@@ -15,22 +18,24 @@
 
 <script lang="ts">
 import { defineAsyncComponent, defineComponent } from 'vue';
-import FormLink from '@/components/form/link.vue';
+import FormFolder from '@/components/form/folder.vue';
 import FormSwitch from '@/components/form/switch.vue';
 import FormInfo from '@/components/ui/info.vue';
 import FormSuspense from '@/components/form/suspense.vue';
 import FormSection from '@/components/form/section.vue';
+import XBotProtection from './bot-protection.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import { fetchInstance } from '@/instance';
 
 export default defineComponent({
 	components: {
-		FormLink,
+		FormFolder,
 		FormSwitch,
 		FormInfo,
 		FormSection,
 		FormSuspense,
+		XBotProtection,
 	},
 
 	emits: ['info'],
diff --git a/packages/client/src/pages/settings/deck.vue b/packages/client/src/pages/settings/deck.vue
index bc82b0ca8..e290b095a 100644
--- a/packages/client/src/pages/settings/deck.vue
+++ b/packages/client/src/pages/settings/deck.vue
@@ -1,42 +1,41 @@
 <template>
-<FormBase>
+<div class="_formRoot">
 	<FormGroup>
 		<template #label>{{ $ts.defaultNavigationBehaviour }}</template>
 		<FormSwitch v-model="navWindow">{{ $ts.openInWindow }}</FormSwitch>
 	</FormGroup>
 
-	<FormSwitch v-model="alwaysShowMainColumn">{{ $ts._deck.alwaysShowMainColumn }}</FormSwitch>
+	<FormSwitch v-model="alwaysShowMainColumn" class="_formBlock">{{ $ts._deck.alwaysShowMainColumn }}</FormSwitch>
 
-	<FormRadios v-model="columnAlign">
-		<template #desc>{{ $ts._deck.columnAlign }}</template>
+	<FormRadios v-model="columnAlign" class="_formBlock">
+		<template #label>{{ $ts._deck.columnAlign }}</template>
 		<option value="left">{{ $ts.left }}</option>
 		<option value="center">{{ $ts.center }}</option>
 	</FormRadios>
 
-	<FormRadios v-model="columnHeaderHeight">
-		<template #desc>{{ $ts._deck.columnHeaderHeight }}</template>
+	<FormRadios v-model="columnHeaderHeight" class="_formBlock">
+		<template #label>{{ $ts._deck.columnHeaderHeight }}</template>
 		<option :value="42">{{ $ts.narrow }}</option>
 		<option :value="45">{{ $ts.medium }}</option>
 		<option :value="48">{{ $ts.wide }}</option>
 	</FormRadios>
 
-	<FormInput v-model="columnMargin" type="number">
-		<span>{{ $ts._deck.columnMargin }}</span>
+	<FormInput v-model="columnMargin" type="number" class="_formBlock">
+		<template #label>{{ $ts._deck.columnMargin }}</template>
 		<template #suffix>px</template>
 	</FormInput>
 
-	<FormLink @click="setProfile">{{ $ts._deck.profile }}<template #suffix>{{ profile }}</template></FormLink>
-</FormBase>
+	<FormLink class="_formBlock" @click="setProfile">{{ $ts._deck.profile }}<template #suffix>{{ profile }}</template></FormLink>
+</div>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormRadios from '@/components/debobigego/radios.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormLink from '@/components/form/link.vue';
+import FormRadios from '@/components/form/radios.vue';
+import FormInput from '@/components/form/input.vue';
+import FormGroup from '@/components/form/group.vue';
 import { deckStore } from '@/ui/deck/deck-store';
 import * as os from '@/os';
 import { unisonReload } from '@/scripts/unison-reload';
@@ -48,7 +47,6 @@ export default defineComponent({
 		FormLink,
 		FormInput,
 		FormRadios,
-		FormBase,
 		FormGroup,
 	},
 

From 76b2561893cfbfbb6bd33fe921d97d0645e5df74 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 21:37:16 +0900
Subject: [PATCH 16/19] tweak ui

---
 packages/client/src/pages/admin/database.vue  |  31 ++--
 .../src/pages/settings/account-info.vue       | 150 ++++++++----------
 2 files changed, 79 insertions(+), 102 deletions(-)

diff --git a/packages/client/src/pages/admin/database.vue b/packages/client/src/pages/admin/database.vue
index b09f1ad86..fc9a3e969 100644
--- a/packages/client/src/pages/admin/database.vue
+++ b/packages/client/src/pages/admin/database.vue
@@ -1,28 +1,18 @@
 <template>
-<FormBase>
+<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
 	<FormSuspense v-slot="{ result: database }" :p="databasePromiseFactory">
-		<FormGroup v-for="table in database" :key="table[0]">
-			<template #label>{{ table[0] }}</template>
-			<FormKeyValueView>
-				<template #key>Size</template>
-				<template #value>{{ bytes(table[1].size) }}</template>
-			</FormKeyValueView>
-			<FormKeyValueView>
-				<template #key>Records</template>
-				<template #value>{{ number(table[1].count) }}</template>
-			</FormKeyValueView>
-		</FormGroup>
+		<MkKeyValue v-for="table in database" :key="table[0]" oneline style="margin: 1em 0;">
+			<template #key>{{ table[0] }}</template>
+			<template #value>{{ bytes(table[1].size) }} ({{ number(table[1].count) }} recs)</template>
+		</MkKeyValue>
 	</FormSuspense>
-</FormBase>
+</MkSpacer>
 </template>
 
 <script lang="ts">
 import { defineComponent } from 'vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
+import FormSuspense from '@/components/form/suspense.vue';
+import MkKeyValue from '@/components/key-value.vue';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
 import bytes from '@/filters/bytes';
@@ -31,10 +21,7 @@ import number from '@/filters/number';
 export default defineComponent({
 	components: {
 		FormSuspense,
-		FormKeyValueView,
-		FormBase,
-		FormGroup,
-		FormLink,
+		MkKeyValue,
 	},
 
 	emits: ['info'],
diff --git a/packages/client/src/pages/settings/account-info.vue b/packages/client/src/pages/settings/account-info.vue
index f3d5e2f2c..1d6afd9d5 100644
--- a/packages/client/src/pages/settings/account-info.vue
+++ b/packages/client/src/pages/settings/account-info.vue
@@ -1,144 +1,139 @@
 <template>
-<FormBase>
-	<FormKeyValueView>
+<div class="_formRoot">
+	<MkKeyValue>
 		<template #key>ID</template>
 		<template #value><span class="_monospace">{{ $i.id }}</span></template>
-	</FormKeyValueView>
+	</MkKeyValue>
 
-	<FormGroup>
-		<FormKeyValueView>
+	<FormSection>
+		<MkKeyValue>
 			<template #key>{{ $ts.registeredDate }}</template>
 			<template #value><MkTime :time="$i.createdAt" mode="detail"/></template>
-		</FormKeyValueView>
-	</FormGroup>
+		</MkKeyValue>
+	</FormSection>
 
-	<FormGroup v-if="stats">
+	<FormSection v-if="stats">
 		<template #label>{{ $ts.statistics }}</template>
-		<FormKeyValueView>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.notesCount }}</template>
 			<template #value>{{ number(stats.notesCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.repliesCount }}</template>
 			<template #value>{{ number(stats.repliesCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.renotesCount }}</template>
 			<template #value>{{ number(stats.renotesCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.repliedCount }}</template>
 			<template #value>{{ number(stats.repliedCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.renotedCount }}</template>
 			<template #value>{{ number(stats.renotedCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.pollVotesCount }}</template>
 			<template #value>{{ number(stats.pollVotesCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.pollVotedCount }}</template>
 			<template #value>{{ number(stats.pollVotedCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.sentReactionsCount }}</template>
 			<template #value>{{ number(stats.sentReactionsCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.receivedReactionsCount }}</template>
 			<template #value>{{ number(stats.receivedReactionsCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.noteFavoritesCount }}</template>
 			<template #value>{{ number(stats.noteFavoritesCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.followingCount }}</template>
 			<template #value>{{ number(stats.followingCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.followingCount }} ({{ $ts.local }})</template>
 			<template #value>{{ number(stats.localFollowingCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.followingCount }} ({{ $ts.remote }})</template>
 			<template #value>{{ number(stats.remoteFollowingCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.followersCount }}</template>
 			<template #value>{{ number(stats.followersCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.followersCount }} ({{ $ts.local }})</template>
 			<template #value>{{ number(stats.localFollowersCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.followersCount }} ({{ $ts.remote }})</template>
 			<template #value>{{ number(stats.remoteFollowersCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.pageLikesCount }}</template>
 			<template #value>{{ number(stats.pageLikesCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.pageLikedCount }}</template>
 			<template #value>{{ number(stats.pageLikedCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.driveFilesCount }}</template>
 			<template #value>{{ number(stats.driveFilesCount) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.driveUsage }}</template>
 			<template #value>{{ bytes(stats.driveUsage) }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>{{ $ts.reversiCount }}</template>
 			<template #value>{{ number(stats.reversiCount) }}</template>
-		</FormKeyValueView>
-	</FormGroup>
+		</MkKeyValue>
+	</FormSection>
 
-	<FormGroup>
+	<FormSection>
 		<template #label>{{ $ts.other }}</template>
-		<FormKeyValueView>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>emailVerified</template>
 			<template #value>{{ $i.emailVerified ? $ts.yes : $ts.no }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>twoFactorEnabled</template>
 			<template #value>{{ $i.twoFactorEnabled ? $ts.yes : $ts.no }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>securityKeys</template>
 			<template #value>{{ $i.securityKeys ? $ts.yes : $ts.no }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>usePasswordLessLogin</template>
 			<template #value>{{ $i.usePasswordLessLogin ? $ts.yes : $ts.no }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>isModerator</template>
 			<template #value>{{ $i.isModerator ? $ts.yes : $ts.no }}</template>
-		</FormKeyValueView>
-		<FormKeyValueView>
+		</MkKeyValue>
+		<MkKeyValue oneline style="margin: 1em 0;">
 			<template #key>isAdmin</template>
 			<template #value>{{ $i.isAdmin ? $ts.yes : $ts.no }}</template>
-		</FormKeyValueView>
-	</FormGroup>
-</FormBase>
+		</MkKeyValue>
+	</FormSection>
+</div>
 </template>
 
 <script lang="ts">
 import { defineAsyncComponent, defineComponent } from 'vue';
-import FormSwitch from '@/components/form/switch.vue';
-import FormSelect from '@/components/form/select.vue';
-import FormLink from '@/components/debobigego/link.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormKeyValueView from '@/components/debobigego/key-value-view.vue';
+import FormSection from '@/components/form/section.vue';
+import MkKeyValue from '@/components/key-value.vue';
 import * as os from '@/os';
 import number from '@/filters/number';
 import bytes from '@/filters/bytes';
@@ -146,13 +141,8 @@ import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
-		FormSelect,
-		FormSwitch,
-		FormButton,
-		FormLink,
-		FormGroup,
-		FormKeyValueView,
+		FormSection,
+		MkKeyValue,
 	},
 
 	emits: ['info'],

From 69d7cfc5ce2ec9892290403cdc353e7ea3bd6a96 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 22:42:04 +0900
Subject: [PATCH 17/19] tweak ui

---
 .../client/src/components/debobigego/base.vue |  65 ----
 .../src/components/debobigego/button.vue      |  81 -----
 .../src/components/debobigego/debobigego.scss |  52 ----
 .../src/components/debobigego/group.vue       |  78 -----
 .../client/src/components/debobigego/info.vue |  47 ---
 .../src/components/debobigego/input.vue       | 292 ------------------
 .../components/debobigego/key-value-view.vue  |  38 ---
 .../client/src/components/debobigego/link.vue | 103 ------
 .../src/components/debobigego/object-view.vue | 102 ------
 .../src/components/debobigego/pagination.vue  |  42 ---
 .../src/components/debobigego/radios.vue      | 112 -------
 .../src/components/debobigego/range.vue       | 122 --------
 .../src/components/debobigego/select.vue      | 145 ---------
 .../src/components/debobigego/suspense.vue    | 101 ------
 .../src/components/debobigego/switch.vue      | 132 --------
 .../src/components/debobigego/textarea.vue    | 161 ----------
 .../src/components/debobigego/tuple.vue       |  36 ---
 .../client/src/components/form/folder.vue     |  10 +-
 .../client/src/components/object-view.vue     |  29 ++
 packages/client/src/pages/admin/database.vue  |   2 +-
 packages/client/src/pages/gallery/edit.vue    |  23 +-
 packages/client/src/pages/instance-info.vue   |   9 +-
 packages/client/src/pages/theme-editor.vue    | 220 ++++++-------
 packages/client/src/pages/user-info.vue       |   9 +-
 24 files changed, 170 insertions(+), 1841 deletions(-)
 delete mode 100644 packages/client/src/components/debobigego/base.vue
 delete mode 100644 packages/client/src/components/debobigego/button.vue
 delete mode 100644 packages/client/src/components/debobigego/debobigego.scss
 delete mode 100644 packages/client/src/components/debobigego/group.vue
 delete mode 100644 packages/client/src/components/debobigego/info.vue
 delete mode 100644 packages/client/src/components/debobigego/input.vue
 delete mode 100644 packages/client/src/components/debobigego/key-value-view.vue
 delete mode 100644 packages/client/src/components/debobigego/link.vue
 delete mode 100644 packages/client/src/components/debobigego/object-view.vue
 delete mode 100644 packages/client/src/components/debobigego/pagination.vue
 delete mode 100644 packages/client/src/components/debobigego/radios.vue
 delete mode 100644 packages/client/src/components/debobigego/range.vue
 delete mode 100644 packages/client/src/components/debobigego/select.vue
 delete mode 100644 packages/client/src/components/debobigego/suspense.vue
 delete mode 100644 packages/client/src/components/debobigego/switch.vue
 delete mode 100644 packages/client/src/components/debobigego/textarea.vue
 delete mode 100644 packages/client/src/components/debobigego/tuple.vue
 create mode 100644 packages/client/src/components/object-view.vue

diff --git a/packages/client/src/components/debobigego/base.vue b/packages/client/src/components/debobigego/base.vue
deleted file mode 100644
index 9ed59abc6..000000000
--- a/packages/client/src/components/debobigego/base.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-<template>
-<div v-size="{ max: [400] }" class="rbusrurv" :class="{ wide: forceWide }">
-	<slot></slot>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-
-export default defineComponent({
-	props: {
-		forceWide: {
-			type: Boolean,
-			required: false,
-			default: false,
-		}
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.rbusrurv {
-	// 他のCSSからも参照されるので消さないように
-	--debobigegoXPadding: 32px;
-	--debobigegoYPadding: 32px;
-
-	--debobigegoContentHMargin: 16px;
-
-	font-size: 95%;
-	line-height: 1.3em;
-	background: var(--bg);
-	padding: var(--debobigegoYPadding) var(--debobigegoXPadding);
-	max-width: 750px;
-	margin: 0 auto;
-
-	&:not(.wide).max-width_400px {
-		--debobigegoXPadding: 0px;
-
-		> ::v-deep(*) {
-			._debobigegoPanel {
-				border: solid 0.5px var(--divider);
-				border-radius: 0;
-				border-left: none;
-				border-right: none;
-			}
-
-			._debobigego_group {
-				> *:not(._debobigegoNoConcat) {
-					&:not(:last-child):not(._debobigegoNoConcatPrev) {
-						&._debobigegoPanel, ._debobigegoPanel {
-							border-bottom: solid 0.5px var(--divider);
-						}
-					}
-
-					&:not(:first-child):not(._debobigegoNoConcatNext) {
-						&._debobigegoPanel, ._debobigegoPanel {
-							border-top: none;
-						}
-					}
-				}
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/button.vue b/packages/client/src/components/debobigego/button.vue
deleted file mode 100644
index b883e817a..000000000
--- a/packages/client/src/components/debobigego/button.vue
+++ /dev/null
@@ -1,81 +0,0 @@
-<template>
-<div class="yzpgjkxe _debobigegoItem">
-	<div class="_debobigegoLabel"><slot name="label"></slot></div>
-	<button class="main _button _debobigegoPanel _debobigegoClickable" :class="{ center, primary, danger }">
-		<slot></slot>
-		<div class="suffix">
-			<slot name="suffix"></slot>
-			<div class="icon">
-				<slot name="suffixIcon"></slot>
-			</div>
-		</div>
-	</button>
-	<div class="_debobigegoCaption"><slot name="desc"></slot></div>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import './debobigego.scss';
-
-export default defineComponent({
-	props: {
-		primary: {
-			type: Boolean,
-			required: false,
-			default: false,
-		},
-		danger: {
-			type: Boolean,
-			required: false,
-			default: false,
-		},
-		disabled: {
-			type: Boolean,
-			required: false,
-			default: false,
-		},
-		center: {
-			type: Boolean,
-			required: false,
-			default: true,
-		}
-	},
-});
-</script>
-
-<style lang="scss" scoped>
-.yzpgjkxe {
-	> .main {
-		display: flex;
-		width: 100%;
-		box-sizing: border-box;
-		padding: 14px 16px;
-		text-align: left;
-		align-items: center;
-
-		&.center {
-			display: block;
-			text-align: center;
-		}
-
-		&.primary {
-			color: var(--accent);
-		}
-
-		&.danger {
-			color: #ff2a2a;
-		}
-
-		> .suffix {
-			display: inline-flex;
-			margin-left: auto;
-			opacity: 0.7;
-
-			> .icon {
-				margin-left: 1em;
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/debobigego.scss b/packages/client/src/components/debobigego/debobigego.scss
deleted file mode 100644
index 833b656b6..000000000
--- a/packages/client/src/components/debobigego/debobigego.scss
+++ /dev/null
@@ -1,52 +0,0 @@
-._debobigegoPanel {
-	background: var(--panel);
-	border-radius: var(--radius);
-	transition: background 0.2s ease;
-
-	&._debobigegoClickable {
-		&:hover {
-			//background: var(--panelHighlight);
-		}
-
-		&:active {
-			background: var(--panelHighlight);
-			transition: background 0s;
-		}
-	}
-}
-
-._debobigegoLabel,
-._debobigegoCaption {
-	font-size: 80%;
-	color: var(--fgTransparentWeak);
-
-	&:empty {
-		display: none;
-	}
-}
-
-._debobigegoLabel {
-	position: sticky;
-	top: var(--stickyTop, 0px);
-	z-index: 2;
-	margin: -8px calc(var(--debobigegoXPadding) * -1) 0 calc(var(--debobigegoXPadding) * -1);
-	padding: 8px calc(var(--debobigegoContentHMargin) + var(--debobigegoXPadding)) 8px calc(var(--debobigegoContentHMargin) + var(--debobigegoXPadding));
-	background: var(--X17);
-	-webkit-backdrop-filter: var(--blur, blur(10px));
-	backdrop-filter: var(--blur, blur(10px));
-}
-
-._themeChanging_ ._debobigegoLabel {
-	transition: none !important;
-	background: transparent;
-}
-
-._debobigegoCaption {
-	padding: 8px var(--debobigegoContentHMargin) 0 var(--debobigegoContentHMargin);
-}
-
-._debobigegoItem {
-	& + ._debobigegoItem {
-		margin-top: 24px;
-	}
-}
diff --git a/packages/client/src/components/debobigego/group.vue b/packages/client/src/components/debobigego/group.vue
deleted file mode 100644
index 871d3c8db..000000000
--- a/packages/client/src/components/debobigego/group.vue
+++ /dev/null
@@ -1,78 +0,0 @@
-<template>
-<div v-size="{ max: [500] }" v-sticky-container class="vrtktovg _debobigegoItem _debobigegoNoConcat">
-	<div class="_debobigegoLabel"><slot name="label"></slot></div>
-	<div ref="child" class="main _debobigego_group">
-		<slot></slot>
-	</div>
-	<div class="_debobigegoCaption"><slot name="caption"></slot></div>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent, onMounted, ref } from 'vue';
-
-export default defineComponent({
-	setup(props, context) {
-		const child = ref<HTMLElement | null>(null);
-
-		const scanChild = () => {
-			if (child.value == null) return;
-			const els = Array.from(child.value.children);
-			for (let i = 0; i < els.length; i++) {
-				const el = els[i];
-				if (el.classList.contains('_debobigegoNoConcat')) {
-					if (els[i - 1]) els[i - 1].classList.add('_debobigegoNoConcatPrev');
-					if (els[i + 1]) els[i + 1].classList.add('_debobigegoNoConcatNext');
-				}
-			}
-		};
-
-		onMounted(() => {
-			scanChild();
-
-			const observer = new MutationObserver(records => {
-				scanChild();
-			});
-
-			observer.observe(child.value, {
-				childList: true,
-				subtree: false,
-				attributes: false,
-				characterData: false,
-			});
-		});
-
-		return {
-			child
-		};
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.vrtktovg {
-	> .main {
-		> ::v-deep(*):not(._debobigegoNoConcat) {
-			&:not(._debobigegoNoConcatNext) {
-				margin: 0;
-			}
-
-			&:not(:last-child):not(._debobigegoNoConcatPrev) {
-				&._debobigegoPanel, ._debobigegoPanel {
-					border-bottom: solid 0.5px var(--divider);
-					border-bottom-left-radius: 0;
-					border-bottom-right-radius: 0;
-				}
-			}
-
-			&:not(:first-child):not(._debobigegoNoConcatNext) {
-				&._debobigegoPanel, ._debobigegoPanel {
-					border-top: none;
-					border-top-left-radius: 0;
-					border-top-right-radius: 0;
-				}
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/info.vue b/packages/client/src/components/debobigego/info.vue
deleted file mode 100644
index 41afb0330..000000000
--- a/packages/client/src/components/debobigego/info.vue
+++ /dev/null
@@ -1,47 +0,0 @@
-<template>
-<div class="fzenkabp _debobigegoItem">
-	<div class="_debobigegoPanel" :class="{ warn }">
-		<i v-if="warn" class="fas fa-exclamation-triangle"></i>
-		<i v-else class="fas fa-info-circle"></i>
-		<slot></slot>
-	</div>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-
-export default defineComponent({
-	props: {
-		warn: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-	},
-	data() {
-		return {
-		};
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.fzenkabp {
-	> div {
-		padding: 14px 16px;
-		font-size: 90%;
-		background: var(--infoBg);
-		color: var(--infoFg);
-
-		&.warn {
-			background: var(--infoWarnBg);
-			color: var(--infoWarnFg);
-		}
-
-		> i {
-			margin-right: 4px;
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/input.vue b/packages/client/src/components/debobigego/input.vue
deleted file mode 100644
index 6228a33fe..000000000
--- a/packages/client/src/components/debobigego/input.vue
+++ /dev/null
@@ -1,292 +0,0 @@
-<template>
-<FormGroup class="_debobigegoItem">
-	<template #label><slot></slot></template>
-	<div class="ztzhwixg _debobigegoItem" :class="{ inline, disabled }">
-		<div ref="icon" class="icon"><slot name="icon"></slot></div>
-		<div class="input _debobigegoPanel">
-			<div ref="prefixEl" class="prefix"><slot name="prefix"></slot></div>
-			<input ref="inputEl"
-				v-model="v"
-				:type="type"
-				:disabled="disabled"
-				:required="required"
-				:readonly="readonly"
-				:placeholder="placeholder"
-				:pattern="pattern"
-				:autocomplete="autocomplete"
-				:spellcheck="spellcheck"
-				:step="step"
-				:list="id"
-				@focus="focused = true"
-				@blur="focused = false"
-				@keydown="onKeydown($event)"
-				@input="onInput"
-			>
-			<datalist v-if="datalist" :id="id">
-				<option v-for="data in datalist" :value="data"/>
-			</datalist>
-			<div ref="suffixEl" class="suffix"><slot name="suffix"></slot></div>
-		</div>
-	</div>
-	<template #caption><slot name="desc"></slot></template>
-
-	<FormButton v-if="manualSave && changed" primary @click="updated"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
-</FormGroup>
-</template>
-
-<script lang="ts">
-import { defineComponent, onMounted, onUnmounted, nextTick, ref, watch, computed, toRefs } from 'vue';
-import './debobigego.scss';
-import FormButton from './button.vue';
-import FormGroup from './group.vue';
-
-export default defineComponent({
-	components: {
-		FormGroup,
-		FormButton,
-	},
-	props: {
-		modelValue: {
-			required: false
-		},
-		type: {
-			type: String,
-			required: false
-		},
-		required: {
-			type: Boolean,
-			required: false
-		},
-		readonly: {
-			type: Boolean,
-			required: false
-		},
-		disabled: {
-			type: Boolean,
-			required: false
-		},
-		pattern: {
-			type: String,
-			required: false
-		},
-		placeholder: {
-			type: String,
-			required: false
-		},
-		autofocus: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-		autocomplete: {
-			required: false
-		},
-		spellcheck: {
-			required: false
-		},
-		step: {
-			required: false
-		},
-		datalist: {
-			type: Array,
-			required: false,
-		},
-		inline: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-		manualSave: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-	},
-	emits: ['change', 'keydown', 'enter', 'update:modelValue'],
-	setup(props, context) {
-		const { modelValue, type, autofocus } = toRefs(props);
-		const v = ref(modelValue.value);
-		const id = Math.random().toString(); // TODO: uuid?
-		const focused = ref(false);
-		const changed = ref(false);
-		const invalid = ref(false);
-		const filled = computed(() => v.value !== '' && v.value != null);
-		const inputEl = ref(null);
-		const prefixEl = ref(null);
-		const suffixEl = ref(null);
-
-		const focus = () => inputEl.value.focus();
-		const onInput = (ev) => {
-			changed.value = true;
-			context.emit('change', ev);
-		};
-		const onKeydown = (ev: KeyboardEvent) => {
-			context.emit('keydown', ev);
-
-			if (ev.code === 'Enter') {
-				context.emit('enter');
-			}
-		};
-
-		const updated = () => {
-			changed.value = false;
-			if (type?.value === 'number') {
-				context.emit('update:modelValue', parseFloat(v.value));
-			} else {
-				context.emit('update:modelValue', v.value);
-			}
-		};
-
-		watch(modelValue.value, newValue => {
-			v.value = newValue;
-		});
-
-		watch(v, newValue => {
-			if (!props.manualSave) {
-				updated();
-			}
-
-			invalid.value = inputEl.value.validity.badInput;
-		});
-
-		onMounted(() => {
-			nextTick(() => {
-				if (autofocus.value) {
-					focus();
-				}
-
-				// このコンポーネントが作成された時、非表示状態である場合がある
-				// 非表示状態だと要素の幅などは0になってしまうので、定期的に計算する
-				const clock = setInterval(() => {
-					if (prefixEl.value) {
-						if (prefixEl.value.offsetWidth) {
-							inputEl.value.style.paddingLeft = prefixEl.value.offsetWidth + 'px';
-						}
-					}
-					if (suffixEl.value) {
-						if (suffixEl.value.offsetWidth) {
-							inputEl.value.style.paddingRight = suffixEl.value.offsetWidth + 'px';
-						}
-					}
-				}, 100);
-
-				onUnmounted(() => {
-					clearInterval(clock);
-				});
-			});
-		});
-
-		return {
-			id,
-			v,
-			focused,
-			invalid,
-			changed,
-			filled,
-			inputEl,
-			prefixEl,
-			suffixEl,
-			focus,
-			onInput,
-			onKeydown,
-			updated,
-		};
-	},
-});
-</script>
-
-<style lang="scss" scoped>
-.ztzhwixg {
-	position: relative;
-
-	> .icon {
-		position: absolute;
-		top: 0;
-		left: 0;
-		width: 24px;
-		text-align: center;
-		line-height: 32px;
-
-		&:not(:empty) + .input {
-			margin-left: 28px;
-		}
-	}
-
-	> .input {
-		$height: 48px;
-		position: relative;
-
-		> input {
-			display: block;
-			height: $height;
-			width: 100%;
-			margin: 0;
-			padding: 0 16px;
-			font: inherit;
-			font-weight: normal;
-			font-size: 1em;
-			line-height: $height;
-			color: var(--inputText);
-			background: transparent;
-			border: none;
-			border-radius: 0;
-			outline: none;
-			box-shadow: none;
-			box-sizing: border-box;
-
-			&[type='file'] {
-				display: none;
-			}
-		}
-
-		> .prefix,
-		> .suffix {
-			display: block;
-			position: absolute;
-			z-index: 1;
-			top: 0;
-			padding: 0 16px;
-			font-size: 1em;
-			line-height: $height;
-			color: var(--inputLabel);
-			pointer-events: none;
-
-			&:empty {
-				display: none;
-			}
-
-			> * {
-				display: inline-block;
-				min-width: 16px;
-				max-width: 150px;
-				overflow: hidden;
-				white-space: nowrap;
-				text-overflow: ellipsis;
-			}
-		}
-
-		> .prefix {
-			left: 0;
-			padding-right: 8px;
-		}
-
-		> .suffix {
-			right: 0;
-			padding-left: 8px;
-		}
-	}
-
-	&.inline {
-		display: inline-block;
-		margin: 0;
-	}
-
-	&.disabled {
-		opacity: 0.7;
-
-		&, * {
-			cursor: not-allowed !important;
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/key-value-view.vue b/packages/client/src/components/debobigego/key-value-view.vue
deleted file mode 100644
index 0e034a2d5..000000000
--- a/packages/client/src/components/debobigego/key-value-view.vue
+++ /dev/null
@@ -1,38 +0,0 @@
-<template>
-<div class="_debobigegoItem">
-	<div class="_debobigegoPanel anocepby">
-		<span class="key"><slot name="key"></slot></span>
-		<span class="value"><slot name="value"></slot></span>
-	</div>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import './debobigego.scss';
-
-export default defineComponent({
-
-});
-</script>
-
-<style lang="scss" scoped>
-.anocepby {
-	display: flex;
-	align-items: center;
-	padding: 14px var(--debobigegoContentHMargin);
-
-	> .key {
-		margin-right: 12px;
-		white-space: nowrap;
-	}
-
-	> .value {
-		margin-left: auto;
-		opacity: 0.7;
-		text-overflow: ellipsis;
-		white-space: nowrap;
-		overflow: hidden;
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/link.vue b/packages/client/src/components/debobigego/link.vue
deleted file mode 100644
index de463465d..000000000
--- a/packages/client/src/components/debobigego/link.vue
+++ /dev/null
@@ -1,103 +0,0 @@
-<template>
-<div class="qmfkfnzi _debobigegoItem">
-	<a v-if="external" class="main _button _debobigegoPanel _debobigegoClickable" :href="to" target="_blank">
-		<span class="icon"><slot name="icon"></slot></span>
-		<span class="text"><slot></slot></span>
-		<span class="right">
-			<span class="text"><slot name="suffix"></slot></span>
-			<i class="fas fa-external-link-alt icon"></i>
-		</span>
-	</a>
-	<MkA v-else class="main _button _debobigegoPanel _debobigegoClickable" :class="{ active }" :to="to" :behavior="behavior">
-		<span class="icon"><slot name="icon"></slot></span>
-		<span class="text"><slot></slot></span>
-		<span class="right">
-			<span class="text"><slot name="suffix"></slot></span>
-			<i class="fas fa-chevron-right icon"></i>
-		</span>
-	</MkA>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import './debobigego.scss';
-
-export default defineComponent({
-	props: {
-		to: {
-			type: String,
-			required: true
-		},
-		active: {
-			type: Boolean,
-			required: false
-		},
-		external: {
-			type: Boolean,
-			required: false
-		},
-		behavior: {
-			type: String,
-			required: false,
-		},
-	},
-	data() {
-		return {
-		};
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.qmfkfnzi {
-	> .main {
-		display: flex;
-		align-items: center;
-		width: 100%;
-		box-sizing: border-box;
-		padding: 14px 16px 14px 14px;
-
-		&:hover {
-			text-decoration: none;
-		}
-
-		&.active {
-			color: var(--accent);
-			background: var(--panelHighlight);
-		}
-
-		> .icon {
-			width: 32px;
-			margin-right: 2px;
-			flex-shrink: 0;
-			text-align: center;
-			opacity: 0.8;
-
-			&:empty {
-				display: none;
-
-				& + .text {
-					padding-left: 4px;
-				}
-			}
-		}
-
-		> .text {
-			white-space: nowrap;
-			text-overflow: ellipsis;
-			overflow: hidden;
-			padding-right: 12px;
-		}
-
-		> .right {
-			margin-left: auto;
-			opacity: 0.7;
-
-			> .text:not(:empty) {
-				margin-right: 0.75em;
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/object-view.vue b/packages/client/src/components/debobigego/object-view.vue
deleted file mode 100644
index 68be08560..000000000
--- a/packages/client/src/components/debobigego/object-view.vue
+++ /dev/null
@@ -1,102 +0,0 @@
-<template>
-<FormGroup class="_debobigegoItem">
-	<template #label><slot></slot></template>
-	<div class="drooglns _debobigegoItem" :class="{ tall }">
-		<div class="input _debobigegoPanel">
-			<textarea v-model="v"
-				class="_monospace"
-				readonly
-				:spellcheck="false"
-			></textarea>
-		</div>
-	</div>
-	<template #caption><slot name="desc"></slot></template>
-</FormGroup>
-</template>
-
-<script lang="ts">
-import { defineComponent, ref, toRefs, watch } from 'vue';
-import * as JSON5 from 'json5';
-import './debobigego.scss';
-import FormGroup from './group.vue';
-
-export default defineComponent({
-	components: {
-		FormGroup,
-	},
-	props: {
-		value: {
-			required: false
-		},
-		tall: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-		pre: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-		manualSave: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-	},
-	setup(props, context) {
-		const { value } = toRefs(props);
-		const v = ref('');
-
-		watch(() => value, newValue => {
-			v.value = JSON5.stringify(newValue.value, null, '\t');
-		}, {
-			immediate: true
-		});
-
-		return {
-			v,
-		};
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.drooglns {
-	position: relative;
-
-	> .input {
-		position: relative;
-	
-		> textarea {
-			display: block;
-			width: 100%;
-			min-width: 100%;
-			max-width: 100%;
-			min-height: 130px;
-			margin: 0;
-			padding: 16px var(--debobigegoContentHMargin);
-			box-sizing: border-box;
-			font: inherit;
-			font-weight: normal;
-			font-size: 1em;
-			background: transparent;
-			border: none;
-			border-radius: 0;
-			outline: none;
-			box-shadow: none;
-			color: var(--fg);
-			tab-size: 2;
-			white-space: pre;
-		}
-	}
-
-	&.tall {
-		> .input {
-			> textarea {
-				min-height: 200px;
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/pagination.vue b/packages/client/src/components/debobigego/pagination.vue
deleted file mode 100644
index 16779caa4..000000000
--- a/packages/client/src/components/debobigego/pagination.vue
+++ /dev/null
@@ -1,42 +0,0 @@
-<template>
-<FormGroup class="uljviswt _debobigegoItem">
-	<template #label><slot name="label"></slot></template>
-	<slot :items="items"></slot>
-	<div v-if="empty" key="_empty_" class="empty">
-		<slot name="empty"></slot>
-	</div>
-	<FormButton v-show="more" class="button" :disabled="moreFetching" :style="{ cursor: moreFetching ? 'wait' : 'pointer' }" primary @click="fetchMore">
-		<template v-if="!moreFetching">{{ $ts.loadMore }}</template>
-		<template v-if="moreFetching"><MkLoading inline/></template>
-	</FormButton>
-</FormGroup>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import FormButton from './button.vue';
-import FormGroup from './group.vue';
-import paging from '@/scripts/paging';
-
-export default defineComponent({
-	components: {
-		FormButton,
-		FormGroup,
-	},
-
-	mixins: [
-		paging({}),
-	],
-
-	props: {
-		pagination: {
-			required: true
-		},
-	},
-});
-</script>
-
-<style lang="scss" scoped>
-.uljviswt {
-}
-</style>
diff --git a/packages/client/src/components/debobigego/radios.vue b/packages/client/src/components/debobigego/radios.vue
deleted file mode 100644
index b4c584133..000000000
--- a/packages/client/src/components/debobigego/radios.vue
+++ /dev/null
@@ -1,112 +0,0 @@
-<script lang="ts">
-import { defineComponent, h } from 'vue';
-import MkRadio from '@/components/form/radio.vue';
-import './debobigego.scss';
-
-export default defineComponent({
-	components: {
-		MkRadio
-	},
-	props: {
-		modelValue: {
-			required: false
-		},
-	},
-	data() {
-		return {
-			value: this.modelValue,
-		}
-	},
-	watch: {
-		modelValue() {
-			this.value = this.modelValue;
-		},
-		value() {
-			this.$emit('update:modelValue', this.value);
-		}
-	},
-	render() {
-		const label = this.$slots.desc();
-		let options = this.$slots.default();
-
-		// なぜかFragmentになることがあるため
-		if (options.length === 1 && options[0].props == null) options = options[0].children;
-
-		return h('div', {
-			class: 'cnklmpwm _debobigegoItem'
-		}, [
-			h('div', {
-				class: '_debobigegoLabel',
-			}, label),
-			...options.map(option => h('button', {
-				class: '_button _debobigegoPanel _debobigegoClickable',
-				key: option.key,
-				onClick: () => this.value = option.props.value,
-			}, [h('span', {
-				class: ['check', { checked: this.value === option.props.value }],
-			}), option.children]))
-		]);
-	}
-});
-</script>
-
-<style lang="scss">
-.cnklmpwm {
-	> button {
-		display: block;
-		width: 100%;
-		box-sizing: border-box;
-		padding: 14px 18px;
-		text-align: left;
-
-		&:not(:first-of-type) {
-			border-top: none !important;
-			border-top-left-radius: 0;
-			border-top-right-radius: 0;
-		}
-
-		&:not(:last-of-type) {
-			border-bottom: solid 0.5px var(--divider);
-			border-bottom-left-radius: 0;
-			border-bottom-right-radius: 0;
-		}
-
-		> .check {
-			display: inline-block;
-			vertical-align: bottom;
-			position: relative;
-			width: 16px;
-			height: 16px;
-			margin-right: 8px;
-			background: none;
-			border: 2px solid var(--inputBorder);
-			border-radius: 100%;
-			transition: inherit;
-
-			&:after {
-				content: "";
-				display: block;
-				position: absolute;
-				top: 3px;
-				right: 3px;
-				bottom: 3px;
-				left: 3px;
-				border-radius: 100%;
-				opacity: 0;
-				transform: scale(0);
-				transition: .4s cubic-bezier(.25,.8,.25,1);
-			}
-
-			&.checked {
-				border-color: var(--accent);
-
-				&:after {
-					background-color: var(--accent);
-					transform: scale(1);
-					opacity: 1;
-				}
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/range.vue b/packages/client/src/components/debobigego/range.vue
deleted file mode 100644
index dc71f25d8..000000000
--- a/packages/client/src/components/debobigego/range.vue
+++ /dev/null
@@ -1,122 +0,0 @@
-<template>
-<div class="ifitouly _debobigegoItem" :class="{ focused, disabled }">
-	<div class="_debobigegoLabel"><slot name="label"></slot></div>
-	<div class="_debobigegoPanel main">
-		<input
-			ref="input"
-			v-model="v"
-			type="range"
-			:disabled="disabled"
-			:min="min"
-			:max="max"
-			:step="step"
-			@focus="focused = true"
-			@blur="focused = false"
-			@input="$emit('update:value', $event.target.value)"
-		/>
-	</div>
-	<div class="_debobigegoCaption"><slot name="caption"></slot></div>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-
-export default defineComponent({
-	props: {
-		value: {
-			type: Number,
-			required: false,
-			default: 0
-		},
-		disabled: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-		min: {
-			type: Number,
-			required: false,
-			default: 0
-		},
-		max: {
-			type: Number,
-			required: false,
-			default: 100
-		},
-		step: {
-			type: Number,
-			required: false,
-			default: 1
-		},
-	},
-	data() {
-		return {
-			v: this.value,
-			focused: false
-		};
-	},
-	watch: {
-		value(v) {
-			this.v = parseFloat(v);
-		}
-	},
-});
-</script>
-
-<style lang="scss" scoped>
-.ifitouly {
-	position: relative;
-
-	> .main {
-		padding: 22px 16px;
-
-		> input {
-			display: block;
-			-webkit-appearance: none;
-			-moz-appearance: none;
-			appearance: none;
-			background: var(--X10);
-			height: 4px;
-			width: 100%;
-			box-sizing: border-box;
-			margin: 0;
-			outline: 0;
-			border: 0;
-			border-radius: 7px;
-
-			&.disabled {
-				opacity: 0.6;
-				cursor: not-allowed;
-			}
-
-			&::-webkit-slider-thumb {
-				-webkit-appearance: none;
-				appearance: none;
-				cursor: pointer;
-				width: 20px;
-				height: 20px;
-				display: block;
-				border-radius: 50%;
-				border: none;
-				background: var(--accent);
-				box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
-				box-sizing: content-box;
-			}
-
-			&::-moz-range-thumb {
-				-moz-appearance: none;
-				appearance: none;
-				cursor: pointer;
-				width: 20px;
-				height: 20px;
-				display: block;
-				border-radius: 50%;
-				border: none;
-				background: var(--accent);
-				box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/select.vue b/packages/client/src/components/debobigego/select.vue
deleted file mode 100644
index 081bbfe30..000000000
--- a/packages/client/src/components/debobigego/select.vue
+++ /dev/null
@@ -1,145 +0,0 @@
-<template>
-<div class="yrtfrpux _debobigegoItem" :class="{ disabled, inline }">
-	<div class="_debobigegoLabel"><slot name="label"></slot></div>
-	<div ref="icon" class="icon"><slot name="icon"></slot></div>
-	<div class="input _debobigegoPanel _debobigegoClickable" @click="focus">
-		<div ref="prefix" class="prefix"><slot name="prefix"></slot></div>
-		<select ref="input"
-			v-model="v"
-			:required="required"
-			:disabled="disabled"
-			@focus="focused = true"
-			@blur="focused = false"
-		>
-			<slot></slot>
-		</select>
-		<div class="suffix">
-			<i class="fas fa-chevron-down"></i>
-		</div>
-	</div>
-	<div class="_debobigegoCaption"><slot name="caption"></slot></div>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import './debobigego.scss';
-
-export default defineComponent({
-	props: {
-		modelValue: {
-			required: false
-		},
-		required: {
-			type: Boolean,
-			required: false
-		},
-		disabled: {
-			type: Boolean,
-			required: false
-		},
-		inline: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-	},
-	data() {
-		return {
-		};
-	},
-	computed: {
-		v: {
-			get() {
-				return this.modelValue;
-			},
-			set(v) {
-				this.$emit('update:modelValue', v);
-			}
-		},
-	},
-	methods: {
-		focus() {
-			this.$refs.input.focus();
-		}
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.yrtfrpux {
-	position: relative;
-
-	> .icon {
-		position: absolute;
-		top: 0;
-		left: 0;
-		width: 24px;
-		text-align: center;
-		line-height: 32px;
-
-		&:not(:empty) + .input {
-			margin-left: 28px;
-		}
-	}
-
-	> .input {
-		display: flex;
-		position: relative;
-
-		> select {
-			display: block;
-			flex: 1;
-			width: 100%;
-			padding: 0 16px;
-			font: inherit;
-			font-weight: normal;
-			font-size: 1em;
-			height: 48px;
-			background: none;
-			border: none;
-			border-radius: 0;
-			outline: none;
-			box-shadow: none;
-			appearance: none;
-			-webkit-appearance: none;
-			color: var(--fg);
-
-			option,
-			optgroup {
-				color: var(--fg);
-				background: var(--bg);
-			}
-		}
-
-		> .prefix,
-		> .suffix {
-			display: block;
-			align-self: center;
-			justify-self: center;
-			font-size: 1em;
-			line-height: 32px;
-			color: var(--inputLabel);
-			pointer-events: none;
-
-			&:empty {
-				display: none;
-			}
-
-			> * {
-				display: block;
-				min-width: 16px;
-			}
-		}
-
-		> .prefix {
-			padding-right: 4px;
-		}
-
-		> .suffix {
-			padding: 0 16px 0 0;
-			opacity: 0.7;
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/suspense.vue b/packages/client/src/components/debobigego/suspense.vue
deleted file mode 100644
index acb0b6442..000000000
--- a/packages/client/src/components/debobigego/suspense.vue
+++ /dev/null
@@ -1,101 +0,0 @@
-<template>
-<transition name="fade" mode="out-in">
-	<div v-if="pending" class="_debobigegoItem">
-		<div class="_debobigegoPanel">
-			<MkLoading/>
-		</div>
-	</div>
-	<div v-else-if="resolved" class="_debobigegoItem">
-		<slot :result="result"></slot>
-	</div>
-	<div v-else class="_debobigegoItem">
-		<div class="_debobigegoPanel eiurkvay">
-			<div><i class="fas fa-exclamation-triangle"></i> {{ $ts.somethingHappened }}</div>
-			<MkButton inline class="retry" @click="retry"><i class="fas fa-redo-alt"></i> {{ $ts.retry }}</MkButton>
-		</div>
-	</div>
-</transition>
-</template>
-
-<script lang="ts">
-import { defineComponent, PropType, ref, watch } from 'vue';
-import './debobigego.scss';
-import MkButton from '@/components/ui/button.vue';
-
-export default defineComponent({
-	components: {
-		MkButton
-	},
-
-	props: {
-		p: {
-			type: Function as PropType<() => Promise<any>>,
-			required: true,
-		}
-	},
-
-	setup(props, context) {
-		const pending = ref(true);
-		const resolved = ref(false);
-		const rejected = ref(false);
-		const result = ref(null);
-
-		const process = () => {
-			if (props.p == null) {
-				return;
-			}
-			const promise = props.p();
-			pending.value = true;
-			resolved.value = false;
-			rejected.value = false;
-			promise.then((_result) => {
-				pending.value = false;
-				resolved.value = true;
-				result.value = _result;
-			});
-			promise.catch(() => {
-				pending.value = false;
-				rejected.value = true;
-			});
-		};
-
-		watch(() => props.p, () => {
-			process();
-		}, {
-			immediate: true
-		});
-
-		const retry = () => {
-			process();
-		};
-
-		return {
-			pending,
-			resolved,
-			rejected,
-			result,
-			retry,
-		};
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.fade-enter-active,
-.fade-leave-active {
-	transition: opacity 0.125s ease;
-}
-.fade-enter-from,
-.fade-leave-to {
-	opacity: 0;
-}
-
-.eiurkvay {
-	padding: 16px;
-	text-align: center;
-
-	> .retry {
-		margin-top: 16px;
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/switch.vue b/packages/client/src/components/debobigego/switch.vue
deleted file mode 100644
index 239140f73..000000000
--- a/packages/client/src/components/debobigego/switch.vue
+++ /dev/null
@@ -1,132 +0,0 @@
-<template>
-<div class="ijnpvmgr _debobigegoItem">
-	<div class="main _debobigegoPanel _debobigegoClickable"
-		:class="{ disabled, checked }"
-		:aria-checked="checked"
-		:aria-disabled="disabled"
-		@click.prevent="toggle"
-	>
-		<input
-			ref="input"
-			type="checkbox"
-			:disabled="disabled"
-			@keydown.enter="toggle"
-		>
-		<span v-tooltip="checked ? $ts.itsOn : $ts.itsOff" class="button">
-			<span class="handle"></span>
-		</span>
-		<span class="label">
-			<span><slot></slot></span>
-		</span>
-	</div>
-	<div class="_debobigegoCaption"><slot name="desc"></slot></div>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-import './debobigego.scss';
-
-export default defineComponent({
-	props: {
-		modelValue: {
-			type: Boolean,
-			default: false
-		},
-		disabled: {
-			type: Boolean,
-			default: false
-		}
-	},
-	computed: {
-		checked(): boolean {
-			return this.modelValue;
-		}
-	},
-	methods: {
-		toggle() {
-			if (this.disabled) return;
-			this.$emit('update:modelValue', !this.checked);
-		}
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.ijnpvmgr {
-	> .main {
-		position: relative;
-		display: flex;
-		padding: 14px 16px;
-		cursor: pointer;
-
-		> * {
-			user-select: none;
-		}
-
-		> input {
-			position: absolute;
-			width: 0;
-			height: 0;
-			opacity: 0;
-			margin: 0;
-		}
-
-		> .button {
-			position: relative;
-			display: inline-block;
-			flex-shrink: 0;
-			margin: 0;
-			width: 34px;
-			height: 22px;
-			background: var(--switchBg);
-			outline: none;
-			border-radius: 999px;
-			transition: all 0.3s;
-			cursor: pointer;
-
-			> .handle {
-				position: absolute;
-				top: 0;
-				left: 3px;
-				bottom: 0;
-				margin: auto 0;
-				border-radius: 100%;
-				transition: background-color 0.3s, transform 0.3s;
-				width: 16px;
-				height: 16px;
-				background-color: #fff;
-				pointer-events: none;
-			}
-		}
-
-		> .label {
-			margin-left: 12px;
-			display: block;
-			transition: inherit;
-			color: var(--fg);
-
-			> span {
-				display: block;
-				line-height: 20px;
-				transition: inherit;
-			}
-		}
-
-		&.disabled {
-			opacity: 0.6;
-			cursor: not-allowed;
-		}
-
-		&.checked {
-			> .button {
-				background-color: var(--accent);
-
-				> .handle {
-					transform: translateX(12px);
-				}
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/textarea.vue b/packages/client/src/components/debobigego/textarea.vue
deleted file mode 100644
index ca5b35c49..000000000
--- a/packages/client/src/components/debobigego/textarea.vue
+++ /dev/null
@@ -1,161 +0,0 @@
-<template>
-<FormGroup class="_debobigegoItem">
-	<template #label><slot></slot></template>
-	<div class="rivhosbp _debobigegoItem" :class="{ tall, pre }">
-		<div class="input _debobigegoPanel">
-			<textarea ref="input" v-model="v"
-				:class="{ code, _monospace: code }"
-				:required="required"
-				:readonly="readonly"
-				:pattern="pattern"
-				:autocomplete="autocomplete"
-				:spellcheck="!code"
-				@input="onInput"
-				@focus="focused = true"
-				@blur="focused = false"
-			></textarea>
-		</div>
-	</div>
-	<template #caption><slot name="desc"></slot></template>
-
-	<FormButton v-if="manualSave && changed" primary @click="updated"><i class="fas fa-save"></i> {{ $ts.save }}</FormButton>
-</FormGroup>
-</template>
-
-<script lang="ts">
-import { defineComponent, ref, toRefs, watch } from 'vue';
-import './debobigego.scss';
-import FormButton from './button.vue';
-import FormGroup from './group.vue';
-
-export default defineComponent({
-	components: {
-		FormGroup,
-		FormButton,
-	},
-	props: {
-		modelValue: {
-			required: false
-		},
-		required: {
-			type: Boolean,
-			required: false
-		},
-		readonly: {
-			type: Boolean,
-			required: false
-		},
-		pattern: {
-			type: String,
-			required: false
-		},
-		autocomplete: {
-			type: String,
-			required: false
-		},
-		code: {
-			type: Boolean,
-			required: false
-		},
-		tall: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-		pre: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-		manualSave: {
-			type: Boolean,
-			required: false,
-			default: false
-		},
-	},
-	setup(props, context) {
-		const { modelValue } = toRefs(props);
-		const v = ref(modelValue.value);
-		const changed = ref(false);
-		const inputEl = ref(null);
-		const focus = () => inputEl.value.focus();
-		const onInput = (ev) => {
-			changed.value = true;
-			context.emit('change', ev);
-		};
-
-		const updated = () => {
-			changed.value = false;
-			context.emit('update:modelValue', v.value);
-		};
-
-		watch(modelValue.value, newValue => {
-			v.value = newValue;
-		});
-
-		watch(v, newValue => {
-			if (!props.manualSave) {
-				updated();
-			}
-		});
-		
-		return {
-			v,
-			updated,
-			changed,
-			focus,
-			onInput,
-		};
-	}
-});
-</script>
-
-<style lang="scss" scoped>
-.rivhosbp {
-	position: relative;
-
-	> .input {
-		position: relative;
-	
-		> textarea {
-			display: block;
-			width: 100%;
-			min-width: 100%;
-			max-width: 100%;
-			min-height: 130px;
-			margin: 0;
-			padding: 16px;
-			box-sizing: border-box;
-			font: inherit;
-			font-weight: normal;
-			font-size: 1em;
-			background: transparent;
-			border: none;
-			border-radius: 0;
-			outline: none;
-			box-shadow: none;
-			color: var(--fg);
-
-			&.code {
-				tab-size: 2;
-			}
-		}
-	}
-
-	&.tall {
-		> .input {
-			> textarea {
-				min-height: 200px;
-			}
-		}
-	}
-
-	&.pre {
-		> .input {
-			> textarea {
-				white-space: pre;
-			}
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/debobigego/tuple.vue b/packages/client/src/components/debobigego/tuple.vue
deleted file mode 100644
index 1d2a6cb55..000000000
--- a/packages/client/src/components/debobigego/tuple.vue
+++ /dev/null
@@ -1,36 +0,0 @@
-<template>
-<div v-size="{ max: [500] }" class="wthhikgt _debobigegoItem">
-	<slot></slot>
-</div>
-</template>
-
-<script lang="ts">
-import { defineComponent } from 'vue';
-
-export default defineComponent({
-});
-</script>
-
-<style lang="scss" scoped>
-.wthhikgt {
-	position: relative;
-	display: flex;
-
-	> ::v-deep(*) {
-		flex: 1;
-		margin: 0;
-
-		&:not(:last-child) {
-			margin-right: 16px;
-		}
-	}
-
-	&.max-width_500px {
-		display: block;
-
-		> ::v-deep(*) {
-			margin: inherit;
-		}
-	}
-}
-</style>
diff --git a/packages/client/src/components/form/folder.vue b/packages/client/src/components/form/folder.vue
index fe1220201..571afe50c 100644
--- a/packages/client/src/components/form/folder.vue
+++ b/packages/client/src/components/form/folder.vue
@@ -20,8 +20,14 @@
 </template>
 
 <script lang="ts" setup>
-let opened = $ref(false);
-let openedAtLeastOnce = $ref(false);
+const props = withDefaults(defineProps<{
+	defaultOpen: boolean;
+}>(), {
+  defaultOpen: false,
+})
+
+let opened = $ref(props.defaultOpen);
+let openedAtLeastOnce = $ref(props.defaultOpen);
 
 const toggle = () => {
 	opened = !opened;
diff --git a/packages/client/src/components/object-view.vue b/packages/client/src/components/object-view.vue
new file mode 100644
index 000000000..4334917e6
--- /dev/null
+++ b/packages/client/src/components/object-view.vue
@@ -0,0 +1,29 @@
+<template>
+<div class="zhyxdalp">
+
+</div>
+</template>
+
+<script lang="ts">
+import { computed, defineComponent } from 'vue';
+import number from '@/filters/number';
+
+export default defineComponent({
+	props: {
+		value: {
+			type: Object,
+			required: true,
+		},
+	},
+
+	setup(props) {
+
+	}
+});
+</script>
+
+<style lang="scss" scoped>
+.zhyxdalp {
+
+}
+</style>
diff --git a/packages/client/src/pages/admin/database.vue b/packages/client/src/pages/admin/database.vue
index fc9a3e969..c1088afd7 100644
--- a/packages/client/src/pages/admin/database.vue
+++ b/packages/client/src/pages/admin/database.vue
@@ -1,5 +1,5 @@
 <template>
-<MkSpacer :content-max="700" :margin-min="16" :margin-max="32">
+<MkSpacer :content-max="800" :margin-min="16" :margin-max="32">
 	<FormSuspense v-slot="{ result: database }" :p="databasePromiseFactory">
 		<MkKeyValue v-for="table in database" :key="table[0]" oneline style="margin: 1em 0;">
 			<template #key>{{ table[0] }}</template>
diff --git a/packages/client/src/pages/gallery/edit.vue b/packages/client/src/pages/gallery/edit.vue
index caca6aed4..d317da038 100644
--- a/packages/client/src/pages/gallery/edit.vue
+++ b/packages/client/src/pages/gallery/edit.vue
@@ -1,12 +1,12 @@
 <template>
-<FormBase>
+<div>
 	<FormSuspense :p="init">
 		<FormInput v-model="title">
-			<span>{{ $ts.title }}</span>
+			<template #label>{{ $ts.title }}</template>
 		</FormInput>
 
 		<FormTextarea v-model="description" :max="500">
-			<span>{{ $ts.description }}</span>
+			<template #label>{{ $ts.description }}</template>
 		</FormTextarea>
 
 		<FormGroup>
@@ -24,19 +24,17 @@
 
 		<FormButton v-if="postId" danger @click="del"><i class="fas fa-trash-alt"></i> {{ $ts.delete }}</FormButton>
 	</FormSuspense>
-</FormBase>
+</div>
 </template>
 
 <script lang="ts">
 import { computed, defineComponent } from 'vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormInput from '@/components/debobigego/input.vue';
-import FormTextarea from '@/components/debobigego/textarea.vue';
-import FormSwitch from '@/components/debobigego/switch.vue';
-import FormTuple from '@/components/debobigego/tuple.vue';
-import FormBase from '@/components/debobigego/base.vue';
-import FormGroup from '@/components/debobigego/group.vue';
-import FormSuspense from '@/components/debobigego/suspense.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormInput from '@/components/form/input.vue';
+import FormTextarea from '@/components/form/textarea.vue';
+import FormSwitch from '@/components/form/switch.vue';
+import FormGroup from '@/components/form/group.vue';
+import FormSuspense from '@/components/form/suspense.vue';
 import { selectFiles } from '@/scripts/select-file';
 import * as os from '@/os';
 import * as symbols from '@/symbols';
@@ -47,7 +45,6 @@ export default defineComponent({
 		FormInput,
 		FormTextarea,
 		FormSwitch,
-		FormBase,
 		FormGroup,
 		FormSuspense,
 	},
diff --git a/packages/client/src/pages/instance-info.vue b/packages/client/src/pages/instance-info.vue
index d6d72f660..475107ab6 100644
--- a/packages/client/src/pages/instance-info.vue
+++ b/packages/client/src/pages/instance-info.vue
@@ -89,9 +89,8 @@
 			</div>
 		</FormSection>
 
-		<FormObjectView tall :value="instance">
-			<span>Raw</span>
-		</FormObjectView>
+		<MkObjectView tall :value="instance">
+		</MkObjectView>
 
 		<FormSection>
 			<template #label>Well-known resources</template>
@@ -108,7 +107,7 @@
 <script lang="ts">
 import { defineAsyncComponent, defineComponent } from 'vue';
 import MkChart from '@/components/chart.vue';
-import FormObjectView from '@/components/debobigego/object-view.vue';
+import MkObjectView from '@/components/object-view.vue';
 import FormTextarea from '@/components/form/textarea.vue';
 import FormLink from '@/components/form/link.vue';
 import MkLink from '@/components/link.vue';
@@ -125,7 +124,7 @@ import * as symbols from '@/symbols';
 export default defineComponent({
 	components: {
 		FormTextarea,
-		FormObjectView,
+		MkObjectView,
 		FormButton,
 		FormLink,
 		FormSection,
diff --git a/packages/client/src/pages/theme-editor.vue b/packages/client/src/pages/theme-editor.vue
index f02365342..c4917e227 100644
--- a/packages/client/src/pages/theme-editor.vue
+++ b/packages/client/src/pages/theme-editor.vue
@@ -1,61 +1,67 @@
 <template>
-<FormBase class="cwepdizn">
-	<div class="_debobigegoItem colorPicker">
-		<div class="_debobigegoLabel">{{ $ts.backgroundColor }}</div>
-		<div class="_debobigegoPanel colors">
-			<div class="row">
-				<button v-for="color in bgColors.filter(x => x.kind === 'light')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)">
-					<div class="preview" :style="{ background: color.forPreview }"></div>
-				</button>
+<MkSpacer :content-max="800" :margin-min="16" :margin-max="32">
+	<div class="cwepdizn _formRoot">
+		<FormFolder :default-open="true" class="_formBlock">
+			<template #label>{{ $ts.backgroundColor }}</template>
+			<div class="cwepdizn-colors">
+				<div class="row">
+					<button v-for="color in bgColors.filter(x => x.kind === 'light')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)">
+						<div class="preview" :style="{ background: color.forPreview }"></div>
+					</button>
+				</div>
+				<div class="row">
+					<button v-for="color in bgColors.filter(x => x.kind === 'dark')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)">
+						<div class="preview" :style="{ background: color.forPreview }"></div>
+					</button>
+				</div>
 			</div>
-			<div class="row">
-				<button v-for="color in bgColors.filter(x => x.kind === 'dark')" :key="color.color" class="color _button" :class="{ active: theme.props.bg === color.color }" @click="setBgColor(color)">
-					<div class="preview" :style="{ background: color.forPreview }"></div>
-				</button>
-			</div>
-		</div>
-	</div>
-	<div class="_debobigegoItem colorPicker">
-		<div class="_debobigegoLabel">{{ $ts.accentColor }}</div>
-		<div class="_debobigegoPanel colors">
-			<div class="row">
-				<button v-for="color in accentColors" :key="color" class="color rounded _button" :class="{ active: theme.props.accent === color }" @click="setAccentColor(color)">
-					<div class="preview" :style="{ background: color }"></div>
-				</button>
-			</div>
-		</div>
-	</div>
-	<div class="_debobigegoItem colorPicker">
-		<div class="_debobigegoLabel">{{ $ts.textColor }}</div>
-		<div class="_debobigegoPanel colors">
-			<div class="row">
-				<button v-for="color in fgColors" :key="color" class="color char _button" :class="{ active: (theme.props.fg === color.forLight) || (theme.props.fg === color.forDark) }" @click="setFgColor(color)">
-					<div class="preview" :style="{ color: color.forPreview ? color.forPreview : theme.base === 'light' ? '#5f5f5f' : '#dadada' }">A</div>
-				</button>
-			</div>
-		</div>
-	</div>
+		</FormFolder>
 
-	<FormGroup v-if="codeEnabled">
-		<FormTextarea v-model="themeCode" tall>
-			<span>{{ $ts._theme.code }}</span>
-		</FormTextarea>
-		<FormButton primary @click="applyThemeCode">{{ $ts.apply }}</FormButton>
-	</FormGroup>
-	<FormButton v-else @click="codeEnabled = true"><i class="fas fa-code"></i> {{ $ts.editCode }}</FormButton>
+		<FormFolder :default-open="true" class="_formBlock">
+			<template #label>{{ $ts.accentColor }}</template>
+			<div class="cwepdizn-colors">
+				<div class="row">
+					<button v-for="color in accentColors" :key="color" class="color rounded _button" :class="{ active: theme.props.accent === color }" @click="setAccentColor(color)">
+						<div class="preview" :style="{ background: color }"></div>
+					</button>
+				</div>
+			</div>
+		</FormFolder>
 
-	<FormGroup v-if="descriptionEnabled">
-		<FormTextarea v-model="description">
-			<span>{{ $ts._theme.description }}</span>
-		</FormTextarea>
-	</FormGroup>
-	<FormButton v-else @click="descriptionEnabled = true">{{ $ts.addDescription }}</FormButton>
+		<FormFolder :default-open="true" class="_formBlock">
+			<template #label>{{ $ts.textColor }}</template>
+			<div class="cwepdizn-colors">
+				<div class="row">
+					<button v-for="color in fgColors" :key="color" class="color char _button" :class="{ active: (theme.props.fg === color.forLight) || (theme.props.fg === color.forDark) }" @click="setFgColor(color)">
+						<div class="preview" :style="{ color: color.forPreview ? color.forPreview : theme.base === 'light' ? '#5f5f5f' : '#dadada' }">A</div>
+					</button>
+				</div>
+			</div>
+		</FormFolder>
 
-	<FormGroup>
-		<FormButton @click="showPreview"><i class="fas fa-eye"></i> {{ $ts.preview }}</FormButton>
-		<FormButton primary @click="saveAs"><i class="fas fa-save"></i> {{ $ts.saveAs }}</FormButton>
-	</FormGroup>
-</FormBase>
+		<FormFolder :default-open="false" class="_formBlock">
+			<template #icon><i class="fas fa-code"></i></template>
+			<template #label>{{ $ts.editCode }}</template>
+
+			<div class="_formRoot">
+				<FormTextarea v-model="themeCode" tall class="_formBlock">
+					<template #label>{{ $ts._theme.code }}</template>
+				</FormTextarea>
+				<FormButton primary class="_formBlock" @click="applyThemeCode">{{ $ts.apply }}</FormButton>
+			</div>
+		</FormFolder>
+
+		<FormFolder :default-open="false" class="_formBlock">
+			<template #label>{{ $ts.addDescription }}</template>
+
+			<div class="_formRoot">
+				<FormTextarea v-model="description">
+					<template #label>{{ $ts._theme.description }}</template>
+				</FormTextarea>
+			</div>
+		</FormFolder>
+	</div>
+</MkSpacer>
 </template>
 
 <script lang="ts">
@@ -65,12 +71,11 @@ import * as tinycolor from 'tinycolor2';
 import { v4 as uuid} from 'uuid';
 import * as JSON5 from 'json5';
 
-import FormBase from '@/components/debobigego/base.vue';
-import FormButton from '@/components/debobigego/button.vue';
-import FormTextarea from '@/components/debobigego/textarea.vue';
-import FormGroup from '@/components/debobigego/group.vue';
+import FormButton from '@/components/ui/button.vue';
+import FormTextarea from '@/components/form/textarea.vue';
+import FormFolder from '@/components/form/folder.vue';
 
-import { Theme, applyTheme, validateTheme, darkTheme, lightTheme } from '@/scripts/theme';
+import { Theme, applyTheme, darkTheme, lightTheme } from '@/scripts/theme';
 import { host } from '@/config';
 import * as os from '@/os';
 import { ColdDeviceStorage } from '@/store';
@@ -79,10 +84,9 @@ import * as symbols from '@/symbols';
 
 export default defineComponent({
 	components: {
-		FormBase,
 		FormButton,
 		FormTextarea,
-		FormGroup,
+		FormFolder,
 	},
 
 	async beforeRouteLeave(to, from) {
@@ -96,13 +100,23 @@ export default defineComponent({
 			[symbols.PAGE_INFO]: {
 				title: this.$ts.themeEditor,
 				icon: 'fas fa-palette',
+				bg: 'var(--bg)',
+				actions: [{
+					asFullButton: true,
+					icon: 'fas fa-eye',
+					text: this.$ts.preview,
+					handler: this.showPreview,
+				}, {
+					asFullButton: true,
+					icon: 'fas fa-check',
+					text: this.$ts.saveAs,
+					handler: this.saveAs,
+				}],
 			},
 			theme: {
 				base: 'light',
 				props: lightTheme.props
 			} as Theme,
-			codeEnabled: false,
-			descriptionEnabled: false,
 			description: null,
 			themeCode: null,
 			bgColors: [
@@ -244,57 +258,51 @@ export default defineComponent({
 
 <style lang="scss" scoped>
 .cwepdizn {
-	max-width: 800px;
-	margin: 0 auto;
+	::v-deep(.cwepdizn-colors) {
+		text-align: center;
 
-	> .colorPicker {
-		> .colors {
-			padding: 32px;
-			text-align: center;
+		> .row {
+			> .color {
+				display: inline-block;
+				position: relative;
+				width: 64px;
+				height: 64px;
+				border-radius: 8px;
 
-			> .row {
-				> .color {
-					display: inline-block;
-					position: relative;
-					width: 64px;
-					height: 64px;
-					border-radius: 8px;
+				> .preview {
+					position: absolute;
+					top: 0;
+					left: 0;
+					right: 0;
+					bottom: 0;
+					margin: auto;
+					width: 42px;
+					height: 42px;
+					border-radius: 4px;
+					box-shadow: 0 2px 4px rgb(0 0 0 / 30%);
+					transition: transform 0.15s ease;
+				}
+
+				&:hover {
+					> .preview {
+						transform: scale(1.1);
+					}
+				}
+
+				&.active {
+					box-shadow: 0 0 0 2px var(--divider) inset;
+				}
+
+				&.rounded {
+					border-radius: 999px;
 
 					> .preview {
-						position: absolute;
-						top: 0;
-						left: 0;
-						right: 0;
-						bottom: 0;
-						margin: auto;
-						width: 42px;
-						height: 42px;
-						border-radius: 4px;
-						box-shadow: 0 2px 4px rgb(0 0 0 / 30%);
-						transition: transform 0.15s ease;
-					}
-
-					&:hover {
-						> .preview {
-							transform: scale(1.1);
-						}
-					}
-
-					&.active {
-						box-shadow: 0 0 0 2px var(--divider) inset;
-					}
-
-					&.rounded {
 						border-radius: 999px;
-
-						> .preview {
-							border-radius: 999px;
-						}
 					}
+				}
 
-					&.char {
-						line-height: 42px;
-					}
+				&.char {
+					line-height: 42px;
 				}
 			}
 		}
diff --git a/packages/client/src/pages/user-info.vue b/packages/client/src/pages/user-info.vue
index e3c10c6df..4bdc82f60 100644
--- a/packages/client/src/pages/user-info.vue
+++ b/packages/client/src/pages/user-info.vue
@@ -53,9 +53,8 @@
 				<FormButton v-if="user.host != null" class="_formBlock" @click="updateRemoteUser"><i class="fas fa-sync"></i> {{ $ts.updateRemoteUser }}</FormButton>
 			</FormSection>
 
-			<FormObjectView tall :value="user">
-				<span>Raw</span>
-			</FormObjectView>
+			<MkObjectView tall :value="user">
+			</MkObjectView>
 		</div>
 	</FormSuspense>
 </MkSpacer>
@@ -63,7 +62,7 @@
 
 <script lang="ts">
 import { computed, defineAsyncComponent, defineComponent } from 'vue';
-import FormObjectView from '@/components/debobigego/object-view.vue';
+import MkObjectView from '@/components/object-view.vue';
 import FormTextarea from '@/components/form/textarea.vue';
 import FormSwitch from '@/components/form/switch.vue';
 import FormLink from '@/components/form/link.vue';
@@ -83,7 +82,7 @@ export default defineComponent({
 		FormSection,
 		FormTextarea,
 		FormSwitch,
-		FormObjectView,
+		MkObjectView,
 		FormButton,
 		FormLink,
 		MkKeyValue,

From 1fc2f2e3e476d3151365e1a0d059034df4859494 Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 22:51:16 +0900
Subject: [PATCH 18/19] tweak ui

---
 packages/client/src/pages/settings/other.vue | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/packages/client/src/pages/settings/other.vue b/packages/client/src/pages/settings/other.vue
index b941c07c6..acc1fb4d3 100644
--- a/packages/client/src/pages/settings/other.vue
+++ b/packages/client/src/pages/settings/other.vue
@@ -1,10 +1,10 @@
 <template>
 <div class="_formRoot">
-	<FormSwitch :value="$i.injectFeaturedNote" @update:modelValue="onChangeInjectFeaturedNote" class="_formBlock">
+	<FormSwitch :value="$i.injectFeaturedNote" class="_formBlock" @update:modelValue="onChangeInjectFeaturedNote">
 		{{ $ts.showFeaturedNotesInTimeline }}
 	</FormSwitch>
 
-	<FormSwitch v-model="reportError" class="_formBlock">{{ $ts.sendErrorReports }}<template #desc>{{ $ts.sendErrorReportsDescription }}</template></FormSwitch>
+	<FormSwitch v-model="reportError" class="_formBlock">{{ $ts.sendErrorReports }}<template #caption>{{ $ts.sendErrorReportsDescription }}</template></FormSwitch>
 
 	<FormLink to="/settings/account-info" class="_formBlock">{{ $ts.accountInfo }}</FormLink>
 

From 5e4877b8a4edaa89d2550e7c03c861536762ea7a Mon Sep 17 00:00:00 2001
From: syuilo <Syuilotan@yahoo.co.jp>
Date: Tue, 4 Jan 2022 23:37:26 +0900
Subject: [PATCH 19/19] tweak ui

---
 .../src/components/object-view.value.vue      | 108 ++++++++++++++++++
 .../client/src/components/object-view.vue     |   8 +-
 packages/client/src/themes/_dark.json5        |   3 +
 packages/client/src/themes/_light.json5       |   3 +
 4 files changed, 120 insertions(+), 2 deletions(-)
 create mode 100644 packages/client/src/components/object-view.value.vue

diff --git a/packages/client/src/components/object-view.value.vue b/packages/client/src/components/object-view.value.vue
new file mode 100644
index 000000000..6f388636d
--- /dev/null
+++ b/packages/client/src/components/object-view.value.vue
@@ -0,0 +1,108 @@
+<template>
+<div class="igpposuu _monospace">
+	<div v-if="value === null" class="null">null</div>
+	<div v-else-if="typeof value === 'boolean'" class="boolean">{{ value ? 'true' : 'false' }}</div>
+	<div v-else-if="typeof value === 'string'" class="string">"{{ value }}"</div>
+	<div v-else-if="typeof value === 'number'" class="number">{{ number(value) }}</div>
+	<div v-else-if="Array.isArray(value)" class="array">
+		<button @click="collapsed_ = !collapsed_">[ {{ collapsed_ ? '+' : '-' }} ]</button>
+		<template v-if="!collapsed_">
+			<div v-for="i in value.length" class="element">
+				{{ i }}: <XValue :value="value[i - 1]" collapsed/>
+			</div>
+		</template>
+	</div>
+	<div v-else-if="typeof value === 'object'" class="object">
+		<button @click="collapsed_ = !collapsed_">{ {{ collapsed_ ? '+' : '-' }} }</button>
+		<template v-if="!collapsed_">
+			<div v-for="k in Object.keys(value)" class="kv">
+				<div class="k">{{ k }}:</div>
+				<div class="v"><XValue :value="value[k]" collapsed/></div>
+			</div>
+		</template>
+	</div>
+</div>
+</template>
+
+<script lang="ts">
+import { computed, defineComponent, ref } from 'vue';
+import number from '@/filters/number';
+
+export default defineComponent({
+	name: 'XValue',
+
+	props: {
+		value: {
+			type: Object,
+			required: true,
+		},
+		collapsed: {
+			type: Boolean,
+			required: false,
+			default: false,
+		},
+	},
+
+	setup(props) {
+		const collapsed_ = ref(props.collapsed);
+
+		return {
+			number,
+			collapsed_,
+		};
+	}
+});
+</script>
+
+<style lang="scss" scoped>
+.igpposuu {
+	display: inline;
+
+	> .null {
+		display: inline;
+		opacity: 0.7;
+	}
+
+	> .boolean {
+		display: inline;
+		color: var(--codeBoolean);
+	}
+
+	> .string {
+		display: inline;
+		color: var(--codeString);
+	}
+
+	> .number {
+		display: inline;
+		color: var(--codeNumber);
+	}
+
+	> .array {
+		display: inline;
+
+		> .element {
+			display: block;
+			padding-left: 16px;
+		}
+	}
+
+	> .object {
+		display: inline;
+
+		> .kv {
+			display: block;
+			padding-left: 16px;
+
+			> .k {
+				display: inline;
+				margin-right: 8px;
+			}
+
+			> .v {
+				display: inline;
+			}
+		}
+	}
+}
+</style>
diff --git a/packages/client/src/components/object-view.vue b/packages/client/src/components/object-view.vue
index 4334917e6..e9db96de8 100644
--- a/packages/client/src/components/object-view.vue
+++ b/packages/client/src/components/object-view.vue
@@ -1,14 +1,18 @@
 <template>
 <div class="zhyxdalp">
-
+	<XValue :value="value" :collapsed="false"/>
 </div>
 </template>
 
 <script lang="ts">
 import { computed, defineComponent } from 'vue';
-import number from '@/filters/number';
+import XValue from './object-view.value.vue';
 
 export default defineComponent({
+	components: {
+		XValue
+	},
+
 	props: {
 		value: {
 			type: Object,
diff --git a/packages/client/src/themes/_dark.json5 b/packages/client/src/themes/_dark.json5
index d8be16f60..1d8778879 100644
--- a/packages/client/src/themes/_dark.json5
+++ b/packages/client/src/themes/_dark.json5
@@ -69,6 +69,9 @@
 		success: '#86b300',
 		error: '#ec4137',
 		warn: '#ecb637',
+		codeString: '#ffb675',
+		codeNumber: '#cfff9e',
+		codeBoolean: '#c59eff',
 		htmlThemeColor: '@bg',
 		X2: ':darken<2<@panel',
 		X3: 'rgba(255, 255, 255, 0.05)',
diff --git a/packages/client/src/themes/_light.json5 b/packages/client/src/themes/_light.json5
index 251aa36c7..359b56068 100644
--- a/packages/client/src/themes/_light.json5
+++ b/packages/client/src/themes/_light.json5
@@ -69,6 +69,9 @@
 		success: '#86b300',
 		error: '#ec4137',
 		warn: '#ecb637',
+		codeString: '#b98710',
+		codeNumber: '#0fbbbb',
+		codeBoolean: '#62b70c',
 		htmlThemeColor: '@bg',
 		X2: ':darken<2<@panel',
 		X3: 'rgba(0, 0, 0, 0.05)',