From 2b8056a8525e1b38536aa0406ba9446a88b365b9 Mon Sep 17 00:00:00 2001
From: Acid Chicken <root@acid-chicken.com>
Date: Sat, 1 Jun 2024 11:16:44 +0900
Subject: [PATCH] fix(backend): use insertOne insteadof insert/findOneOrFail
 combination (#13908)

* fix(backend): use insertOne insteadof insert/findOneOrFail combination

* fix: typo

* fix(backend): inherit mainAlias?

* refactor(backend): use extend

* fix(backend): invalid entityTarget

* fix(backend): fake where

* chore: debug

* chore: debug

* test: log

* fix(backend): column names

* fix(backend): remove dummy from

* revert: log

* fix(backend): position

* fix(backend): automatic aliasing

* chore(backend): alias

* chore(backend): remove from

* fix(backend): type

* fix(backend): avoid pure name

* test(backend): fix type

* chore(backend): use cte

* fix(backend): avoid useless alias

* fix(backend): fix typo

* fix(backend): __disambiguation__

* fix(backend): quote

* chore(backend): t

* chore(backend): accessible

* chore(backend): concrete returning

* fix(backend): quote

* chore: log more

* chore: log metadata

* chore(backend): use raw

* fix(backend): returning column name

* fix(backend): transform

* build(backend): wanna logging

* build(backend): transform empty

* build(backend): build alias

* build(backend): restore name

* chore: return entity

* fix: test case

* test(backend): 204

* chore(backend): log sql

* chore(backend): assert user joined

* fix(backend): typo

* chore(backend): log long sql

* chore(backend): log join

* chore(backend): log join depth null

* chore(backend): joinAttributes

* chore(backend): override createJoinExpression

* chore: join log

* fix(backend): escape

* test(backend): log log

* chore(backend): join gonna success?

* chore(backend): relations

* chore(backend): undefined

* chore(backend): target

* chore(backend): remove log

* chore(backend): log chart update

* chore(backend): log columns

* chore(backend): check hasMetadata

* chore(backend): unshift id when not included

* chore(backend): missing select

* chore(backend): remove debug code
---
 .../backend/src/core/AnnouncementService.ts   |   4 +-
 .../src/core/AvatarDecorationService.ts       |   4 +-
 packages/backend/src/core/ClipService.ts      |   4 +-
 .../backend/src/core/CustomEmojiService.ts    |   4 +-
 packages/backend/src/core/DriveService.ts     |   6 +-
 .../src/core/FederatedInstanceService.ts      |   4 +-
 packages/backend/src/core/RelayService.ts     |   4 +-
 packages/backend/src/core/ReversiService.ts   |   7 +-
 packages/backend/src/core/RoleService.ts      |   8 +-
 .../backend/src/core/UserFollowingService.ts  |   4 +-
 .../core/activitypub/models/ApNoteService.ts  |   4 +-
 packages/backend/src/core/chart/core.ts       |  23 +-
 .../backend/src/models/RepositoryModule.ts    | 136 ++++++------
 packages/backend/src/models/_.ts              | 205 ++++++++++++------
 .../ImportAntennasProcessorService.ts         |   4 +-
 .../ImportUserListsProcessorService.ts        |   4 +-
 .../backend/src/server/api/SigninService.ts   |   4 +-
 .../src/server/api/SignupApiService.ts        |   4 +-
 .../server/api/endpoints/admin/ad/create.ts   |   4 +-
 .../api/endpoints/admin/invite/create.ts      |   4 +-
 .../server/api/endpoints/antennas/create.ts   |   4 +-
 .../src/server/api/endpoints/app/create.ts    |   4 +-
 .../api/endpoints/auth/session/generate.ts    |   4 +-
 .../server/api/endpoints/channels/create.ts   |   4 +-
 .../api/endpoints/drive/folders/create.ts     |   4 +-
 .../src/server/api/endpoints/flash/create.ts  |   4 +-
 .../api/endpoints/gallery/posts/create.ts     |   4 +-
 .../server/api/endpoints/i/webhooks/create.ts |   4 +-
 .../src/server/api/endpoints/invite/create.ts |   4 +-
 .../server/api/endpoints/notes/polls/vote.ts  |   4 +-
 .../src/server/api/endpoints/pages/create.ts  |   4 +-
 .../users/lists/create-from-public.ts         |   4 +-
 .../api/endpoints/users/lists/create.ts       |   4 +-
 .../api/endpoints/users/report-abuse.ts       |   4 +-
 packages/backend/test/e2e/move.ts             |   4 +-
 packages/backend/test/e2e/reversi-game.ts     |  33 +++
 36 files changed, 319 insertions(+), 215 deletions(-)
 create mode 100644 packages/backend/test/e2e/reversi-game.ts

diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts
index 9b60df2cae..40a9db01c0 100644
--- a/packages/backend/src/core/AnnouncementService.ts
+++ b/packages/backend/src/core/AnnouncementService.ts
@@ -67,7 +67,7 @@ export class AnnouncementService {
 
 	@bindThis
 	public async create(values: Partial<MiAnnouncement>, moderator?: MiUser): Promise<{ raw: MiAnnouncement; packed: Packed<'Announcement'> }> {
-		const announcement = await this.announcementsRepository.insert({
+		const announcement = await this.announcementsRepository.insertOne({
 			id: this.idService.gen(),
 			updatedAt: null,
 			title: values.title,
@@ -79,7 +79,7 @@ export class AnnouncementService {
 			silence: values.silence,
 			needConfirmationToRead: values.needConfirmationToRead,
 			userId: values.userId,
-		}).then(x => this.announcementsRepository.findOneByOrFail(x.identifiers[0]));
+		});
 
 		const packed = await this.announcementEntityService.pack(announcement);
 
diff --git a/packages/backend/src/core/AvatarDecorationService.ts b/packages/backend/src/core/AvatarDecorationService.ts
index 21e31d79a4..8b54bbe012 100644
--- a/packages/backend/src/core/AvatarDecorationService.ts
+++ b/packages/backend/src/core/AvatarDecorationService.ts
@@ -55,10 +55,10 @@ export class AvatarDecorationService implements OnApplicationShutdown {
 
 	@bindThis
 	public async create(options: Partial<MiAvatarDecoration>, moderator?: MiUser): Promise<MiAvatarDecoration> {
-		const created = await this.avatarDecorationsRepository.insert({
+		const created = await this.avatarDecorationsRepository.insertOne({
 			id: this.idService.gen(),
 			...options,
-		}).then(x => this.avatarDecorationsRepository.findOneByOrFail(x.identifiers[0]));
+		});
 
 		this.globalEventService.publishInternalEvent('avatarDecorationCreated', created);
 
diff --git a/packages/backend/src/core/ClipService.ts b/packages/backend/src/core/ClipService.ts
index bb8be26ce6..9fd1ebad87 100644
--- a/packages/backend/src/core/ClipService.ts
+++ b/packages/backend/src/core/ClipService.ts
@@ -45,13 +45,13 @@ export class ClipService {
 			throw new ClipService.TooManyClipsError();
 		}
 
-		const clip = await this.clipsRepository.insert({
+		const clip = await this.clipsRepository.insertOne({
 			id: this.idService.gen(),
 			userId: me.id,
 			name: name,
 			isPublic: isPublic,
 			description: description,
-		}).then(x => this.clipsRepository.findOneByOrFail(x.identifiers[0]));
+		});
 
 		return clip;
 	}
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index b1feca7fb4..7e11b9cdca 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -68,7 +68,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
 		localOnly: boolean;
 		roleIdsThatCanBeUsedThisEmojiAsReaction: MiRole['id'][];
 	}, moderator?: MiUser): Promise<MiEmoji> {
-		const emoji = await this.emojisRepository.insert({
+		const emoji = await this.emojisRepository.insertOne({
 			id: this.idService.gen(),
 			updatedAt: new Date(),
 			name: data.name,
@@ -82,7 +82,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
 			isSensitive: data.isSensitive,
 			localOnly: data.localOnly,
 			roleIdsThatCanBeUsedThisEmojiAsReaction: data.roleIdsThatCanBeUsedThisEmojiAsReaction,
-		}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
+		});
 
 		if (data.host == null) {
 			this.localEmojisCache.refresh();
diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts
index 26cf532c70..37c5d1adf7 100644
--- a/packages/backend/src/core/DriveService.ts
+++ b/packages/backend/src/core/DriveService.ts
@@ -220,7 +220,7 @@ export class DriveService {
 			file.size = size;
 			file.storedInternal = false;
 
-			return await this.driveFilesRepository.insert(file).then(x => this.driveFilesRepository.findOneByOrFail(x.identifiers[0]));
+			return await this.driveFilesRepository.insertOne(file);
 		} else { // use internal storage
 			const accessKey = randomUUID();
 			const thumbnailAccessKey = 'thumbnail-' + randomUUID();
@@ -254,7 +254,7 @@ export class DriveService {
 			file.md5 = hash;
 			file.size = size;
 
-			return await this.driveFilesRepository.insert(file).then(x => this.driveFilesRepository.findOneByOrFail(x.identifiers[0]));
+			return await this.driveFilesRepository.insertOne(file);
 		}
 	}
 
@@ -615,7 +615,7 @@ export class DriveService {
 				file.type = info.type.mime;
 				file.storedInternal = false;
 
-				file = await this.driveFilesRepository.insert(file).then(x => this.driveFilesRepository.findOneByOrFail(x.identifiers[0]));
+				file = await this.driveFilesRepository.insertOne(file);
 			} catch (err) {
 			// duplicate key error (when already registered)
 				if (isDuplicateKeyValueError(err)) {
diff --git a/packages/backend/src/core/FederatedInstanceService.ts b/packages/backend/src/core/FederatedInstanceService.ts
index 66db2067d9..6799f2c5bb 100644
--- a/packages/backend/src/core/FederatedInstanceService.ts
+++ b/packages/backend/src/core/FederatedInstanceService.ts
@@ -55,11 +55,11 @@ export class FederatedInstanceService implements OnApplicationShutdown {
 		const index = await this.instancesRepository.findOneBy({ host });
 
 		if (index == null) {
-			const i = await this.instancesRepository.insert({
+			const i = await this.instancesRepository.insertOne({
 				id: this.idService.gen(),
 				host,
 				firstRetrievedAt: new Date(),
-			}).then(x => this.instancesRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			this.federatedInstanceCache.set(host, i);
 			return i;
diff --git a/packages/backend/src/core/RelayService.ts b/packages/backend/src/core/RelayService.ts
index e9dc9b57af..8dd3d64f5b 100644
--- a/packages/backend/src/core/RelayService.ts
+++ b/packages/backend/src/core/RelayService.ts
@@ -53,11 +53,11 @@ export class RelayService {
 
 	@bindThis
 	public async addRelay(inbox: string): Promise<MiRelay> {
-		const relay = await this.relaysRepository.insert({
+		const relay = await this.relaysRepository.insertOne({
 			id: this.idService.gen(),
 			inbox,
 			status: 'requesting',
-		}).then(x => this.relaysRepository.findOneByOrFail(x.identifiers[0]));
+		});
 
 		const relayActor = await this.getRelayActor();
 		const follow = await this.apRendererService.renderFollowRelay(relay, relayActor);
diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts
index 439bc08845..7f939b99c7 100644
--- a/packages/backend/src/core/ReversiService.ts
+++ b/packages/backend/src/core/ReversiService.ts
@@ -281,7 +281,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 
 	@bindThis
 	private async matched(parentId: MiUser['id'], childId: MiUser['id'], options: { noIrregularRules: boolean; }): Promise<MiReversiGame> {
-		const game = await this.reversiGamesRepository.insert({
+		const game = await this.reversiGamesRepository.insertOne({
 			id: this.idService.gen(),
 			user1Id: parentId,
 			user2Id: childId,
@@ -294,10 +294,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 			bw: 'random',
 			isLlotheo: false,
 			noIrregularRules: options.noIrregularRules,
-		}).then(x => this.reversiGamesRepository.findOneOrFail({
-			where: { id: x.identifiers[0].id },
-			relations: ['user1', 'user2'],
-		}));
+		}, { relations: ['user1', 'user2'] });
 		this.cacheGame(game);
 
 		const packed = await this.reversiGameEntityService.packDetail(game);
diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts
index 70c537f9ab..d6eea70297 100644
--- a/packages/backend/src/core/RoleService.ts
+++ b/packages/backend/src/core/RoleService.ts
@@ -471,12 +471,12 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
 			}
 		}
 
-		const created = await this.roleAssignmentsRepository.insert({
+		const created = await this.roleAssignmentsRepository.insertOne({
 			id: this.idService.gen(now),
 			expiresAt: expiresAt,
 			roleId: roleId,
 			userId: userId,
-		}).then(x => this.roleAssignmentsRepository.findOneByOrFail(x.identifiers[0]));
+		});
 
 		this.rolesRepository.update(roleId, {
 			lastUsedAt: new Date(),
@@ -558,7 +558,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
 	@bindThis
 	public async create(values: Partial<MiRole>, moderator?: MiUser): Promise<MiRole> {
 		const date = new Date();
-		const created = await this.rolesRepository.insert({
+		const created = await this.rolesRepository.insertOne({
 			id: this.idService.gen(date.getTime()),
 			updatedAt: date,
 			lastUsedAt: date,
@@ -576,7 +576,7 @@ export class RoleService implements OnApplicationShutdown, OnModuleInit {
 			canEditMembersByModerator: values.canEditMembersByModerator,
 			displayOrder: values.displayOrder,
 			policies: values.policies,
-		}).then(x => this.rolesRepository.findOneByOrFail(x.identifiers[0]));
+		});
 
 		this.globalEventService.publishInternalEvent('roleCreated', created);
 
diff --git a/packages/backend/src/core/UserFollowingService.ts b/packages/backend/src/core/UserFollowingService.ts
index deeecdeb1f..406ea04031 100644
--- a/packages/backend/src/core/UserFollowingService.ts
+++ b/packages/backend/src/core/UserFollowingService.ts
@@ -517,7 +517,7 @@ export class UserFollowingService implements OnModuleInit {
 			followerId: follower.id,
 		});
 
-		const followRequest = await this.followRequestsRepository.insert({
+		const followRequest = await this.followRequestsRepository.insertOne({
 			id: this.idService.gen(),
 			followerId: follower.id,
 			followeeId: followee.id,
@@ -531,7 +531,7 @@ export class UserFollowingService implements OnModuleInit {
 			followeeHost: followee.host,
 			followeeInbox: this.userEntityService.isRemoteUser(followee) ? followee.inbox : undefined,
 			followeeSharedInbox: this.userEntityService.isRemoteUser(followee) ? followee.sharedInbox : undefined,
-		}).then(x => this.followRequestsRepository.findOneByOrFail(x.identifiers[0]));
+		});
 
 		// Publish receiveRequest event
 		if (this.userEntityService.isLocalUser(followee)) {
diff --git a/packages/backend/src/core/activitypub/models/ApNoteService.ts b/packages/backend/src/core/activitypub/models/ApNoteService.ts
index e6dff067f3..c6e6b3a1e8 100644
--- a/packages/backend/src/core/activitypub/models/ApNoteService.ts
+++ b/packages/backend/src/core/activitypub/models/ApNoteService.ts
@@ -407,7 +407,7 @@ export class ApNoteService {
 
 			this.logger.info(`register emoji host=${host}, name=${name}`);
 
-			return await this.emojisRepository.insert({
+			return await this.emojisRepository.insertOne({
 				id: this.idService.gen(),
 				host,
 				name,
@@ -416,7 +416,7 @@ export class ApNoteService {
 				publicUrl: tag.icon.url,
 				updatedAt: new Date(),
 				aliases: [],
-			}).then(x => this.emojisRepository.findOneByOrFail(x.identifiers[0]));
+			});
 		}));
 	}
 }
diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts
index f10e30ef10..af5485a46e 100644
--- a/packages/backend/src/core/chart/core.ts
+++ b/packages/backend/src/core/chart/core.ts
@@ -14,7 +14,8 @@ import { EntitySchema, LessThan, Between } from 'typeorm';
 import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/misc/prelude/time.js';
 import type Logger from '@/logger.js';
 import { bindThis } from '@/decorators.js';
-import type { Repository, DataSource } from 'typeorm';
+import { MiRepository, miRepository } from '@/models/_.js';
+import type { DataSource, Repository } from 'typeorm';
 
 const COLUMN_PREFIX = '___' as const;
 const UNIQUE_TEMP_COLUMN_PREFIX = 'unique_temp___' as const;
@@ -145,10 +146,10 @@ export default abstract class Chart<T extends Schema> {
 		group: string | null;
 	}[] = [];
 	// ↓にしたいけどfindOneとかで型エラーになる
-	//private repositoryForHour: Repository<RawRecord<T>>;
-	//private repositoryForDay: Repository<RawRecord<T>>;
-	private repositoryForHour: Repository<{ id: number; group?: string | null; date: number; }>;
-	private repositoryForDay: Repository<{ id: number; group?: string | null; date: number; }>;
+	//private repositoryForHour: Repository<RawRecord<T>> & MiRepository<RawRecord<T>>;
+	//private repositoryForDay: Repository<RawRecord<T>> & MiRepository<RawRecord<T>>;
+	private repositoryForHour: Repository<{ id: number; group?: string | null; date: number; }> & MiRepository<{ id: number; group?: string | null; date: number; }>;
+	private repositoryForDay: Repository<{ id: number; group?: string | null; date: number; }> & MiRepository<{ id: number; group?: string | null; date: number; }>;
 
 	/**
 	 * 1日に一回程度実行されれば良いような計算処理を入れる(主にCASCADE削除などアプリケーション側で感知できない変動によるズレの修正用)
@@ -211,6 +212,10 @@ export default abstract class Chart<T extends Schema> {
 	} {
 		const createEntity = (span: 'hour' | 'day'): EntitySchema => new EntitySchema({
 			name:
+				span === 'hour' ? `ChartX${name}` :
+				span === 'day' ? `ChartDayX${name}` :
+				new Error('not happen') as never,
+			tableName:
 				span === 'hour' ? `__chart__${camelToSnake(name)}` :
 				span === 'day' ? `__chart_day__${camelToSnake(name)}` :
 				new Error('not happen') as never,
@@ -271,8 +276,8 @@ export default abstract class Chart<T extends Schema> {
 		this.logger = logger;
 
 		const { hour, day } = Chart.schemaToEntity(name, schema, grouped);
-		this.repositoryForHour = db.getRepository<{ id: number; group?: string | null; date: number; }>(hour);
-		this.repositoryForDay = db.getRepository<{ id: number; group?: string | null; date: number; }>(day);
+		this.repositoryForHour = db.getRepository<{ id: number; group?: string | null; date: number; }>(hour).extend(miRepository as MiRepository<{ id: number; group?: string | null; date: number; }>);
+		this.repositoryForDay = db.getRepository<{ id: number; group?: string | null; date: number; }>(day).extend(miRepository as MiRepository<{ id: number; group?: string | null; date: number; }>);
 	}
 
 	@bindThis
@@ -387,11 +392,11 @@ export default abstract class Chart<T extends Schema> {
 			}
 
 			// 新規ログ挿入
-			log = await repository.insert({
+			log = await repository.insertOne({
 				date: date,
 				...(group ? { group: group } : {}),
 				...columns,
-			}).then(x => repository.findOneByOrFail(x.identifiers[0])) as RawRecord<T>;
+			}) as RawRecord<T>;
 
 			this.logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): New commit created`);
 
diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts
index bd447570dd..d3062d6b36 100644
--- a/packages/backend/src/models/RepositoryModule.ts
+++ b/packages/backend/src/models/RepositoryModule.ts
@@ -5,409 +5,409 @@
 
 import { Module } from '@nestjs/common';
 import { DI } from '@/di-symbols.js';
-import { MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook, MiBubbleGameRecord, MiReversiGame } from './_.js';
+import { MiRepository, MiAbuseUserReport, MiAccessToken, MiAd, MiAnnouncement, MiAnnouncementRead, MiAntenna, MiApp, MiAuthSession, MiAvatarDecoration, MiBlocking, MiChannel, MiChannelFavorite, MiChannelFollowing, MiClip, MiClipFavorite, MiClipNote, MiDriveFile, MiDriveFolder, MiEmoji, MiFlash, MiFlashLike, MiFollowRequest, MiFollowing, MiGalleryLike, MiGalleryPost, MiHashtag, MiInstance, MiMeta, MiModerationLog, MiMuting, MiNote, MiNoteFavorite, MiNoteReaction, MiNoteThreadMuting, MiNoteUnread, MiPage, MiPageLike, MiPasswordResetRequest, MiPoll, MiPollVote, MiPromoNote, MiPromoRead, MiRegistrationTicket, MiRegistryItem, MiRelay, MiRenoteMuting, MiRetentionAggregation, MiRole, MiRoleAssignment, MiSignin, MiSwSubscription, MiUsedUsername, MiUser, MiUserIp, MiUserKeypair, MiUserList, MiUserListFavorite, MiUserListMembership, MiUserMemo, MiUserNotePining, MiUserPending, MiUserProfile, MiUserPublickey, MiUserSecurityKey, MiWebhook, MiBubbleGameRecord, MiReversiGame, miRepository } from './_.js';
 import type { DataSource } from 'typeorm';
 import type { Provider } from '@nestjs/common';
 
 const $usersRepository: Provider = {
 	provide: DI.usersRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUser),
+	useFactory: (db: DataSource) => db.getRepository(MiUser).extend(miRepository as MiRepository<MiUser>),
 	inject: [DI.db],
 };
 
 const $notesRepository: Provider = {
 	provide: DI.notesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiNote),
+	useFactory: (db: DataSource) => db.getRepository(MiNote).extend(miRepository as MiRepository<MiNote>),
 	inject: [DI.db],
 };
 
 const $announcementsRepository: Provider = {
 	provide: DI.announcementsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiAnnouncement),
+	useFactory: (db: DataSource) => db.getRepository(MiAnnouncement).extend(miRepository as MiRepository<MiAnnouncement>),
 	inject: [DI.db],
 };
 
 const $announcementReadsRepository: Provider = {
 	provide: DI.announcementReadsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiAnnouncementRead),
+	useFactory: (db: DataSource) => db.getRepository(MiAnnouncementRead).extend(miRepository as MiRepository<MiAnnouncementRead>),
 	inject: [DI.db],
 };
 
 const $appsRepository: Provider = {
 	provide: DI.appsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiApp),
+	useFactory: (db: DataSource) => db.getRepository(MiApp).extend(miRepository as MiRepository<MiApp>),
 	inject: [DI.db],
 };
 
 const $avatarDecorationsRepository: Provider = {
 	provide: DI.avatarDecorationsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiAvatarDecoration),
+	useFactory: (db: DataSource) => db.getRepository(MiAvatarDecoration).extend(miRepository as MiRepository<MiAvatarDecoration>),
 	inject: [DI.db],
 };
 
 const $noteFavoritesRepository: Provider = {
 	provide: DI.noteFavoritesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiNoteFavorite),
+	useFactory: (db: DataSource) => db.getRepository(MiNoteFavorite).extend(miRepository as MiRepository<MiNoteFavorite>),
 	inject: [DI.db],
 };
 
 const $noteThreadMutingsRepository: Provider = {
 	provide: DI.noteThreadMutingsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiNoteThreadMuting),
+	useFactory: (db: DataSource) => db.getRepository(MiNoteThreadMuting).extend(miRepository as MiRepository<MiNoteThreadMuting>),
 	inject: [DI.db],
 };
 
 const $noteReactionsRepository: Provider = {
 	provide: DI.noteReactionsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiNoteReaction),
+	useFactory: (db: DataSource) => db.getRepository(MiNoteReaction).extend(miRepository as MiRepository<MiNoteReaction>),
 	inject: [DI.db],
 };
 
 const $noteUnreadsRepository: Provider = {
 	provide: DI.noteUnreadsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiNoteUnread),
+	useFactory: (db: DataSource) => db.getRepository(MiNoteUnread).extend(miRepository as MiRepository<MiNoteUnread>),
 	inject: [DI.db],
 };
 
 const $pollsRepository: Provider = {
 	provide: DI.pollsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiPoll),
+	useFactory: (db: DataSource) => db.getRepository(MiPoll).extend(miRepository as MiRepository<MiPoll>),
 	inject: [DI.db],
 };
 
 const $pollVotesRepository: Provider = {
 	provide: DI.pollVotesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiPollVote),
+	useFactory: (db: DataSource) => db.getRepository(MiPollVote).extend(miRepository as MiRepository<MiPollVote>),
 	inject: [DI.db],
 };
 
 const $userProfilesRepository: Provider = {
 	provide: DI.userProfilesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserProfile),
+	useFactory: (db: DataSource) => db.getRepository(MiUserProfile).extend(miRepository as MiRepository<MiUserProfile>),
 	inject: [DI.db],
 };
 
 const $userKeypairsRepository: Provider = {
 	provide: DI.userKeypairsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserKeypair),
+	useFactory: (db: DataSource) => db.getRepository(MiUserKeypair).extend(miRepository as MiRepository<MiUserKeypair>),
 	inject: [DI.db],
 };
 
 const $userPendingsRepository: Provider = {
 	provide: DI.userPendingsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserPending),
+	useFactory: (db: DataSource) => db.getRepository(MiUserPending).extend(miRepository as MiRepository<MiUserPending>),
 	inject: [DI.db],
 };
 
 const $userSecurityKeysRepository: Provider = {
 	provide: DI.userSecurityKeysRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserSecurityKey),
+	useFactory: (db: DataSource) => db.getRepository(MiUserSecurityKey).extend(miRepository as MiRepository<MiUserSecurityKey>),
 	inject: [DI.db],
 };
 
 const $userPublickeysRepository: Provider = {
 	provide: DI.userPublickeysRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserPublickey),
+	useFactory: (db: DataSource) => db.getRepository(MiUserPublickey).extend(miRepository as MiRepository<MiUserPublickey>),
 	inject: [DI.db],
 };
 
 const $userListsRepository: Provider = {
 	provide: DI.userListsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserList),
+	useFactory: (db: DataSource) => db.getRepository(MiUserList).extend(miRepository as MiRepository<MiUserList>),
 	inject: [DI.db],
 };
 
 const $userListFavoritesRepository: Provider = {
 	provide: DI.userListFavoritesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserListFavorite),
+	useFactory: (db: DataSource) => db.getRepository(MiUserListFavorite).extend(miRepository as MiRepository<MiUserListFavorite>),
 	inject: [DI.db],
 };
 
 const $userListMembershipsRepository: Provider = {
 	provide: DI.userListMembershipsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserListMembership),
+	useFactory: (db: DataSource) => db.getRepository(MiUserListMembership).extend(miRepository as MiRepository<MiUserListMembership>),
 	inject: [DI.db],
 };
 
 const $userNotePiningsRepository: Provider = {
 	provide: DI.userNotePiningsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserNotePining),
+	useFactory: (db: DataSource) => db.getRepository(MiUserNotePining).extend(miRepository as MiRepository<MiUserNotePining>),
 	inject: [DI.db],
 };
 
 const $userIpsRepository: Provider = {
 	provide: DI.userIpsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserIp),
+	useFactory: (db: DataSource) => db.getRepository(MiUserIp).extend(miRepository as MiRepository<MiUserIp>),
 	inject: [DI.db],
 };
 
 const $usedUsernamesRepository: Provider = {
 	provide: DI.usedUsernamesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUsedUsername),
+	useFactory: (db: DataSource) => db.getRepository(MiUsedUsername).extend(miRepository as MiRepository<MiUsedUsername>),
 	inject: [DI.db],
 };
 
 const $followingsRepository: Provider = {
 	provide: DI.followingsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiFollowing),
+	useFactory: (db: DataSource) => db.getRepository(MiFollowing).extend(miRepository as MiRepository<MiFollowing>),
 	inject: [DI.db],
 };
 
 const $followRequestsRepository: Provider = {
 	provide: DI.followRequestsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiFollowRequest),
+	useFactory: (db: DataSource) => db.getRepository(MiFollowRequest).extend(miRepository as MiRepository<MiFollowRequest>),
 	inject: [DI.db],
 };
 
 const $instancesRepository: Provider = {
 	provide: DI.instancesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiInstance),
+	useFactory: (db: DataSource) => db.getRepository(MiInstance).extend(miRepository as MiRepository<MiInstance>),
 	inject: [DI.db],
 };
 
 const $emojisRepository: Provider = {
 	provide: DI.emojisRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiEmoji),
+	useFactory: (db: DataSource) => db.getRepository(MiEmoji).extend(miRepository as MiRepository<MiEmoji>),
 	inject: [DI.db],
 };
 
 const $driveFilesRepository: Provider = {
 	provide: DI.driveFilesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiDriveFile),
+	useFactory: (db: DataSource) => db.getRepository(MiDriveFile).extend(miRepository as MiRepository<MiDriveFile>),
 	inject: [DI.db],
 };
 
 const $driveFoldersRepository: Provider = {
 	provide: DI.driveFoldersRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiDriveFolder),
+	useFactory: (db: DataSource) => db.getRepository(MiDriveFolder).extend(miRepository as MiRepository<MiDriveFolder>),
 	inject: [DI.db],
 };
 
 const $metasRepository: Provider = {
 	provide: DI.metasRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiMeta),
+	useFactory: (db: DataSource) => db.getRepository(MiMeta).extend(miRepository as MiRepository<MiMeta>),
 	inject: [DI.db],
 };
 
 const $mutingsRepository: Provider = {
 	provide: DI.mutingsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiMuting),
+	useFactory: (db: DataSource) => db.getRepository(MiMuting).extend(miRepository as MiRepository<MiMuting>),
 	inject: [DI.db],
 };
 
 const $renoteMutingsRepository: Provider = {
 	provide: DI.renoteMutingsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiRenoteMuting),
+	useFactory: (db: DataSource) => db.getRepository(MiRenoteMuting).extend(miRepository as MiRepository<MiRenoteMuting>),
 	inject: [DI.db],
 };
 
 const $blockingsRepository: Provider = {
 	provide: DI.blockingsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiBlocking),
+	useFactory: (db: DataSource) => db.getRepository(MiBlocking).extend(miRepository as MiRepository<MiBlocking>),
 	inject: [DI.db],
 };
 
 const $swSubscriptionsRepository: Provider = {
 	provide: DI.swSubscriptionsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiSwSubscription),
+	useFactory: (db: DataSource) => db.getRepository(MiSwSubscription).extend(miRepository as MiRepository<MiSwSubscription>),
 	inject: [DI.db],
 };
 
 const $hashtagsRepository: Provider = {
 	provide: DI.hashtagsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiHashtag),
+	useFactory: (db: DataSource) => db.getRepository(MiHashtag).extend(miRepository as MiRepository<MiHashtag>),
 	inject: [DI.db],
 };
 
 const $abuseUserReportsRepository: Provider = {
 	provide: DI.abuseUserReportsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiAbuseUserReport),
+	useFactory: (db: DataSource) => db.getRepository(MiAbuseUserReport).extend(miRepository as MiRepository<MiAbuseUserReport>),
 	inject: [DI.db],
 };
 
 const $registrationTicketsRepository: Provider = {
 	provide: DI.registrationTicketsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiRegistrationTicket),
+	useFactory: (db: DataSource) => db.getRepository(MiRegistrationTicket).extend(miRepository as MiRepository<MiRegistrationTicket>),
 	inject: [DI.db],
 };
 
 const $authSessionsRepository: Provider = {
 	provide: DI.authSessionsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiAuthSession),
+	useFactory: (db: DataSource) => db.getRepository(MiAuthSession).extend(miRepository as MiRepository<MiAuthSession>),
 	inject: [DI.db],
 };
 
 const $accessTokensRepository: Provider = {
 	provide: DI.accessTokensRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiAccessToken),
+	useFactory: (db: DataSource) => db.getRepository(MiAccessToken).extend(miRepository as MiRepository<MiAccessToken>),
 	inject: [DI.db],
 };
 
 const $signinsRepository: Provider = {
 	provide: DI.signinsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiSignin),
+	useFactory: (db: DataSource) => db.getRepository(MiSignin).extend(miRepository as MiRepository<MiSignin>),
 	inject: [DI.db],
 };
 
 const $pagesRepository: Provider = {
 	provide: DI.pagesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiPage),
+	useFactory: (db: DataSource) => db.getRepository(MiPage).extend(miRepository as MiRepository<MiPage>),
 	inject: [DI.db],
 };
 
 const $pageLikesRepository: Provider = {
 	provide: DI.pageLikesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiPageLike),
+	useFactory: (db: DataSource) => db.getRepository(MiPageLike).extend(miRepository as MiRepository<MiPageLike>),
 	inject: [DI.db],
 };
 
 const $galleryPostsRepository: Provider = {
 	provide: DI.galleryPostsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiGalleryPost),
+	useFactory: (db: DataSource) => db.getRepository(MiGalleryPost).extend(miRepository as MiRepository<MiGalleryPost>),
 	inject: [DI.db],
 };
 
 const $galleryLikesRepository: Provider = {
 	provide: DI.galleryLikesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiGalleryLike),
+	useFactory: (db: DataSource) => db.getRepository(MiGalleryLike).extend(miRepository as MiRepository<MiGalleryLike>),
 	inject: [DI.db],
 };
 
 const $moderationLogsRepository: Provider = {
 	provide: DI.moderationLogsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiModerationLog),
+	useFactory: (db: DataSource) => db.getRepository(MiModerationLog).extend(miRepository as MiRepository<MiModerationLog>),
 	inject: [DI.db],
 };
 
 const $clipsRepository: Provider = {
 	provide: DI.clipsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiClip),
+	useFactory: (db: DataSource) => db.getRepository(MiClip).extend(miRepository as MiRepository<MiClip>),
 	inject: [DI.db],
 };
 
 const $clipNotesRepository: Provider = {
 	provide: DI.clipNotesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiClipNote),
+	useFactory: (db: DataSource) => db.getRepository(MiClipNote).extend(miRepository as MiRepository<MiClipNote>),
 	inject: [DI.db],
 };
 
 const $clipFavoritesRepository: Provider = {
 	provide: DI.clipFavoritesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiClipFavorite),
+	useFactory: (db: DataSource) => db.getRepository(MiClipFavorite).extend(miRepository as MiRepository<MiClipFavorite>),
 	inject: [DI.db],
 };
 
 const $antennasRepository: Provider = {
 	provide: DI.antennasRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiAntenna),
+	useFactory: (db: DataSource) => db.getRepository(MiAntenna).extend(miRepository as MiRepository<MiAntenna>),
 	inject: [DI.db],
 };
 
 const $promoNotesRepository: Provider = {
 	provide: DI.promoNotesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiPromoNote),
+	useFactory: (db: DataSource) => db.getRepository(MiPromoNote).extend(miRepository as MiRepository<MiPromoNote>),
 	inject: [DI.db],
 };
 
 const $promoReadsRepository: Provider = {
 	provide: DI.promoReadsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiPromoRead),
+	useFactory: (db: DataSource) => db.getRepository(MiPromoRead).extend(miRepository as MiRepository<MiPromoRead>),
 	inject: [DI.db],
 };
 
 const $relaysRepository: Provider = {
 	provide: DI.relaysRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiRelay),
+	useFactory: (db: DataSource) => db.getRepository(MiRelay).extend(miRepository as MiRepository<MiRelay>),
 	inject: [DI.db],
 };
 
 const $channelsRepository: Provider = {
 	provide: DI.channelsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiChannel),
+	useFactory: (db: DataSource) => db.getRepository(MiChannel).extend(miRepository as MiRepository<MiChannel>),
 	inject: [DI.db],
 };
 
 const $channelFollowingsRepository: Provider = {
 	provide: DI.channelFollowingsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiChannelFollowing),
+	useFactory: (db: DataSource) => db.getRepository(MiChannelFollowing).extend(miRepository as MiRepository<MiChannelFollowing>),
 	inject: [DI.db],
 };
 
 const $channelFavoritesRepository: Provider = {
 	provide: DI.channelFavoritesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiChannelFavorite),
+	useFactory: (db: DataSource) => db.getRepository(MiChannelFavorite).extend(miRepository as MiRepository<MiChannelFavorite>),
 	inject: [DI.db],
 };
 
 const $registryItemsRepository: Provider = {
 	provide: DI.registryItemsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiRegistryItem),
+	useFactory: (db: DataSource) => db.getRepository(MiRegistryItem).extend(miRepository as MiRepository<MiRegistryItem>),
 	inject: [DI.db],
 };
 
 const $webhooksRepository: Provider = {
 	provide: DI.webhooksRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiWebhook),
+	useFactory: (db: DataSource) => db.getRepository(MiWebhook).extend(miRepository as MiRepository<MiWebhook>),
 	inject: [DI.db],
 };
 
 const $adsRepository: Provider = {
 	provide: DI.adsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiAd),
+	useFactory: (db: DataSource) => db.getRepository(MiAd).extend(miRepository as MiRepository<MiAd>),
 	inject: [DI.db],
 };
 
 const $passwordResetRequestsRepository: Provider = {
 	provide: DI.passwordResetRequestsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiPasswordResetRequest),
+	useFactory: (db: DataSource) => db.getRepository(MiPasswordResetRequest).extend(miRepository as MiRepository<MiPasswordResetRequest>),
 	inject: [DI.db],
 };
 
 const $retentionAggregationsRepository: Provider = {
 	provide: DI.retentionAggregationsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiRetentionAggregation),
+	useFactory: (db: DataSource) => db.getRepository(MiRetentionAggregation).extend(miRepository as MiRepository<MiRetentionAggregation>),
 	inject: [DI.db],
 };
 
 const $flashsRepository: Provider = {
 	provide: DI.flashsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiFlash),
+	useFactory: (db: DataSource) => db.getRepository(MiFlash).extend(miRepository as MiRepository<MiFlash>),
 	inject: [DI.db],
 };
 
 const $flashLikesRepository: Provider = {
 	provide: DI.flashLikesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiFlashLike),
+	useFactory: (db: DataSource) => db.getRepository(MiFlashLike).extend(miRepository as MiRepository<MiFlashLike>),
 	inject: [DI.db],
 };
 
 const $rolesRepository: Provider = {
 	provide: DI.rolesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiRole),
+	useFactory: (db: DataSource) => db.getRepository(MiRole).extend(miRepository as MiRepository<MiRole>),
 	inject: [DI.db],
 };
 
 const $roleAssignmentsRepository: Provider = {
 	provide: DI.roleAssignmentsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiRoleAssignment),
+	useFactory: (db: DataSource) => db.getRepository(MiRoleAssignment).extend(miRepository as MiRepository<MiRoleAssignment>),
 	inject: [DI.db],
 };
 
 const $userMemosRepository: Provider = {
 	provide: DI.userMemosRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiUserMemo),
+	useFactory: (db: DataSource) => db.getRepository(MiUserMemo).extend(miRepository as MiRepository<MiUserMemo>),
 	inject: [DI.db],
 };
 
 const $bubbleGameRecordsRepository: Provider = {
 	provide: DI.bubbleGameRecordsRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiBubbleGameRecord),
+	useFactory: (db: DataSource) => db.getRepository(MiBubbleGameRecord).extend(miRepository as MiRepository<MiBubbleGameRecord>),
 	inject: [DI.db],
 };
 
 const $reversiGamesRepository: Provider = {
 	provide: DI.reversiGamesRepository,
-	useFactory: (db: DataSource) => db.getRepository(MiReversiGame),
+	useFactory: (db: DataSource) => db.getRepository(MiReversiGame).extend(miRepository as MiRepository<MiReversiGame>),
 	inject: [DI.db],
 };
 
diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts
index 43d42d80dd..2e6a41586e 100644
--- a/packages/backend/src/models/_.ts
+++ b/packages/backend/src/models/_.ts
@@ -3,6 +3,13 @@
  * SPDX-License-Identifier: AGPL-3.0-only
  */
 
+import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository, SelectQueryBuilder, TypeORMError } from 'typeorm';
+import { DriverUtils } from 'typeorm/driver/DriverUtils.js';
+import { RelationCountLoader } from 'typeorm/query-builder/relation-count/RelationCountLoader.js';
+import { RelationIdLoader } from 'typeorm/query-builder/relation-id/RelationIdLoader.js';
+import { RawSqlResultsToEntityTransformer } from 'typeorm/query-builder/transformer/RawSqlResultsToEntityTransformer.js';
+import { ObjectUtils } from 'typeorm/util/ObjectUtils.js';
+import { OrmUtils } from 'typeorm/util/OrmUtils.js';
 import { MiAbuseUserReport } from '@/models/AbuseUserReport.js';
 import { MiAccessToken } from '@/models/AccessToken.js';
 import { MiAd } from '@/models/Ad.js';
@@ -70,8 +77,70 @@ import { MiFlashLike } from '@/models/FlashLike.js';
 import { MiUserListFavorite } from '@/models/UserListFavorite.js';
 import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js';
 import { MiReversiGame } from '@/models/ReversiGame.js';
+import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js';
 
-import type { Repository } from 'typeorm';
+export interface MiRepository<T extends ObjectLiteral> {
+	createTableColumnNames(this: Repository<T> & MiRepository<T>, queryBuilder: InsertQueryBuilder<T>): string[];
+	createTableColumnNamesWithPrimaryKey(this: Repository<T> & MiRepository<T>, queryBuilder: InsertQueryBuilder<T>): string[];
+	insertOne(this: Repository<T> & MiRepository<T>, entity: QueryDeepPartialEntity<T>, findOptions?: Pick<FindOneOptions<T>, 'relations'>): Promise<T>;
+	selectAliasColumnNames(this: Repository<T> & MiRepository<T>, queryBuilder: InsertQueryBuilder<T>, builder: SelectQueryBuilder<T>): void;
+}
+
+export const miRepository = {
+	createTableColumnNames(queryBuilder) {
+		// @ts-expect-error -- protected
+		const insertedColumns = queryBuilder.getInsertedColumns();
+		if (insertedColumns.length) {
+			return insertedColumns.map(column => column.databaseName);
+		}
+		if (!queryBuilder.expressionMap.mainAlias?.hasMetadata && !queryBuilder.expressionMap.insertColumns.length) {
+			// @ts-expect-error -- protected
+			const valueSets = queryBuilder.getValueSets();
+			if (valueSets.length === 1) {
+				return Object.keys(valueSets[0]);
+			}
+		}
+		return queryBuilder.expressionMap.insertColumns;
+	},
+	createTableColumnNamesWithPrimaryKey(queryBuilder) {
+		const columnNames = this.createTableColumnNames(queryBuilder);
+		if (!columnNames.includes('id')) {
+			columnNames.unshift('id');
+		}
+		return columnNames;
+	},
+	async insertOne(entity, findOptions?) {
+		const queryBuilder = this.createQueryBuilder().insert().values(entity);
+		// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+		const mainAlias = queryBuilder.expressionMap.mainAlias!;
+		const name = mainAlias.name;
+		mainAlias.name = 't';
+		const columnNames = this.createTableColumnNamesWithPrimaryKey(queryBuilder);
+		queryBuilder.returning(columnNames.reduce((a, c) => `${a}, ${queryBuilder.escape(c)}`, '').slice(2));
+		const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames });
+		// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+		builder.expressionMap.mainAlias!.tablePath = 'cte';
+		this.selectAliasColumnNames(queryBuilder, builder);
+		if (findOptions) {
+			builder.setFindOptions(findOptions);
+		}
+		const raw = await builder.execute();
+		mainAlias.name = name;
+		const relationId = await new RelationIdLoader(builder.connection, this.queryRunner, builder.expressionMap.relationIdAttributes).load(raw);
+		const relationCount = await new RelationCountLoader(builder.connection, this.queryRunner, builder.expressionMap.relationCountAttributes).load(raw);
+		const result = new RawSqlResultsToEntityTransformer(builder.expressionMap, builder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, mainAlias);
+		return result[0];
+	},
+	selectAliasColumnNames(queryBuilder, builder) {
+		let selectOrAddSelect = (selection: string, selectionAliasName?: string) => {
+			selectOrAddSelect = (selection, selectionAliasName) => builder.addSelect(selection, selectionAliasName);
+			return builder.select(selection, selectionAliasName);
+		};
+		for (const columnName of this.createTableColumnNamesWithPrimaryKey(queryBuilder)) {
+			selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`);
+		}
+	},
+} satisfies MiRepository<ObjectLiteral>;
 
 export {
 	MiAbuseUserReport,
@@ -143,70 +212,70 @@ export {
 	MiReversiGame,
 };
 
-export type AbuseUserReportsRepository = Repository<MiAbuseUserReport>;
-export type AccessTokensRepository = Repository<MiAccessToken>;
-export type AdsRepository = Repository<MiAd>;
-export type AnnouncementsRepository = Repository<MiAnnouncement>;
-export type AnnouncementReadsRepository = Repository<MiAnnouncementRead>;
-export type AntennasRepository = Repository<MiAntenna>;
-export type AppsRepository = Repository<MiApp>;
-export type AvatarDecorationsRepository = Repository<MiAvatarDecoration>;
-export type AuthSessionsRepository = Repository<MiAuthSession>;
-export type BlockingsRepository = Repository<MiBlocking>;
-export type ChannelFollowingsRepository = Repository<MiChannelFollowing>;
-export type ChannelFavoritesRepository = Repository<MiChannelFavorite>;
-export type ClipsRepository = Repository<MiClip>;
-export type ClipNotesRepository = Repository<MiClipNote>;
-export type ClipFavoritesRepository = Repository<MiClipFavorite>;
-export type DriveFilesRepository = Repository<MiDriveFile>;
-export type DriveFoldersRepository = Repository<MiDriveFolder>;
-export type EmojisRepository = Repository<MiEmoji>;
-export type FollowingsRepository = Repository<MiFollowing>;
-export type FollowRequestsRepository = Repository<MiFollowRequest>;
-export type GalleryLikesRepository = Repository<MiGalleryLike>;
-export type GalleryPostsRepository = Repository<MiGalleryPost>;
-export type HashtagsRepository = Repository<MiHashtag>;
-export type InstancesRepository = Repository<MiInstance>;
-export type MetasRepository = Repository<MiMeta>;
-export type ModerationLogsRepository = Repository<MiModerationLog>;
-export type MutingsRepository = Repository<MiMuting>;
-export type RenoteMutingsRepository = Repository<MiRenoteMuting>;
-export type NotesRepository = Repository<MiNote>;
-export type NoteFavoritesRepository = Repository<MiNoteFavorite>;
-export type NoteReactionsRepository = Repository<MiNoteReaction>;
-export type NoteThreadMutingsRepository = Repository<MiNoteThreadMuting>;
-export type NoteUnreadsRepository = Repository<MiNoteUnread>;
-export type PagesRepository = Repository<MiPage>;
-export type PageLikesRepository = Repository<MiPageLike>;
-export type PasswordResetRequestsRepository = Repository<MiPasswordResetRequest>;
-export type PollsRepository = Repository<MiPoll>;
-export type PollVotesRepository = Repository<MiPollVote>;
-export type PromoNotesRepository = Repository<MiPromoNote>;
-export type PromoReadsRepository = Repository<MiPromoRead>;
-export type RegistrationTicketsRepository = Repository<MiRegistrationTicket>;
-export type RegistryItemsRepository = Repository<MiRegistryItem>;
-export type RelaysRepository = Repository<MiRelay>;
-export type SigninsRepository = Repository<MiSignin>;
-export type SwSubscriptionsRepository = Repository<MiSwSubscription>;
-export type UsedUsernamesRepository = Repository<MiUsedUsername>;
-export type UsersRepository = Repository<MiUser>;
-export type UserIpsRepository = Repository<MiUserIp>;
-export type UserKeypairsRepository = Repository<MiUserKeypair>;
-export type UserListsRepository = Repository<MiUserList>;
-export type UserListFavoritesRepository = Repository<MiUserListFavorite>;
-export type UserListMembershipsRepository = Repository<MiUserListMembership>;
-export type UserNotePiningsRepository = Repository<MiUserNotePining>;
-export type UserPendingsRepository = Repository<MiUserPending>;
-export type UserProfilesRepository = Repository<MiUserProfile>;
-export type UserPublickeysRepository = Repository<MiUserPublickey>;
-export type UserSecurityKeysRepository = Repository<MiUserSecurityKey>;
-export type WebhooksRepository = Repository<MiWebhook>;
-export type ChannelsRepository = Repository<MiChannel>;
-export type RetentionAggregationsRepository = Repository<MiRetentionAggregation>;
-export type RolesRepository = Repository<MiRole>;
-export type RoleAssignmentsRepository = Repository<MiRoleAssignment>;
-export type FlashsRepository = Repository<MiFlash>;
-export type FlashLikesRepository = Repository<MiFlashLike>;
-export type UserMemoRepository = Repository<MiUserMemo>;
-export type BubbleGameRecordsRepository = Repository<MiBubbleGameRecord>;
-export type ReversiGamesRepository = Repository<MiReversiGame>;
+export type AbuseUserReportsRepository = Repository<MiAbuseUserReport> & MiRepository<MiAbuseUserReport>;
+export type AccessTokensRepository = Repository<MiAccessToken> & MiRepository<MiAccessToken>;
+export type AdsRepository = Repository<MiAd> & MiRepository<MiAd>;
+export type AnnouncementsRepository = Repository<MiAnnouncement> & MiRepository<MiAnnouncement>;
+export type AnnouncementReadsRepository = Repository<MiAnnouncementRead> & MiRepository<MiAnnouncementRead>;
+export type AntennasRepository = Repository<MiAntenna> & MiRepository<MiAntenna>;
+export type AppsRepository = Repository<MiApp> & MiRepository<MiApp>;
+export type AvatarDecorationsRepository = Repository<MiAvatarDecoration> & MiRepository<MiAvatarDecoration>;
+export type AuthSessionsRepository = Repository<MiAuthSession> & MiRepository<MiAuthSession>;
+export type BlockingsRepository = Repository<MiBlocking> & MiRepository<MiBlocking>;
+export type ChannelFollowingsRepository = Repository<MiChannelFollowing> & MiRepository<MiChannelFollowing>;
+export type ChannelFavoritesRepository = Repository<MiChannelFavorite> & MiRepository<MiChannelFavorite>;
+export type ClipsRepository = Repository<MiClip> & MiRepository<MiClip>;
+export type ClipNotesRepository = Repository<MiClipNote> & MiRepository<MiClipNote>;
+export type ClipFavoritesRepository = Repository<MiClipFavorite> & MiRepository<MiClipFavorite>;
+export type DriveFilesRepository = Repository<MiDriveFile> & MiRepository<MiDriveFile>;
+export type DriveFoldersRepository = Repository<MiDriveFolder> & MiRepository<MiDriveFolder>;
+export type EmojisRepository = Repository<MiEmoji> & MiRepository<MiEmoji>;
+export type FollowingsRepository = Repository<MiFollowing> & MiRepository<MiFollowing>;
+export type FollowRequestsRepository = Repository<MiFollowRequest> & MiRepository<MiFollowRequest>;
+export type GalleryLikesRepository = Repository<MiGalleryLike> & MiRepository<MiGalleryLike>;
+export type GalleryPostsRepository = Repository<MiGalleryPost> & MiRepository<MiGalleryPost>;
+export type HashtagsRepository = Repository<MiHashtag> & MiRepository<MiHashtag>;
+export type InstancesRepository = Repository<MiInstance> & MiRepository<MiInstance>;
+export type MetasRepository = Repository<MiMeta> & MiRepository<MiMeta>;
+export type ModerationLogsRepository = Repository<MiModerationLog> & MiRepository<MiModerationLog>;
+export type MutingsRepository = Repository<MiMuting> & MiRepository<MiMuting>;
+export type RenoteMutingsRepository = Repository<MiRenoteMuting> & MiRepository<MiRenoteMuting>;
+export type NotesRepository = Repository<MiNote> & MiRepository<MiNote>;
+export type NoteFavoritesRepository = Repository<MiNoteFavorite> & MiRepository<MiNoteFavorite>;
+export type NoteReactionsRepository = Repository<MiNoteReaction> & MiRepository<MiNoteReaction>;
+export type NoteThreadMutingsRepository = Repository<MiNoteThreadMuting> & MiRepository<MiNoteThreadMuting>;
+export type NoteUnreadsRepository = Repository<MiNoteUnread> & MiRepository<MiNoteUnread>;
+export type PagesRepository = Repository<MiPage> & MiRepository<MiPage>;
+export type PageLikesRepository = Repository<MiPageLike> & MiRepository<MiPageLike>;
+export type PasswordResetRequestsRepository = Repository<MiPasswordResetRequest> & MiRepository<MiPasswordResetRequest>;
+export type PollsRepository = Repository<MiPoll> & MiRepository<MiPoll>;
+export type PollVotesRepository = Repository<MiPollVote> & MiRepository<MiPollVote>;
+export type PromoNotesRepository = Repository<MiPromoNote> & MiRepository<MiPromoNote>;
+export type PromoReadsRepository = Repository<MiPromoRead> & MiRepository<MiPromoRead>;
+export type RegistrationTicketsRepository = Repository<MiRegistrationTicket> & MiRepository<MiRegistrationTicket>;
+export type RegistryItemsRepository = Repository<MiRegistryItem> & MiRepository<MiRegistryItem>;
+export type RelaysRepository = Repository<MiRelay> & MiRepository<MiRelay>;
+export type SigninsRepository = Repository<MiSignin> & MiRepository<MiSignin>;
+export type SwSubscriptionsRepository = Repository<MiSwSubscription> & MiRepository<MiSwSubscription>;
+export type UsedUsernamesRepository = Repository<MiUsedUsername> & MiRepository<MiUsedUsername>;
+export type UsersRepository = Repository<MiUser> & MiRepository<MiUser>;
+export type UserIpsRepository = Repository<MiUserIp> & MiRepository<MiUserIp>;
+export type UserKeypairsRepository = Repository<MiUserKeypair> & MiRepository<MiUserKeypair>;
+export type UserListsRepository = Repository<MiUserList> & MiRepository<MiUserList>;
+export type UserListFavoritesRepository = Repository<MiUserListFavorite> & MiRepository<MiUserListFavorite>;
+export type UserListMembershipsRepository = Repository<MiUserListMembership> & MiRepository<MiUserListMembership>;
+export type UserNotePiningsRepository = Repository<MiUserNotePining> & MiRepository<MiUserNotePining>;
+export type UserPendingsRepository = Repository<MiUserPending> & MiRepository<MiUserPending>;
+export type UserProfilesRepository = Repository<MiUserProfile> & MiRepository<MiUserProfile>;
+export type UserPublickeysRepository = Repository<MiUserPublickey> & MiRepository<MiUserPublickey>;
+export type UserSecurityKeysRepository = Repository<MiUserSecurityKey> & MiRepository<MiUserSecurityKey>;
+export type WebhooksRepository = Repository<MiWebhook> & MiRepository<MiWebhook>;
+export type ChannelsRepository = Repository<MiChannel> & MiRepository<MiChannel>;
+export type RetentionAggregationsRepository = Repository<MiRetentionAggregation> & MiRepository<MiRetentionAggregation>;
+export type RolesRepository = Repository<MiRole> & MiRepository<MiRole>;
+export type RoleAssignmentsRepository = Repository<MiRoleAssignment> & MiRepository<MiRoleAssignment>;
+export type FlashsRepository = Repository<MiFlash> & MiRepository<MiFlash>;
+export type FlashLikesRepository = Repository<MiFlashLike> & MiRepository<MiFlashLike>;
+export type UserMemoRepository = Repository<MiUserMemo> & MiRepository<MiUserMemo>;
+export type BubbleGameRecordsRepository = Repository<MiBubbleGameRecord> & MiRepository<MiBubbleGameRecord>;
+export type ReversiGamesRepository = Repository<MiReversiGame> & MiRepository<MiReversiGame>;
diff --git a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts
index e5b7c5ac52..9c033b73e2 100644
--- a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts
+++ b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts
@@ -76,7 +76,7 @@ export class ImportAntennasProcessorService {
 					this.logger.warn('Validation Failed');
 					continue;
 				}
-				const result = await this.antennasRepository.insert({
+				const result = await this.antennasRepository.insertOne({
 					id: this.idService.gen(now.getTime()),
 					lastUsedAt: now,
 					userId: job.data.user.id,
@@ -91,7 +91,7 @@ export class ImportAntennasProcessorService {
 					excludeBots: antenna.excludeBots,
 					withReplies: antenna.withReplies,
 					withFile: antenna.withFile,
-				}).then(x => this.antennasRepository.findOneByOrFail(x.identifiers[0]));
+				});
 				this.logger.succ('Antenna created: ' + result.id);
 				this.globalEventService.publishInternalEvent('antennaCreated', result);
 			}
diff --git a/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts b/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts
index a5992c28c8..db9255b35d 100644
--- a/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts
+++ b/packages/backend/src/queue/processors/ImportUserListsProcessorService.ts
@@ -79,11 +79,11 @@ export class ImportUserListsProcessorService {
 				});
 
 				if (list == null) {
-					list = await this.userListsRepository.insert({
+					list = await this.userListsRepository.insertOne({
 						id: this.idService.gen(),
 						userId: user.id,
 						name: listName,
-					}).then(x => this.userListsRepository.findOneByOrFail(x.identifiers[0]));
+					});
 				}
 
 				let target = this.utilityService.isSelfHost(host!) ? await this.usersRepository.findOneBy({
diff --git a/packages/backend/src/server/api/SigninService.ts b/packages/backend/src/server/api/SigninService.ts
index 714e56e8c3..70306c3113 100644
--- a/packages/backend/src/server/api/SigninService.ts
+++ b/packages/backend/src/server/api/SigninService.ts
@@ -29,13 +29,13 @@ export class SigninService {
 	public signin(request: FastifyRequest, reply: FastifyReply, user: MiLocalUser) {
 		setImmediate(async () => {
 			// Append signin history
-			const record = await this.signinsRepository.insert({
+			const record = await this.signinsRepository.insertOne({
 				id: this.idService.gen(),
 				userId: user.id,
 				ip: request.ip,
 				headers: request.headers as any,
 				success: true,
-			}).then(x => this.signinsRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			// Publish signin event
 			this.globalEventService.publishMainStream(user.id, 'signin', await this.signinEntityService.pack(record));
diff --git a/packages/backend/src/server/api/SignupApiService.ts b/packages/backend/src/server/api/SignupApiService.ts
index 546de48e6b..632b0c62bc 100644
--- a/packages/backend/src/server/api/SignupApiService.ts
+++ b/packages/backend/src/server/api/SignupApiService.ts
@@ -183,13 +183,13 @@ export class SignupApiService {
 			const salt = await bcrypt.genSalt(8);
 			const hash = await bcrypt.hash(password, salt);
 
-			const pendingUser = await this.userPendingsRepository.insert({
+			const pendingUser = await this.userPendingsRepository.insertOne({
 				id: this.idService.gen(),
 				code,
 				email: emailAddress!,
 				username: username,
 				password: hash,
-			}).then(x => this.userPendingsRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			const link = `${this.config.url}/signup-complete/${code}`;
 
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 1e7a9fb3ec..955154f4fb 100644
--- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/ad/create.ts
@@ -50,7 +50,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 		private moderationLogService: ModerationLogService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const ad = await this.adsRepository.insert({
+			const ad = await this.adsRepository.insertOne({
 				id: this.idService.gen(),
 				expiresAt: new Date(ps.expiresAt),
 				startsAt: new Date(ps.startsAt),
@@ -61,7 +61,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				ratio: ps.ratio,
 				place: ps.place,
 				memo: ps.memo,
-			}).then(r => this.adsRepository.findOneByOrFail({ id: r.identifiers[0].id }));
+			});
 
 			this.moderationLogService.log(me, 'createAd', {
 				adId: ad.id,
diff --git a/packages/backend/src/server/api/endpoints/admin/invite/create.ts b/packages/backend/src/server/api/endpoints/admin/invite/create.ts
index 0f551e1ba2..5ecae3161a 100644
--- a/packages/backend/src/server/api/endpoints/admin/invite/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/invite/create.ts
@@ -66,11 +66,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			const ticketsPromises = [];
 
 			for (let i = 0; i < ps.count; i++) {
-				ticketsPromises.push(this.registrationTicketsRepository.insert({
+				ticketsPromises.push(this.registrationTicketsRepository.insertOne({
 					id: this.idService.gen(),
 					expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null,
 					code: generateInviteCode(),
-				}).then(x => this.registrationTicketsRepository.findOneByOrFail(x.identifiers[0])));
+				}));
 			}
 
 			const tickets = await Promise.all(ticketsPromises);
diff --git a/packages/backend/src/server/api/endpoints/antennas/create.ts b/packages/backend/src/server/api/endpoints/antennas/create.ts
index 6b7bacb054..ec08198514 100644
--- a/packages/backend/src/server/api/endpoints/antennas/create.ts
+++ b/packages/backend/src/server/api/endpoints/antennas/create.ts
@@ -112,7 +112,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 
 			const now = new Date();
 
-			const antenna = await this.antennasRepository.insert({
+			const antenna = await this.antennasRepository.insertOne({
 				id: this.idService.gen(now.getTime()),
 				lastUsedAt: now,
 				userId: me.id,
@@ -127,7 +127,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				excludeBots: ps.excludeBots,
 				withReplies: ps.withReplies,
 				withFile: ps.withFile,
-			}).then(x => this.antennasRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			this.globalEventService.publishInternalEvent('antennaCreated', antenna);
 
diff --git a/packages/backend/src/server/api/endpoints/app/create.ts b/packages/backend/src/server/api/endpoints/app/create.ts
index 492705d6f9..ba847fc4f0 100644
--- a/packages/backend/src/server/api/endpoints/app/create.ts
+++ b/packages/backend/src/server/api/endpoints/app/create.ts
@@ -54,7 +54,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			const permission = unique(ps.permission.map(v => v.replace(/^(.+)(\/|-)(read|write)$/, '$3:$1')));
 
 			// Create account
-			const app = await this.appsRepository.insert({
+			const app = await this.appsRepository.insertOne({
 				id: this.idService.gen(),
 				userId: me ? me.id : null,
 				name: ps.name,
@@ -62,7 +62,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				permission,
 				callbackUrl: ps.callbackUrl,
 				secret: secret,
-			}).then(x => this.appsRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			return await this.appEntityService.pack(app, null, {
 				detail: true,
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 26dd893138..f8ddfdb75c 100644
--- a/packages/backend/src/server/api/endpoints/auth/session/generate.ts
+++ b/packages/backend/src/server/api/endpoints/auth/session/generate.ts
@@ -78,11 +78,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			const token = randomUUID();
 
 			// Create session token document
-			const doc = await this.authSessionsRepository.insert({
+			const doc = await this.authSessionsRepository.insertOne({
 				id: this.idService.gen(),
 				appId: app.id,
 				token: token,
-			}).then(x => this.authSessionsRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			return {
 				token: doc.token,
diff --git a/packages/backend/src/server/api/endpoints/channels/create.ts b/packages/backend/src/server/api/endpoints/channels/create.ts
index 2866db5424..e3a6d2d670 100644
--- a/packages/backend/src/server/api/endpoints/channels/create.ts
+++ b/packages/backend/src/server/api/endpoints/channels/create.ts
@@ -80,7 +80,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				}
 			}
 
-			const channel = await this.channelsRepository.insert({
+			const channel = await this.channelsRepository.insertOne({
 				id: this.idService.gen(),
 				userId: me.id,
 				name: ps.name,
@@ -89,7 +89,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				isSensitive: ps.isSensitive ?? false,
 				...(ps.color !== undefined ? { color: ps.color } : {}),
 				allowRenoteToExternal: ps.allowRenoteToExternal ?? true,
-			} as MiChannel).then(x => this.channelsRepository.findOneByOrFail(x.identifiers[0]));
+			} as MiChannel);
 
 			return await this.channelEntityService.pack(channel, me);
 		});
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 c94070d9ff..08d9d9cdc3 100644
--- a/packages/backend/src/server/api/endpoints/drive/folders/create.ts
+++ b/packages/backend/src/server/api/endpoints/drive/folders/create.ts
@@ -75,12 +75,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			}
 
 			// Create folder
-			const folder = await this.driveFoldersRepository.insert({
+			const folder = await this.driveFoldersRepository.insertOne({
 				id: this.idService.gen(),
 				name: ps.name,
 				parentId: parent !== null ? parent.id : null,
 				userId: me.id,
-			}).then(x => this.driveFoldersRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			const folderObj = await this.driveFolderEntityService.pack(folder);
 
diff --git a/packages/backend/src/server/api/endpoints/flash/create.ts b/packages/backend/src/server/api/endpoints/flash/create.ts
index 361496e17e..64f13a577e 100644
--- a/packages/backend/src/server/api/endpoints/flash/create.ts
+++ b/packages/backend/src/server/api/endpoints/flash/create.ts
@@ -59,7 +59,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 		private idService: IdService,
 	) {
 		super(meta, paramDef, async (ps, me) => {
-			const flash = await this.flashsRepository.insert({
+			const flash = await this.flashsRepository.insertOne({
 				id: this.idService.gen(),
 				userId: me.id,
 				updatedAt: new Date(),
@@ -68,7 +68,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				script: ps.script,
 				permissions: ps.permissions,
 				visibility: ps.visibility,
-			}).then(x => this.flashsRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			return await this.flashEntityService.pack(flash);
 		});
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 b07cdf1ed9..46f8998810 100644
--- a/packages/backend/src/server/api/endpoints/gallery/posts/create.ts
+++ b/packages/backend/src/server/api/endpoints/gallery/posts/create.ts
@@ -76,7 +76,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				throw new Error();
 			}
 
-			const post = await this.galleryPostsRepository.insert(new MiGalleryPost({
+			const post = await this.galleryPostsRepository.insertOne(new MiGalleryPost({
 				id: this.idService.gen(),
 				updatedAt: new Date(),
 				title: ps.title,
@@ -84,7 +84,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				userId: me.id,
 				isSensitive: ps.isSensitive,
 				fileIds: files.map(file => file.id),
-			})).then(x => this.galleryPostsRepository.findOneByOrFail(x.identifiers[0]));
+			}));
 
 			return await this.galleryPostEntityService.pack(post, me);
 		});
diff --git a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts
index 535a3ea308..c692380288 100644
--- a/packages/backend/src/server/api/endpoints/i/webhooks/create.ts
+++ b/packages/backend/src/server/api/endpoints/i/webhooks/create.ts
@@ -89,14 +89,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				throw new ApiError(meta.errors.tooManyWebhooks);
 			}
 
-			const webhook = await this.webhooksRepository.insert({
+			const webhook = await this.webhooksRepository.insertOne({
 				id: this.idService.gen(),
 				userId: me.id,
 				name: ps.name,
 				url: ps.url,
 				secret: ps.secret,
 				on: ps.on,
-			}).then(x => this.webhooksRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			this.globalEventService.publishInternalEvent('webhookCreated', webhook);
 
diff --git a/packages/backend/src/server/api/endpoints/invite/create.ts b/packages/backend/src/server/api/endpoints/invite/create.ts
index 0ff125ad9c..a70b587da7 100644
--- a/packages/backend/src/server/api/endpoints/invite/create.ts
+++ b/packages/backend/src/server/api/endpoints/invite/create.ts
@@ -66,13 +66,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				}
 			}
 
-			const ticket = await this.registrationTicketsRepository.insert({
+			const ticket = await this.registrationTicketsRepository.insertOne({
 				id: this.idService.gen(),
 				createdBy: me,
 				createdById: me.id,
 				expiresAt: policies.inviteExpirationTime ? new Date(Date.now() + (policies.inviteExpirationTime * 1000 * 60)) : null,
 				code: generateInviteCode(),
-			}).then(x => this.registrationTicketsRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			return await this.inviteCodeEntityService.pack(ticket, me);
 		});
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 a91c506afd..f33f49075b 100644
--- a/packages/backend/src/server/api/endpoints/notes/polls/vote.ts
+++ b/packages/backend/src/server/api/endpoints/notes/polls/vote.ts
@@ -144,12 +144,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 			}
 
 			// Create vote
-			const vote = await this.pollVotesRepository.insert({
+			const vote = await this.pollVotesRepository.insertOne({
 				id: this.idService.gen(createdAt.getTime()),
 				noteId: note.id,
 				userId: me.id,
 				choice: ps.choice,
-			}).then(x => this.pollVotesRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			// Increment votes count
 			const index = ps.choice + 1; // In SQL, array index is 1 based
diff --git a/packages/backend/src/server/api/endpoints/pages/create.ts b/packages/backend/src/server/api/endpoints/pages/create.ts
index 3a02d359f8..fa03b0b457 100644
--- a/packages/backend/src/server/api/endpoints/pages/create.ts
+++ b/packages/backend/src/server/api/endpoints/pages/create.ts
@@ -102,7 +102,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				}
 			});
 
-			const page = await this.pagesRepository.insert(new MiPage({
+			const page = await this.pagesRepository.insertOne(new MiPage({
 				id: this.idService.gen(),
 				updatedAt: new Date(),
 				title: ps.title,
@@ -117,7 +117,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				alignCenter: ps.alignCenter,
 				hideTitleWhenPinned: ps.hideTitleWhenPinned,
 				font: ps.font,
-			})).then(x => this.pagesRepository.findOneByOrFail(x.identifiers[0]));
+			}));
 
 			return await this.pageEntityService.pack(page);
 		});
diff --git a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
index e2db71c5c7..8504da0209 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/create-from-public.ts
@@ -104,11 +104,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				throw new ApiError(meta.errors.tooManyUserLists);
 			}
 
-			const userList = await this.userListsRepository.insert({
+			const userList = await this.userListsRepository.insertOne({
 				id: this.idService.gen(),
 				userId: me.id,
 				name: ps.name,
-			} as MiUserList).then(x => this.userListsRepository.findOneByOrFail(x.identifiers[0]));
+			} as MiUserList);
 
 			const users = (await this.userListMembershipsRepository.findBy({
 				userListId: ps.listId,
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 952580e639..9378bde5cb 100644
--- a/packages/backend/src/server/api/endpoints/users/lists/create.ts
+++ b/packages/backend/src/server/api/endpoints/users/lists/create.ts
@@ -65,11 +65,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				throw new ApiError(meta.errors.tooManyUserLists);
 			}
 
-			const userList = await this.userListsRepository.insert({
+			const userList = await this.userListsRepository.insertOne({
 				id: this.idService.gen(),
 				userId: me.id,
 				name: ps.name,
-			} as MiUserList).then(x => this.userListsRepository.findOneByOrFail(x.identifiers[0]));
+			} as MiUserList);
 
 			return await this.userListEntityService.pack(userList);
 		});
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 1750dd6206..48e14b68cc 100644
--- a/packages/backend/src/server/api/endpoints/users/report-abuse.ts
+++ b/packages/backend/src/server/api/endpoints/users/report-abuse.ts
@@ -82,14 +82,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
 				throw new ApiError(meta.errors.cannotReportAdmin);
 			}
 
-			const report = await this.abuseUserReportsRepository.insert({
+			const report = await this.abuseUserReportsRepository.insertOne({
 				id: this.idService.gen(),
 				targetUserId: user.id,
 				targetUserHost: user.host,
 				reporterId: me.id,
 				reporterHost: null,
 				comment: ps.comment,
-			}).then(x => this.abuseUserReportsRepository.findOneByOrFail(x.identifiers[0]));
+			});
 
 			// Publish event to moderators
 			setImmediate(async () => {
diff --git a/packages/backend/test/e2e/move.ts b/packages/backend/test/e2e/move.ts
index 35050130dc..74cf61a785 100644
--- a/packages/backend/test/e2e/move.ts
+++ b/packages/backend/test/e2e/move.ts
@@ -9,7 +9,7 @@ process.env.NODE_ENV = 'test';
 
 import * as assert from 'assert';
 import { loadConfig } from '@/config.js';
-import { MiUser, UsersRepository } from '@/models/_.js';
+import { MiRepository, MiUser, UsersRepository, miRepository } from '@/models/_.js';
 import { secureRndstr } from '@/misc/secure-rndstr.js';
 import { jobQueue } from '@/boot/common.js';
 import { api, initTestDb, signup, sleep, successfulApiCall, uploadFile } from '../utils.js';
@@ -42,7 +42,7 @@ describe('Account Move', () => {
 		dave = await signup({ username: 'dave' });
 		eve = await signup({ username: 'eve' });
 		frank = await signup({ username: 'frank' });
-		Users = connection.getRepository(MiUser);
+		Users = connection.getRepository(MiUser).extend(miRepository as MiRepository<MiUser>);
 	}, 1000 * 60 * 2);
 
 	afterAll(async () => {
diff --git a/packages/backend/test/e2e/reversi-game.ts b/packages/backend/test/e2e/reversi-game.ts
new file mode 100644
index 0000000000..788255beac
--- /dev/null
+++ b/packages/backend/test/e2e/reversi-game.ts
@@ -0,0 +1,33 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+process.env.NODE_ENV = 'test';
+
+import * as assert from 'assert';
+import { ReversiMatchResponse } from 'misskey-js/entities.js';
+import { api, signup } from '../utils.js';
+import type * as misskey from 'misskey-js';
+
+describe('ReversiGame', () => {
+	let alice: misskey.entities.SignupResponse;
+	let bob: misskey.entities.SignupResponse;
+
+	beforeAll(async () => {
+		alice = await signup({ username: 'alice' });
+		bob = await signup({ username: 'bob' });
+	}, 1000 * 60 * 2);
+
+	test('matches when alice invites bob and bob accepts', async () => {
+		const response1 = await api('reversi/match', { userId: bob.id }, alice);
+		assert.strictEqual(response1.status, 204);
+		assert.strictEqual(response1.body, null);
+		const response2 = await api('reversi/match', { userId: alice.id }, bob);
+		assert.strictEqual(response2.status, 200);
+		assert.notStrictEqual(response2.body, null);
+		const body = response2.body as ReversiMatchResponse;
+		assert.strictEqual(body.user1.id, alice.id);
+		assert.strictEqual(body.user2.id, bob.id);
+	});
+});