From 427034255081adcb3d27426eef7fa4a42bfc6aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 14:30:03 +0900 Subject: [PATCH 01/62] fix(backend): use insertOne insteadof insert/findOneOrFail combination --- .../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 | 11 +- .../backend/src/models/RepositoryModule.ts | 136 +++++++++--------- packages/backend/src/models/_.ts | 37 ++++- .../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 +- 34 files changed, 175 insertions(+), 142 deletions(-) diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts index 9b60df2cae99..40a9db01c057 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, 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 21e31d79a429..8b54bbe01241 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, moderator?: MiUser): Promise { - 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 bb8be26ce6c5..9fd1ebad8724 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 b1feca7fb4d3..7e11b9cdca15 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 { - 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 26cf532c7016..37c5d1adf7b7 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 66db2067d9f8..6799f2c5bbdc 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 e9dc9b57afef..8dd3d64f5b29 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 { - 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 439bc0884585..7f939b99c7a6 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 { - 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 70c537f9abdc..d6eea702970b 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, moderator?: MiUser): Promise { 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 deeecdeb1f12..406ea040316a 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 e6dff067f31f..c6e6b3a1e8db 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 f10e30ef1048..6893d21faa54 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 { Repository } from '@/models/_.js'; +import type { DataSource } from 'typeorm'; const COLUMN_PREFIX = '___' as const; const UNIQUE_TEMP_COLUMN_PREFIX = 'unique_temp___' as const; @@ -271,8 +272,8 @@ export default abstract class Chart { 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 = new Repository(db.getRepository<{ id: number; group?: string | null; date: number; }>(hour)); + this.repositoryForDay = new Repository(db.getRepository<{ id: number; group?: string | null; date: number; }>(day)); } @bindThis @@ -387,11 +388,11 @@ export default abstract class Chart { } // 新規ログ挿入 - log = await repository.insert({ + log = await repository.insertOne({ date: date, ...(group ? { group: group } : {}), ...columns, - }).then(x => repository.findOneByOrFail(x.identifiers[0])) as RawRecord; + }) as RawRecord; 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 bd447570ddf0..d0d37bf4f508 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 { 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, Repository } 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) => new Repository(db.getRepository(MiUser)), inject: [DI.db], }; const $notesRepository: Provider = { provide: DI.notesRepository, - useFactory: (db: DataSource) => db.getRepository(MiNote), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiNote)), inject: [DI.db], }; const $announcementsRepository: Provider = { provide: DI.announcementsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAnnouncement), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiAnnouncement)), inject: [DI.db], }; const $announcementReadsRepository: Provider = { provide: DI.announcementReadsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAnnouncementRead), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiAnnouncementRead)), inject: [DI.db], }; const $appsRepository: Provider = { provide: DI.appsRepository, - useFactory: (db: DataSource) => db.getRepository(MiApp), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiApp)), inject: [DI.db], }; const $avatarDecorationsRepository: Provider = { provide: DI.avatarDecorationsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAvatarDecoration), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiAvatarDecoration)), inject: [DI.db], }; const $noteFavoritesRepository: Provider = { provide: DI.noteFavoritesRepository, - useFactory: (db: DataSource) => db.getRepository(MiNoteFavorite), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiNoteFavorite)), inject: [DI.db], }; const $noteThreadMutingsRepository: Provider = { provide: DI.noteThreadMutingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiNoteThreadMuting), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiNoteThreadMuting)), inject: [DI.db], }; const $noteReactionsRepository: Provider = { provide: DI.noteReactionsRepository, - useFactory: (db: DataSource) => db.getRepository(MiNoteReaction), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiNoteReaction)), inject: [DI.db], }; const $noteUnreadsRepository: Provider = { provide: DI.noteUnreadsRepository, - useFactory: (db: DataSource) => db.getRepository(MiNoteUnread), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiNoteUnread)), inject: [DI.db], }; const $pollsRepository: Provider = { provide: DI.pollsRepository, - useFactory: (db: DataSource) => db.getRepository(MiPoll), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiPoll)), inject: [DI.db], }; const $pollVotesRepository: Provider = { provide: DI.pollVotesRepository, - useFactory: (db: DataSource) => db.getRepository(MiPollVote), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiPollVote)), inject: [DI.db], }; const $userProfilesRepository: Provider = { provide: DI.userProfilesRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserProfile), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserProfile)), inject: [DI.db], }; const $userKeypairsRepository: Provider = { provide: DI.userKeypairsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserKeypair), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserKeypair)), inject: [DI.db], }; const $userPendingsRepository: Provider = { provide: DI.userPendingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserPending), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserPending)), inject: [DI.db], }; const $userSecurityKeysRepository: Provider = { provide: DI.userSecurityKeysRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserSecurityKey), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserSecurityKey)), inject: [DI.db], }; const $userPublickeysRepository: Provider = { provide: DI.userPublickeysRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserPublickey), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserPublickey)), inject: [DI.db], }; const $userListsRepository: Provider = { provide: DI.userListsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserList), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserList)), inject: [DI.db], }; const $userListFavoritesRepository: Provider = { provide: DI.userListFavoritesRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserListFavorite), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserListFavorite)), inject: [DI.db], }; const $userListMembershipsRepository: Provider = { provide: DI.userListMembershipsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserListMembership), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserListMembership)), inject: [DI.db], }; const $userNotePiningsRepository: Provider = { provide: DI.userNotePiningsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserNotePining), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserNotePining)), inject: [DI.db], }; const $userIpsRepository: Provider = { provide: DI.userIpsRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserIp), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserIp)), inject: [DI.db], }; const $usedUsernamesRepository: Provider = { provide: DI.usedUsernamesRepository, - useFactory: (db: DataSource) => db.getRepository(MiUsedUsername), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUsedUsername)), inject: [DI.db], }; const $followingsRepository: Provider = { provide: DI.followingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiFollowing), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiFollowing)), inject: [DI.db], }; const $followRequestsRepository: Provider = { provide: DI.followRequestsRepository, - useFactory: (db: DataSource) => db.getRepository(MiFollowRequest), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiFollowRequest)), inject: [DI.db], }; const $instancesRepository: Provider = { provide: DI.instancesRepository, - useFactory: (db: DataSource) => db.getRepository(MiInstance), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiInstance)), inject: [DI.db], }; const $emojisRepository: Provider = { provide: DI.emojisRepository, - useFactory: (db: DataSource) => db.getRepository(MiEmoji), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiEmoji)), inject: [DI.db], }; const $driveFilesRepository: Provider = { provide: DI.driveFilesRepository, - useFactory: (db: DataSource) => db.getRepository(MiDriveFile), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiDriveFile)), inject: [DI.db], }; const $driveFoldersRepository: Provider = { provide: DI.driveFoldersRepository, - useFactory: (db: DataSource) => db.getRepository(MiDriveFolder), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiDriveFolder)), inject: [DI.db], }; const $metasRepository: Provider = { provide: DI.metasRepository, - useFactory: (db: DataSource) => db.getRepository(MiMeta), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiMeta)), inject: [DI.db], }; const $mutingsRepository: Provider = { provide: DI.mutingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiMuting), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiMuting)), inject: [DI.db], }; const $renoteMutingsRepository: Provider = { provide: DI.renoteMutingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRenoteMuting), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiRenoteMuting)), inject: [DI.db], }; const $blockingsRepository: Provider = { provide: DI.blockingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiBlocking), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiBlocking)), inject: [DI.db], }; const $swSubscriptionsRepository: Provider = { provide: DI.swSubscriptionsRepository, - useFactory: (db: DataSource) => db.getRepository(MiSwSubscription), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiSwSubscription)), inject: [DI.db], }; const $hashtagsRepository: Provider = { provide: DI.hashtagsRepository, - useFactory: (db: DataSource) => db.getRepository(MiHashtag), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiHashtag)), inject: [DI.db], }; const $abuseUserReportsRepository: Provider = { provide: DI.abuseUserReportsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAbuseUserReport), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiAbuseUserReport)), inject: [DI.db], }; const $registrationTicketsRepository: Provider = { provide: DI.registrationTicketsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRegistrationTicket), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiRegistrationTicket)), inject: [DI.db], }; const $authSessionsRepository: Provider = { provide: DI.authSessionsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAuthSession), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiAuthSession)), inject: [DI.db], }; const $accessTokensRepository: Provider = { provide: DI.accessTokensRepository, - useFactory: (db: DataSource) => db.getRepository(MiAccessToken), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiAccessToken)), inject: [DI.db], }; const $signinsRepository: Provider = { provide: DI.signinsRepository, - useFactory: (db: DataSource) => db.getRepository(MiSignin), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiSignin)), inject: [DI.db], }; const $pagesRepository: Provider = { provide: DI.pagesRepository, - useFactory: (db: DataSource) => db.getRepository(MiPage), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiPage)), inject: [DI.db], }; const $pageLikesRepository: Provider = { provide: DI.pageLikesRepository, - useFactory: (db: DataSource) => db.getRepository(MiPageLike), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiPageLike)), inject: [DI.db], }; const $galleryPostsRepository: Provider = { provide: DI.galleryPostsRepository, - useFactory: (db: DataSource) => db.getRepository(MiGalleryPost), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiGalleryPost)), inject: [DI.db], }; const $galleryLikesRepository: Provider = { provide: DI.galleryLikesRepository, - useFactory: (db: DataSource) => db.getRepository(MiGalleryLike), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiGalleryLike)), inject: [DI.db], }; const $moderationLogsRepository: Provider = { provide: DI.moderationLogsRepository, - useFactory: (db: DataSource) => db.getRepository(MiModerationLog), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiModerationLog)), inject: [DI.db], }; const $clipsRepository: Provider = { provide: DI.clipsRepository, - useFactory: (db: DataSource) => db.getRepository(MiClip), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiClip)), inject: [DI.db], }; const $clipNotesRepository: Provider = { provide: DI.clipNotesRepository, - useFactory: (db: DataSource) => db.getRepository(MiClipNote), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiClipNote)), inject: [DI.db], }; const $clipFavoritesRepository: Provider = { provide: DI.clipFavoritesRepository, - useFactory: (db: DataSource) => db.getRepository(MiClipFavorite), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiClipFavorite)), inject: [DI.db], }; const $antennasRepository: Provider = { provide: DI.antennasRepository, - useFactory: (db: DataSource) => db.getRepository(MiAntenna), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiAntenna)), inject: [DI.db], }; const $promoNotesRepository: Provider = { provide: DI.promoNotesRepository, - useFactory: (db: DataSource) => db.getRepository(MiPromoNote), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiPromoNote)), inject: [DI.db], }; const $promoReadsRepository: Provider = { provide: DI.promoReadsRepository, - useFactory: (db: DataSource) => db.getRepository(MiPromoRead), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiPromoRead)), inject: [DI.db], }; const $relaysRepository: Provider = { provide: DI.relaysRepository, - useFactory: (db: DataSource) => db.getRepository(MiRelay), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiRelay)), inject: [DI.db], }; const $channelsRepository: Provider = { provide: DI.channelsRepository, - useFactory: (db: DataSource) => db.getRepository(MiChannel), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiChannel)), inject: [DI.db], }; const $channelFollowingsRepository: Provider = { provide: DI.channelFollowingsRepository, - useFactory: (db: DataSource) => db.getRepository(MiChannelFollowing), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiChannelFollowing)), inject: [DI.db], }; const $channelFavoritesRepository: Provider = { provide: DI.channelFavoritesRepository, - useFactory: (db: DataSource) => db.getRepository(MiChannelFavorite), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiChannelFavorite)), inject: [DI.db], }; const $registryItemsRepository: Provider = { provide: DI.registryItemsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRegistryItem), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiRegistryItem)), inject: [DI.db], }; const $webhooksRepository: Provider = { provide: DI.webhooksRepository, - useFactory: (db: DataSource) => db.getRepository(MiWebhook), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiWebhook)), inject: [DI.db], }; const $adsRepository: Provider = { provide: DI.adsRepository, - useFactory: (db: DataSource) => db.getRepository(MiAd), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiAd)), inject: [DI.db], }; const $passwordResetRequestsRepository: Provider = { provide: DI.passwordResetRequestsRepository, - useFactory: (db: DataSource) => db.getRepository(MiPasswordResetRequest), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiPasswordResetRequest)), inject: [DI.db], }; const $retentionAggregationsRepository: Provider = { provide: DI.retentionAggregationsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRetentionAggregation), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiRetentionAggregation)), inject: [DI.db], }; const $flashsRepository: Provider = { provide: DI.flashsRepository, - useFactory: (db: DataSource) => db.getRepository(MiFlash), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiFlash)), inject: [DI.db], }; const $flashLikesRepository: Provider = { provide: DI.flashLikesRepository, - useFactory: (db: DataSource) => db.getRepository(MiFlashLike), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiFlashLike)), inject: [DI.db], }; const $rolesRepository: Provider = { provide: DI.rolesRepository, - useFactory: (db: DataSource) => db.getRepository(MiRole), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiRole)), inject: [DI.db], }; const $roleAssignmentsRepository: Provider = { provide: DI.roleAssignmentsRepository, - useFactory: (db: DataSource) => db.getRepository(MiRoleAssignment), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiRoleAssignment)), inject: [DI.db], }; const $userMemosRepository: Provider = { provide: DI.userMemosRepository, - useFactory: (db: DataSource) => db.getRepository(MiUserMemo), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserMemo)), inject: [DI.db], }; const $bubbleGameRecordsRepository: Provider = { provide: DI.bubbleGameRecordsRepository, - useFactory: (db: DataSource) => db.getRepository(MiBubbleGameRecord), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiBubbleGameRecord)), inject: [DI.db], }; const $reversiGamesRepository: Provider = { provide: DI.reversiGamesRepository, - useFactory: (db: DataSource) => db.getRepository(MiReversiGame), + useFactory: (db: DataSource) => new Repository(db.getRepository(MiReversiGame)), inject: [DI.db], }; diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 43d42d80dd32..cc32810cdcff 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -3,6 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ +import * as typeorm from 'typeorm'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; @@ -70,8 +71,42 @@ 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 class Repository extends typeorm.Repository { + constructor(repository: typeorm.Repository) { + super(repository.target, repository.manager, repository.queryRunner); + } + + createColumnNames(queryBuilder: typeorm.InsertQueryBuilder): string[] { + // @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; + } + + async insertOne(entity: QueryDeepPartialEntity, findOptions?: Pick, 'relations'>): Promise { + const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); + const columnNames = this.createColumnNames(queryBuilder); + const builder = this.createQueryBuilder() + .addCommonTableExpression(queryBuilder, 'cte', { columnNames }) + .select('*') + .from('cte', this.metadata.targetName); + if (findOptions) { + return await builder.setFindOptions(findOptions).getOneOrFail(); + } + return await builder.getOneOrFail(); + } +} export { MiAbuseUserReport, diff --git a/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts b/packages/backend/src/queue/processors/ImportAntennasProcessorService.ts index e5b7c5ac5213..9c033b73e2b7 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 a5992c28c846..db9255b35d5c 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 714e56e8c3fa..70306c31135b 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 546de48e6bdb..632b0c62bc5d 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 1e7a9fb3ecf3..955154f4fb08 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 { // 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 { // 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 0f551e1ba2c4..c5967cd13734 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 { // 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 6b7bacb05499..ec081985142c 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 { // 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 { // 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 492705d6f921..ba847fc4f0ee 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 { // 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 { // 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 26dd8931385e..f8ddfdb75cbd 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 { // 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 2866db54240c..e3a6d2d670e6 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 { // 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 { // 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 c94070d9ff09..08d9d9cdc340 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 { // 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 361496e17e12..64f13a577e35 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 { // 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 { // 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 b07cdf1ed979..46f8998810d4 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 { // 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 { // 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 535a3ea30850..c69238028804 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 { // 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 0ff125ad9cbe..a70b587da7e5 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 { // 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 a91c506afd27..f33f49075bc0 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 { // 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 3a02d359f80b..fa03b0b4575f 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 { // 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 { // 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 e2db71c5c7f4..8504da0209d2 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 { // 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 952580e639fd..9378bde5cb55 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 { // 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 1750dd6206f1..48e14b68cca5 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 { // 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 () => { From 1fc606c86e83df7f5e70e371a1cd09d887100605 Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Wed, 29 May 2024 14:38:10 +0900 Subject: [PATCH 02/62] fix: typo --- .../backend/src/server/api/endpoints/admin/invite/create.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 c5967cd13734..5ecae3161a39 100644 --- a/packages/backend/src/server/api/endpoints/admin/invite/create.ts +++ b/packages/backend/src/server/api/endpoints/admin/invite/create.ts @@ -70,7 +70,7 @@ export default class extends Endpoint { // eslint- id: this.idService.gen(), expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null, code: generateInviteCode(), - }); + })); } const tickets = await Promise.all(ticketsPromises); From 7e8f95bc9e7b99c76ee9bd4bf3be72a23ccf2b97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 14:58:56 +0900 Subject: [PATCH 03/62] fix(backend): inherit mainAlias? --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index cc32810cdcff..7d4f19226638 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -100,7 +100,7 @@ export class Repository extends typeorm.Reposit const builder = this.createQueryBuilder() .addCommonTableExpression(queryBuilder, 'cte', { columnNames }) .select('*') - .from('cte', this.metadata.targetName); + .from('cte', queryBuilder.expressionMap.mainAlias?.name ?? this.metadata.tableName); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From a979e1f36ae5820478a7dfb2b5235cc92d551fc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 15:24:10 +0900 Subject: [PATCH 04/62] refactor(backend): use extend --- packages/backend/src/core/chart/core.ts | 14 +- .../backend/src/models/RepositoryModule.ts | 136 +++++++-------- packages/backend/src/models/_.ts | 158 +++++++++--------- 3 files changed, 154 insertions(+), 154 deletions(-) diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts index 6893d21faa54..764b3e333d2f 100644 --- a/packages/backend/src/core/chart/core.ts +++ b/packages/backend/src/core/chart/core.ts @@ -14,7 +14,7 @@ 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 { Repository } from '@/models/_.js'; +import { MiRepository, miRepository } from '@/models/_.js'; import type { DataSource } from 'typeorm'; const COLUMN_PREFIX = '___' as const; @@ -146,10 +146,10 @@ export default abstract class Chart { group: string | null; }[] = []; // ↓にしたいけどfindOneとかで型エラーになる - //private repositoryForHour: Repository>; - //private repositoryForDay: Repository>; - private repositoryForHour: Repository<{ id: number; group?: string | null; date: number; }>; - private repositoryForDay: Repository<{ id: number; group?: string | null; date: number; }>; + //private repositoryForHour: MiRepository>; + //private repositoryForDay: MiRepository>; + private repositoryForHour: MiRepository<{ id: number; group?: string | null; date: number; }>; + private repositoryForDay: MiRepository<{ id: number; group?: string | null; date: number; }>; /** * 1日に一回程度実行されれば良いような計算処理を入れる(主にCASCADE削除などアプリケーション側で感知できない変動によるズレの修正用) @@ -272,8 +272,8 @@ export default abstract class Chart { this.logger = logger; const { hour, day } = Chart.schemaToEntity(name, schema, grouped); - this.repositoryForHour = new Repository(db.getRepository<{ id: number; group?: string | null; date: number; }>(hour)); - this.repositoryForDay = new Repository(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 diff --git a/packages/backend/src/models/RepositoryModule.ts b/packages/backend/src/models/RepositoryModule.ts index d0d37bf4f508..d3062d6b36f8 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, Repository } 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) => new Repository(db.getRepository(MiUser)), + useFactory: (db: DataSource) => db.getRepository(MiUser).extend(miRepository as MiRepository), inject: [DI.db], }; const $notesRepository: Provider = { provide: DI.notesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiNote)), + useFactory: (db: DataSource) => db.getRepository(MiNote).extend(miRepository as MiRepository), inject: [DI.db], }; const $announcementsRepository: Provider = { provide: DI.announcementsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiAnnouncement)), + useFactory: (db: DataSource) => db.getRepository(MiAnnouncement).extend(miRepository as MiRepository), inject: [DI.db], }; const $announcementReadsRepository: Provider = { provide: DI.announcementReadsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiAnnouncementRead)), + useFactory: (db: DataSource) => db.getRepository(MiAnnouncementRead).extend(miRepository as MiRepository), inject: [DI.db], }; const $appsRepository: Provider = { provide: DI.appsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiApp)), + useFactory: (db: DataSource) => db.getRepository(MiApp).extend(miRepository as MiRepository), inject: [DI.db], }; const $avatarDecorationsRepository: Provider = { provide: DI.avatarDecorationsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiAvatarDecoration)), + useFactory: (db: DataSource) => db.getRepository(MiAvatarDecoration).extend(miRepository as MiRepository), inject: [DI.db], }; const $noteFavoritesRepository: Provider = { provide: DI.noteFavoritesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiNoteFavorite)), + useFactory: (db: DataSource) => db.getRepository(MiNoteFavorite).extend(miRepository as MiRepository), inject: [DI.db], }; const $noteThreadMutingsRepository: Provider = { provide: DI.noteThreadMutingsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiNoteThreadMuting)), + useFactory: (db: DataSource) => db.getRepository(MiNoteThreadMuting).extend(miRepository as MiRepository), inject: [DI.db], }; const $noteReactionsRepository: Provider = { provide: DI.noteReactionsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiNoteReaction)), + useFactory: (db: DataSource) => db.getRepository(MiNoteReaction).extend(miRepository as MiRepository), inject: [DI.db], }; const $noteUnreadsRepository: Provider = { provide: DI.noteUnreadsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiNoteUnread)), + useFactory: (db: DataSource) => db.getRepository(MiNoteUnread).extend(miRepository as MiRepository), inject: [DI.db], }; const $pollsRepository: Provider = { provide: DI.pollsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiPoll)), + useFactory: (db: DataSource) => db.getRepository(MiPoll).extend(miRepository as MiRepository), inject: [DI.db], }; const $pollVotesRepository: Provider = { provide: DI.pollVotesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiPollVote)), + useFactory: (db: DataSource) => db.getRepository(MiPollVote).extend(miRepository as MiRepository), inject: [DI.db], }; const $userProfilesRepository: Provider = { provide: DI.userProfilesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserProfile)), + useFactory: (db: DataSource) => db.getRepository(MiUserProfile).extend(miRepository as MiRepository), inject: [DI.db], }; const $userKeypairsRepository: Provider = { provide: DI.userKeypairsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserKeypair)), + useFactory: (db: DataSource) => db.getRepository(MiUserKeypair).extend(miRepository as MiRepository), inject: [DI.db], }; const $userPendingsRepository: Provider = { provide: DI.userPendingsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserPending)), + useFactory: (db: DataSource) => db.getRepository(MiUserPending).extend(miRepository as MiRepository), inject: [DI.db], }; const $userSecurityKeysRepository: Provider = { provide: DI.userSecurityKeysRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserSecurityKey)), + useFactory: (db: DataSource) => db.getRepository(MiUserSecurityKey).extend(miRepository as MiRepository), inject: [DI.db], }; const $userPublickeysRepository: Provider = { provide: DI.userPublickeysRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserPublickey)), + useFactory: (db: DataSource) => db.getRepository(MiUserPublickey).extend(miRepository as MiRepository), inject: [DI.db], }; const $userListsRepository: Provider = { provide: DI.userListsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserList)), + useFactory: (db: DataSource) => db.getRepository(MiUserList).extend(miRepository as MiRepository), inject: [DI.db], }; const $userListFavoritesRepository: Provider = { provide: DI.userListFavoritesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserListFavorite)), + useFactory: (db: DataSource) => db.getRepository(MiUserListFavorite).extend(miRepository as MiRepository), inject: [DI.db], }; const $userListMembershipsRepository: Provider = { provide: DI.userListMembershipsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserListMembership)), + useFactory: (db: DataSource) => db.getRepository(MiUserListMembership).extend(miRepository as MiRepository), inject: [DI.db], }; const $userNotePiningsRepository: Provider = { provide: DI.userNotePiningsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserNotePining)), + useFactory: (db: DataSource) => db.getRepository(MiUserNotePining).extend(miRepository as MiRepository), inject: [DI.db], }; const $userIpsRepository: Provider = { provide: DI.userIpsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserIp)), + useFactory: (db: DataSource) => db.getRepository(MiUserIp).extend(miRepository as MiRepository), inject: [DI.db], }; const $usedUsernamesRepository: Provider = { provide: DI.usedUsernamesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUsedUsername)), + useFactory: (db: DataSource) => db.getRepository(MiUsedUsername).extend(miRepository as MiRepository), inject: [DI.db], }; const $followingsRepository: Provider = { provide: DI.followingsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiFollowing)), + useFactory: (db: DataSource) => db.getRepository(MiFollowing).extend(miRepository as MiRepository), inject: [DI.db], }; const $followRequestsRepository: Provider = { provide: DI.followRequestsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiFollowRequest)), + useFactory: (db: DataSource) => db.getRepository(MiFollowRequest).extend(miRepository as MiRepository), inject: [DI.db], }; const $instancesRepository: Provider = { provide: DI.instancesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiInstance)), + useFactory: (db: DataSource) => db.getRepository(MiInstance).extend(miRepository as MiRepository), inject: [DI.db], }; const $emojisRepository: Provider = { provide: DI.emojisRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiEmoji)), + useFactory: (db: DataSource) => db.getRepository(MiEmoji).extend(miRepository as MiRepository), inject: [DI.db], }; const $driveFilesRepository: Provider = { provide: DI.driveFilesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiDriveFile)), + useFactory: (db: DataSource) => db.getRepository(MiDriveFile).extend(miRepository as MiRepository), inject: [DI.db], }; const $driveFoldersRepository: Provider = { provide: DI.driveFoldersRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiDriveFolder)), + useFactory: (db: DataSource) => db.getRepository(MiDriveFolder).extend(miRepository as MiRepository), inject: [DI.db], }; const $metasRepository: Provider = { provide: DI.metasRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiMeta)), + useFactory: (db: DataSource) => db.getRepository(MiMeta).extend(miRepository as MiRepository), inject: [DI.db], }; const $mutingsRepository: Provider = { provide: DI.mutingsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiMuting)), + useFactory: (db: DataSource) => db.getRepository(MiMuting).extend(miRepository as MiRepository), inject: [DI.db], }; const $renoteMutingsRepository: Provider = { provide: DI.renoteMutingsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiRenoteMuting)), + useFactory: (db: DataSource) => db.getRepository(MiRenoteMuting).extend(miRepository as MiRepository), inject: [DI.db], }; const $blockingsRepository: Provider = { provide: DI.blockingsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiBlocking)), + useFactory: (db: DataSource) => db.getRepository(MiBlocking).extend(miRepository as MiRepository), inject: [DI.db], }; const $swSubscriptionsRepository: Provider = { provide: DI.swSubscriptionsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiSwSubscription)), + useFactory: (db: DataSource) => db.getRepository(MiSwSubscription).extend(miRepository as MiRepository), inject: [DI.db], }; const $hashtagsRepository: Provider = { provide: DI.hashtagsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiHashtag)), + useFactory: (db: DataSource) => db.getRepository(MiHashtag).extend(miRepository as MiRepository), inject: [DI.db], }; const $abuseUserReportsRepository: Provider = { provide: DI.abuseUserReportsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiAbuseUserReport)), + useFactory: (db: DataSource) => db.getRepository(MiAbuseUserReport).extend(miRepository as MiRepository), inject: [DI.db], }; const $registrationTicketsRepository: Provider = { provide: DI.registrationTicketsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiRegistrationTicket)), + useFactory: (db: DataSource) => db.getRepository(MiRegistrationTicket).extend(miRepository as MiRepository), inject: [DI.db], }; const $authSessionsRepository: Provider = { provide: DI.authSessionsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiAuthSession)), + useFactory: (db: DataSource) => db.getRepository(MiAuthSession).extend(miRepository as MiRepository), inject: [DI.db], }; const $accessTokensRepository: Provider = { provide: DI.accessTokensRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiAccessToken)), + useFactory: (db: DataSource) => db.getRepository(MiAccessToken).extend(miRepository as MiRepository), inject: [DI.db], }; const $signinsRepository: Provider = { provide: DI.signinsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiSignin)), + useFactory: (db: DataSource) => db.getRepository(MiSignin).extend(miRepository as MiRepository), inject: [DI.db], }; const $pagesRepository: Provider = { provide: DI.pagesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiPage)), + useFactory: (db: DataSource) => db.getRepository(MiPage).extend(miRepository as MiRepository), inject: [DI.db], }; const $pageLikesRepository: Provider = { provide: DI.pageLikesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiPageLike)), + useFactory: (db: DataSource) => db.getRepository(MiPageLike).extend(miRepository as MiRepository), inject: [DI.db], }; const $galleryPostsRepository: Provider = { provide: DI.galleryPostsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiGalleryPost)), + useFactory: (db: DataSource) => db.getRepository(MiGalleryPost).extend(miRepository as MiRepository), inject: [DI.db], }; const $galleryLikesRepository: Provider = { provide: DI.galleryLikesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiGalleryLike)), + useFactory: (db: DataSource) => db.getRepository(MiGalleryLike).extend(miRepository as MiRepository), inject: [DI.db], }; const $moderationLogsRepository: Provider = { provide: DI.moderationLogsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiModerationLog)), + useFactory: (db: DataSource) => db.getRepository(MiModerationLog).extend(miRepository as MiRepository), inject: [DI.db], }; const $clipsRepository: Provider = { provide: DI.clipsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiClip)), + useFactory: (db: DataSource) => db.getRepository(MiClip).extend(miRepository as MiRepository), inject: [DI.db], }; const $clipNotesRepository: Provider = { provide: DI.clipNotesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiClipNote)), + useFactory: (db: DataSource) => db.getRepository(MiClipNote).extend(miRepository as MiRepository), inject: [DI.db], }; const $clipFavoritesRepository: Provider = { provide: DI.clipFavoritesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiClipFavorite)), + useFactory: (db: DataSource) => db.getRepository(MiClipFavorite).extend(miRepository as MiRepository), inject: [DI.db], }; const $antennasRepository: Provider = { provide: DI.antennasRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiAntenna)), + useFactory: (db: DataSource) => db.getRepository(MiAntenna).extend(miRepository as MiRepository), inject: [DI.db], }; const $promoNotesRepository: Provider = { provide: DI.promoNotesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiPromoNote)), + useFactory: (db: DataSource) => db.getRepository(MiPromoNote).extend(miRepository as MiRepository), inject: [DI.db], }; const $promoReadsRepository: Provider = { provide: DI.promoReadsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiPromoRead)), + useFactory: (db: DataSource) => db.getRepository(MiPromoRead).extend(miRepository as MiRepository), inject: [DI.db], }; const $relaysRepository: Provider = { provide: DI.relaysRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiRelay)), + useFactory: (db: DataSource) => db.getRepository(MiRelay).extend(miRepository as MiRepository), inject: [DI.db], }; const $channelsRepository: Provider = { provide: DI.channelsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiChannel)), + useFactory: (db: DataSource) => db.getRepository(MiChannel).extend(miRepository as MiRepository), inject: [DI.db], }; const $channelFollowingsRepository: Provider = { provide: DI.channelFollowingsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiChannelFollowing)), + useFactory: (db: DataSource) => db.getRepository(MiChannelFollowing).extend(miRepository as MiRepository), inject: [DI.db], }; const $channelFavoritesRepository: Provider = { provide: DI.channelFavoritesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiChannelFavorite)), + useFactory: (db: DataSource) => db.getRepository(MiChannelFavorite).extend(miRepository as MiRepository), inject: [DI.db], }; const $registryItemsRepository: Provider = { provide: DI.registryItemsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiRegistryItem)), + useFactory: (db: DataSource) => db.getRepository(MiRegistryItem).extend(miRepository as MiRepository), inject: [DI.db], }; const $webhooksRepository: Provider = { provide: DI.webhooksRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiWebhook)), + useFactory: (db: DataSource) => db.getRepository(MiWebhook).extend(miRepository as MiRepository), inject: [DI.db], }; const $adsRepository: Provider = { provide: DI.adsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiAd)), + useFactory: (db: DataSource) => db.getRepository(MiAd).extend(miRepository as MiRepository), inject: [DI.db], }; const $passwordResetRequestsRepository: Provider = { provide: DI.passwordResetRequestsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiPasswordResetRequest)), + useFactory: (db: DataSource) => db.getRepository(MiPasswordResetRequest).extend(miRepository as MiRepository), inject: [DI.db], }; const $retentionAggregationsRepository: Provider = { provide: DI.retentionAggregationsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiRetentionAggregation)), + useFactory: (db: DataSource) => db.getRepository(MiRetentionAggregation).extend(miRepository as MiRepository), inject: [DI.db], }; const $flashsRepository: Provider = { provide: DI.flashsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiFlash)), + useFactory: (db: DataSource) => db.getRepository(MiFlash).extend(miRepository as MiRepository), inject: [DI.db], }; const $flashLikesRepository: Provider = { provide: DI.flashLikesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiFlashLike)), + useFactory: (db: DataSource) => db.getRepository(MiFlashLike).extend(miRepository as MiRepository), inject: [DI.db], }; const $rolesRepository: Provider = { provide: DI.rolesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiRole)), + useFactory: (db: DataSource) => db.getRepository(MiRole).extend(miRepository as MiRepository), inject: [DI.db], }; const $roleAssignmentsRepository: Provider = { provide: DI.roleAssignmentsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiRoleAssignment)), + useFactory: (db: DataSource) => db.getRepository(MiRoleAssignment).extend(miRepository as MiRepository), inject: [DI.db], }; const $userMemosRepository: Provider = { provide: DI.userMemosRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiUserMemo)), + useFactory: (db: DataSource) => db.getRepository(MiUserMemo).extend(miRepository as MiRepository), inject: [DI.db], }; const $bubbleGameRecordsRepository: Provider = { provide: DI.bubbleGameRecordsRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiBubbleGameRecord)), + useFactory: (db: DataSource) => db.getRepository(MiBubbleGameRecord).extend(miRepository as MiRepository), inject: [DI.db], }; const $reversiGamesRepository: Provider = { provide: DI.reversiGamesRepository, - useFactory: (db: DataSource) => new Repository(db.getRepository(MiReversiGame)), + useFactory: (db: DataSource) => db.getRepository(MiReversiGame).extend(miRepository as MiRepository), inject: [DI.db], }; diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 7d4f19226638..7d05f74131b1 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import * as typeorm from 'typeorm'; +import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository } from 'typeorm'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; @@ -73,12 +73,13 @@ import { MiBubbleGameRecord } from '@/models/BubbleGameRecord.js'; import { MiReversiGame } from '@/models/ReversiGame.js'; import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; -export class Repository extends typeorm.Repository { - constructor(repository: typeorm.Repository) { - super(repository.target, repository.manager, repository.queryRunner); - } +export interface MiRepository { + createColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; + insertOne(this: Repository & MiRepository, entity: QueryDeepPartialEntity, findOptions?: Pick, 'relations'>): Promise; +} - createColumnNames(queryBuilder: typeorm.InsertQueryBuilder): string[] { +export const miRepository = { + createColumnNames(queryBuilder) { // @ts-expect-error -- protected const insertedColumns = queryBuilder.getInsertedColumns(); if (insertedColumns.length) { @@ -92,21 +93,20 @@ export class Repository extends typeorm.Reposit } } return queryBuilder.expressionMap.insertColumns; - } - - async insertOne(entity: QueryDeepPartialEntity, findOptions?: Pick, 'relations'>): Promise { + }, + async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); const columnNames = this.createColumnNames(queryBuilder); const builder = this.createQueryBuilder() .addCommonTableExpression(queryBuilder, 'cte', { columnNames }) .select('*') - .from('cte', queryBuilder.expressionMap.mainAlias?.name ?? this.metadata.tableName); + .from('cte', this.metadata.tableName); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } return await builder.getOneOrFail(); - } -} + }, +} satisfies MiRepository; export { MiAbuseUserReport, @@ -178,70 +178,70 @@ export { MiReversiGame, }; -export type AbuseUserReportsRepository = Repository; -export type AccessTokensRepository = Repository; -export type AdsRepository = Repository; -export type AnnouncementsRepository = Repository; -export type AnnouncementReadsRepository = Repository; -export type AntennasRepository = Repository; -export type AppsRepository = Repository; -export type AvatarDecorationsRepository = Repository; -export type AuthSessionsRepository = Repository; -export type BlockingsRepository = Repository; -export type ChannelFollowingsRepository = Repository; -export type ChannelFavoritesRepository = Repository; -export type ClipsRepository = Repository; -export type ClipNotesRepository = Repository; -export type ClipFavoritesRepository = Repository; -export type DriveFilesRepository = Repository; -export type DriveFoldersRepository = Repository; -export type EmojisRepository = Repository; -export type FollowingsRepository = Repository; -export type FollowRequestsRepository = Repository; -export type GalleryLikesRepository = Repository; -export type GalleryPostsRepository = Repository; -export type HashtagsRepository = Repository; -export type InstancesRepository = Repository; -export type MetasRepository = Repository; -export type ModerationLogsRepository = Repository; -export type MutingsRepository = Repository; -export type RenoteMutingsRepository = Repository; -export type NotesRepository = Repository; -export type NoteFavoritesRepository = Repository; -export type NoteReactionsRepository = Repository; -export type NoteThreadMutingsRepository = Repository; -export type NoteUnreadsRepository = Repository; -export type PagesRepository = Repository; -export type PageLikesRepository = Repository; -export type PasswordResetRequestsRepository = Repository; -export type PollsRepository = Repository; -export type PollVotesRepository = Repository; -export type PromoNotesRepository = Repository; -export type PromoReadsRepository = Repository; -export type RegistrationTicketsRepository = Repository; -export type RegistryItemsRepository = Repository; -export type RelaysRepository = Repository; -export type SigninsRepository = Repository; -export type SwSubscriptionsRepository = Repository; -export type UsedUsernamesRepository = Repository; -export type UsersRepository = Repository; -export type UserIpsRepository = Repository; -export type UserKeypairsRepository = Repository; -export type UserListsRepository = Repository; -export type UserListFavoritesRepository = Repository; -export type UserListMembershipsRepository = Repository; -export type UserNotePiningsRepository = Repository; -export type UserPendingsRepository = Repository; -export type UserProfilesRepository = Repository; -export type UserPublickeysRepository = Repository; -export type UserSecurityKeysRepository = Repository; -export type WebhooksRepository = Repository; -export type ChannelsRepository = Repository; -export type RetentionAggregationsRepository = Repository; -export type RolesRepository = Repository; -export type RoleAssignmentsRepository = Repository; -export type FlashsRepository = Repository; -export type FlashLikesRepository = Repository; -export type UserMemoRepository = Repository; -export type BubbleGameRecordsRepository = Repository; -export type ReversiGamesRepository = Repository; +export type AbuseUserReportsRepository = Repository & MiRepository; +export type AccessTokensRepository = Repository & MiRepository; +export type AdsRepository = Repository & MiRepository; +export type AnnouncementsRepository = Repository & MiRepository; +export type AnnouncementReadsRepository = Repository & MiRepository; +export type AntennasRepository = Repository & MiRepository; +export type AppsRepository = Repository & MiRepository; +export type AvatarDecorationsRepository = Repository & MiRepository; +export type AuthSessionsRepository = Repository & MiRepository; +export type BlockingsRepository = Repository & MiRepository; +export type ChannelFollowingsRepository = Repository & MiRepository; +export type ChannelFavoritesRepository = Repository & MiRepository; +export type ClipsRepository = Repository & MiRepository; +export type ClipNotesRepository = Repository & MiRepository; +export type ClipFavoritesRepository = Repository & MiRepository; +export type DriveFilesRepository = Repository & MiRepository; +export type DriveFoldersRepository = Repository & MiRepository; +export type EmojisRepository = Repository & MiRepository; +export type FollowingsRepository = Repository & MiRepository; +export type FollowRequestsRepository = Repository & MiRepository; +export type GalleryLikesRepository = Repository & MiRepository; +export type GalleryPostsRepository = Repository & MiRepository; +export type HashtagsRepository = Repository & MiRepository; +export type InstancesRepository = Repository & MiRepository; +export type MetasRepository = Repository & MiRepository; +export type ModerationLogsRepository = Repository & MiRepository; +export type MutingsRepository = Repository & MiRepository; +export type RenoteMutingsRepository = Repository & MiRepository; +export type NotesRepository = Repository & MiRepository; +export type NoteFavoritesRepository = Repository & MiRepository; +export type NoteReactionsRepository = Repository & MiRepository; +export type NoteThreadMutingsRepository = Repository & MiRepository; +export type NoteUnreadsRepository = Repository & MiRepository; +export type PagesRepository = Repository & MiRepository; +export type PageLikesRepository = Repository & MiRepository; +export type PasswordResetRequestsRepository = Repository & MiRepository; +export type PollsRepository = Repository & MiRepository; +export type PollVotesRepository = Repository & MiRepository; +export type PromoNotesRepository = Repository & MiRepository; +export type PromoReadsRepository = Repository & MiRepository; +export type RegistrationTicketsRepository = Repository & MiRepository; +export type RegistryItemsRepository = Repository & MiRepository; +export type RelaysRepository = Repository & MiRepository; +export type SigninsRepository = Repository & MiRepository; +export type SwSubscriptionsRepository = Repository & MiRepository; +export type UsedUsernamesRepository = Repository & MiRepository; +export type UsersRepository = Repository & MiRepository; +export type UserIpsRepository = Repository & MiRepository; +export type UserKeypairsRepository = Repository & MiRepository; +export type UserListsRepository = Repository & MiRepository; +export type UserListFavoritesRepository = Repository & MiRepository; +export type UserListMembershipsRepository = Repository & MiRepository; +export type UserNotePiningsRepository = Repository & MiRepository; +export type UserPendingsRepository = Repository & MiRepository; +export type UserProfilesRepository = Repository & MiRepository; +export type UserPublickeysRepository = Repository & MiRepository; +export type UserSecurityKeysRepository = Repository & MiRepository; +export type WebhooksRepository = Repository & MiRepository; +export type ChannelsRepository = Repository & MiRepository; +export type RetentionAggregationsRepository = Repository & MiRepository; +export type RolesRepository = Repository & MiRepository; +export type RoleAssignmentsRepository = Repository & MiRepository; +export type FlashsRepository = Repository & MiRepository; +export type FlashLikesRepository = Repository & MiRepository; +export type UserMemoRepository = Repository & MiRepository; +export type BubbleGameRecordsRepository = Repository & MiRepository; +export type ReversiGamesRepository = Repository & MiRepository; From f8851e6d517376bcb2d76305a06c40c2a2c0c903 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 15:35:16 +0900 Subject: [PATCH 05/62] fix(backend): invalid entityTarget --- packages/backend/src/models/_.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 7d05f74131b1..cbc4ba001504 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -98,9 +98,9 @@ export const miRepository = { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); const columnNames = this.createColumnNames(queryBuilder); const builder = this.createQueryBuilder() - .addCommonTableExpression(queryBuilder, 'cte', { columnNames }) + .addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }) .select('*') - .from('cte', this.metadata.tableName); + .from(this.metadata.tableName, this.metadata.tableName); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From 86dd737def4781e997f6e13596408d5a4cb9ed05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 15:47:52 +0900 Subject: [PATCH 06/62] fix(backend): fake where --- packages/backend/src/models/_.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index cbc4ba001504..e502659550fd 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -100,7 +100,8 @@ export const miRepository = { const builder = this.createQueryBuilder() .addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }) .select('*') - .from(this.metadata.tableName, this.metadata.tableName); + .from(this.metadata.tableName, this.metadata.tableName) + .where('1 = 1'); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From 92e2c5c45fcec1dd321ccc4fafd708f011e49041 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 15:53:09 +0900 Subject: [PATCH 07/62] chore: debug --- packages/backend/src/models/_.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index e502659550fd..364eb73c4797 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -102,6 +102,7 @@ export const miRepository = { .select('*') .from(this.metadata.tableName, this.metadata.tableName) .where('1 = 1'); + console.log(builder.getQueryAndParameters()); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From 698c325b97f0ba9c78b6be507f7cea85f74cf21f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 15:59:48 +0900 Subject: [PATCH 08/62] chore: debug --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 364eb73c4797..73a3ac088531 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -102,7 +102,7 @@ export const miRepository = { .select('*') .from(this.metadata.tableName, this.metadata.tableName) .where('1 = 1'); - console.log(builder.getQueryAndParameters()); + console.log(builder.getSql()); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From 6304c4259af406793fcd0b50d5f3f8c8609c5dbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 16:12:09 +0900 Subject: [PATCH 09/62] test: log --- packages/backend/src/models/_.ts | 4 +--- packages/backend/src/postgres.ts | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 73a3ac088531..cbc4ba001504 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -100,9 +100,7 @@ export const miRepository = { const builder = this.createQueryBuilder() .addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }) .select('*') - .from(this.metadata.tableName, this.metadata.tableName) - .where('1 = 1'); - console.log(builder.getSql()); + .from(this.metadata.tableName, this.metadata.tableName); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index 2d14537bbb07..f986759fe22b 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -243,8 +243,8 @@ export function createPostgresDataSource(config: Config) { }, } : false, logging: log, - logger: log ? new MyCustomLogger() : undefined, - maxQueryExecutionTime: 300, + logger: log ? process.env.NODE_ENV === 'test' ? 'advanced-console' : new MyCustomLogger() : undefined, + maxQueryExecutionTime: log ? 0 : 300, entities: entities, migrations: ['../../migration/*.js'], }); From 47278d3f6d6b567b2c6a7462a321a2509825e403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 16:29:39 +0900 Subject: [PATCH 10/62] fix(backend): column names --- packages/backend/src/models/_.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index cbc4ba001504..a95d37e1faff 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -74,12 +74,17 @@ import { MiReversiGame } from '@/models/ReversiGame.js'; import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; export interface MiRepository { - createColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; + createAliasColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; + createTableColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; insertOne(this: Repository & MiRepository, entity: QueryDeepPartialEntity, findOptions?: Pick, 'relations'>): Promise; } export const miRepository = { - createColumnNames(queryBuilder) { + createAliasColumnNames(queryBuilder) { + const tableColumnNames = this.createTableColumnNames(queryBuilder); + return tableColumnNames.map(columnName => `${queryBuilder.alias}_${columnName}`); + }, + createTableColumnNames(queryBuilder) { // @ts-expect-error -- protected const insertedColumns = queryBuilder.getInsertedColumns(); if (insertedColumns.length) { @@ -96,7 +101,7 @@ export const miRepository = { }, async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); - const columnNames = this.createColumnNames(queryBuilder); + const columnNames = this.createAliasColumnNames(queryBuilder); const builder = this.createQueryBuilder() .addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }) .select('*') From e4d3a66f62ce38480b040106a1455e32ad56180e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 16:35:24 +0900 Subject: [PATCH 11/62] fix(backend): remove dummy from --- packages/backend/src/models/_.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index a95d37e1faff..2377fef95187 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -106,6 +106,7 @@ export const miRepository = { .addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }) .select('*') .from(this.metadata.tableName, this.metadata.tableName); + builder.expressionMap.aliases.splice(1, 1); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From 55ce6f831affd65b8a01a1e84f5258fbd9e82d6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 16:41:08 +0900 Subject: [PATCH 12/62] revert: log --- packages/backend/src/models/_.ts | 1 + packages/backend/src/postgres.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 2377fef95187..cdeb957caab9 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -107,6 +107,7 @@ export const miRepository = { .select('*') .from(this.metadata.tableName, this.metadata.tableName); builder.expressionMap.aliases.splice(1, 1); + console.log(builder.getQueryAndParameters()); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index f986759fe22b..2d14537bbb07 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -243,8 +243,8 @@ export function createPostgresDataSource(config: Config) { }, } : false, logging: log, - logger: log ? process.env.NODE_ENV === 'test' ? 'advanced-console' : new MyCustomLogger() : undefined, - maxQueryExecutionTime: log ? 0 : 300, + logger: log ? new MyCustomLogger() : undefined, + maxQueryExecutionTime: 300, entities: entities, migrations: ['../../migration/*.js'], }); From 3bb8b6fc69846da11015d9f25118e358ea8780e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 16:51:33 +0900 Subject: [PATCH 13/62] fix(backend): position --- packages/backend/src/models/_.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index cdeb957caab9..825ce790f0e0 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository } from 'typeorm'; +import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository, SelectQueryBuilder } from 'typeorm'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; @@ -74,16 +74,12 @@ import { MiReversiGame } from '@/models/ReversiGame.js'; import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; export interface MiRepository { - createAliasColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; createTableColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; insertOne(this: Repository & MiRepository, entity: QueryDeepPartialEntity, findOptions?: Pick, 'relations'>): Promise; + selectAliasColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder, builder: SelectQueryBuilder): void; } export const miRepository = { - createAliasColumnNames(queryBuilder) { - const tableColumnNames = this.createTableColumnNames(queryBuilder); - return tableColumnNames.map(columnName => `${queryBuilder.alias}_${columnName}`); - }, createTableColumnNames(queryBuilder) { // @ts-expect-error -- protected const insertedColumns = queryBuilder.getInsertedColumns(); @@ -101,18 +97,28 @@ export const miRepository = { }, async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); - const columnNames = this.createAliasColumnNames(queryBuilder); + const columnNames = this.createTableColumnNames(queryBuilder); const builder = this.createQueryBuilder() .addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }) .select('*') .from(this.metadata.tableName, this.metadata.tableName); builder.expressionMap.aliases.splice(1, 1); + this.selectAliasColumnNames(queryBuilder, builder); console.log(builder.getQueryAndParameters()); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } return await builder.getOneOrFail(); }, + 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.createTableColumnNames(queryBuilder)) { + selectOrAddSelect(columnName, `${queryBuilder.alias}_${columnName}`); + } + }, } satisfies MiRepository; export { From 10b5eebd8d023c21add32e5906f5aa31906441ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 16:54:39 +0900 Subject: [PATCH 14/62] fix(backend): automatic aliasing --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 825ce790f0e0..5586b2af01ee 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -116,7 +116,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(columnName, `${queryBuilder.alias}_${columnName}`); + selectOrAddSelect(`${queryBuilder.alias}.${columnName}`); } }, } satisfies MiRepository; From 482ad29a0833f2da85a3e25685a178519adb9ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 17:01:55 +0900 Subject: [PATCH 15/62] chore(backend): alias --- packages/backend/src/models/_.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 5586b2af01ee..5497616e6839 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -102,9 +102,8 @@ export const miRepository = { .addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }) .select('*') .from(this.metadata.tableName, this.metadata.tableName); - builder.expressionMap.aliases.splice(1, 1); this.selectAliasColumnNames(queryBuilder, builder); - console.log(builder.getQueryAndParameters()); + console.log(builder.expressionMap.aliases, builder.getQueryAndParameters()); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From 024d854cf46abd09ed377a86f844de7ea5a4f004 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 17:07:18 +0900 Subject: [PATCH 16/62] chore(backend): remove from --- packages/backend/src/models/_.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 5497616e6839..f4ec0830a933 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -98,10 +98,7 @@ export const miRepository = { async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); const columnNames = this.createTableColumnNames(queryBuilder); - const builder = this.createQueryBuilder() - .addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }) - .select('*') - .from(this.metadata.tableName, this.metadata.tableName); + const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }); this.selectAliasColumnNames(queryBuilder, builder); console.log(builder.expressionMap.aliases, builder.getQueryAndParameters()); if (findOptions) { @@ -115,7 +112,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(`${queryBuilder.alias}.${columnName}`); + selectOrAddSelect(`${queryBuilder.alias}.${columnName}`, `${queryBuilder.alias}_${columnName}`); } }, } satisfies MiRepository; From 7e967f36ba14749e2873fef02556ef7e0d07b3bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 17:23:00 +0900 Subject: [PATCH 17/62] fix(backend): type --- packages/backend/src/core/chart/core.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts index 764b3e333d2f..9bced4b5dbf1 100644 --- a/packages/backend/src/core/chart/core.ts +++ b/packages/backend/src/core/chart/core.ts @@ -15,7 +15,7 @@ import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/misc import type Logger from '@/logger.js'; import { bindThis } from '@/decorators.js'; import { MiRepository, miRepository } from '@/models/_.js'; -import type { DataSource } from 'typeorm'; +import type { DataSource, Repository } from 'typeorm'; const COLUMN_PREFIX = '___' as const; const UNIQUE_TEMP_COLUMN_PREFIX = 'unique_temp___' as const; @@ -146,10 +146,10 @@ export default abstract class Chart { group: string | null; }[] = []; // ↓にしたいけどfindOneとかで型エラーになる - //private repositoryForHour: MiRepository>; - //private repositoryForDay: MiRepository>; - private repositoryForHour: MiRepository<{ id: number; group?: string | null; date: number; }>; - private repositoryForDay: MiRepository<{ id: number; group?: string | null; date: number; }>; + //private repositoryForHour: Repository> & MiRepository>; + //private repositoryForDay: Repository> & MiRepository>; + 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削除などアプリケーション側で感知できない変動によるズレの修正用) From f694bb78ee9f3f9be18b63abd91cef44f44250bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 17:30:19 +0900 Subject: [PATCH 18/62] fix(backend): avoid pure name --- packages/backend/src/core/chart/core.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts index 9bced4b5dbf1..f40bdf3d7318 100644 --- a/packages/backend/src/core/chart/core.ts +++ b/packages/backend/src/core/chart/core.ts @@ -212,6 +212,10 @@ export default abstract class Chart { } { const createEntity = (span: 'hour' | 'day'): EntitySchema => new EntitySchema({ name: + span === 'hour' ? `ChartX${name.replace(/[^a-zA-Z0-9]/g, '')}` : + span === 'day' ? `ChartDayX${name.replace(/[^a-zA-Z0-9]/g, '')}` : + new Error('not happen') as never, + tableName: span === 'hour' ? `__chart__${camelToSnake(name)}` : span === 'day' ? `__chart_day__${camelToSnake(name)}` : new Error('not happen') as never, From b27b5c9ed73350cc313fae578b29fdb71814384e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 17:35:56 +0900 Subject: [PATCH 19/62] test(backend): fix type --- packages/backend/test/e2e/move.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/backend/test/e2e/move.ts b/packages/backend/test/e2e/move.ts index 35050130dc1b..74cf61a7857a 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); }, 1000 * 60 * 2); afterAll(async () => { From 45f38094b9e5485979aae6f59f703250bdaac5bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 17:49:19 +0900 Subject: [PATCH 20/62] chore(backend): use cte --- packages/backend/src/models/_.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index f4ec0830a933..d7fff622e223 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -98,7 +98,8 @@ export const miRepository = { async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); const columnNames = this.createTableColumnNames(queryBuilder); - const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, this.metadata.tableName, { columnNames }); + const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); + builder.expressionMap.mainAlias!.tablePath = 'cte'; this.selectAliasColumnNames(queryBuilder, builder); console.log(builder.expressionMap.aliases, builder.getQueryAndParameters()); if (findOptions) { From 68e1c615cc3dcf04b30e82633948edba59fc383a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 18:02:18 +0900 Subject: [PATCH 21/62] fix(backend): avoid useless alias --- packages/backend/src/models/_.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index d7fff622e223..8fd16c6666c3 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -97,6 +97,8 @@ export const miRepository = { }, async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); + // @ts-expect-error -- protected + queryBuilder.expressionMap.mainAlias!.name = queryBuilder.getMainTableName(); const columnNames = this.createTableColumnNames(queryBuilder); const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); builder.expressionMap.mainAlias!.tablePath = 'cte'; From c8ac5a7e2b202703a644a8d8696689cfe359640a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 18:07:04 +0900 Subject: [PATCH 22/62] fix(backend): fix typo --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 8fd16c6666c3..72203ee945d7 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -115,7 +115,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(`${queryBuilder.alias}.${columnName}`, `${queryBuilder.alias}_${columnName}`); + selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`); } }, } satisfies MiRepository; From 0d8a88b2c89011ad07636999e630e63c9f25d2fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 18:16:10 +0900 Subject: [PATCH 23/62] fix(backend): __disambiguation__ --- packages/backend/src/models/_.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 72203ee945d7..0d60e4b17b52 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -84,16 +84,16 @@ export const miRepository = { // @ts-expect-error -- protected const insertedColumns = queryBuilder.getInsertedColumns(); if (insertedColumns.length) { - return insertedColumns.map(column => column.databaseName); + return insertedColumns.map(column => `__disambiguation__${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 Object.keys(valueSets[0]).map(key => `__disambiguation__${key}`); } } - return queryBuilder.expressionMap.insertColumns; + return queryBuilder.expressionMap.insertColumns.map(column => `__disambiguation__${column}`); }, async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); @@ -115,7 +115,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`); + selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName.slice('__disambiguation__'.length)}`); } }, } satisfies MiRepository; From 4bd5d219af5b42e4d2c3dbfa478dd22060957caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 18:19:53 +0900 Subject: [PATCH 24/62] fix(backend): quote --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 0d60e4b17b52..c82d7a633445 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -115,7 +115,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName.slice('__disambiguation__'.length)}`); + selectOrAddSelect(`"${builder.alias}"."${columnName}"`, `${builder.alias}_${columnName.slice('__disambiguation__'.length)}`); } }, } satisfies MiRepository; From 461f4bb64bc23bb39351b0d7043b6ed5f7dd6e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 18:32:43 +0900 Subject: [PATCH 25/62] chore(backend): t --- packages/backend/src/models/_.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index c82d7a633445..f323d84fd5cc 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -84,21 +84,21 @@ export const miRepository = { // @ts-expect-error -- protected const insertedColumns = queryBuilder.getInsertedColumns(); if (insertedColumns.length) { - return insertedColumns.map(column => `__disambiguation__${column.databaseName}`); + 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]).map(key => `__disambiguation__${key}`); + return Object.keys(valueSets[0]); } } - return queryBuilder.expressionMap.insertColumns.map(column => `__disambiguation__${column}`); + return queryBuilder.expressionMap.insertColumns; }, async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); // @ts-expect-error -- protected - queryBuilder.expressionMap.mainAlias!.name = queryBuilder.getMainTableName(); + queryBuilder.expressionMap.mainAlias!.name = 't'; const columnNames = this.createTableColumnNames(queryBuilder); const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); builder.expressionMap.mainAlias!.tablePath = 'cte'; @@ -115,7 +115,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(`"${builder.alias}"."${columnName}"`, `${builder.alias}_${columnName.slice('__disambiguation__'.length)}`); + selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`); } }, } satisfies MiRepository; From 6302a8b9040622a265e165f6306f434cdd948604 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 18:36:46 +0900 Subject: [PATCH 26/62] chore(backend): accessible --- packages/backend/src/models/_.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index f323d84fd5cc..a639039befb3 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -97,7 +97,6 @@ export const miRepository = { }, async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); - // @ts-expect-error -- protected queryBuilder.expressionMap.mainAlias!.name = 't'; const columnNames = this.createTableColumnNames(queryBuilder); const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); From 9227496389af7771d5dcd176e6b5fdb4be058f8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 22:35:34 +0900 Subject: [PATCH 27/62] chore(backend): concrete returning --- packages/backend/src/core/chart/core.ts | 4 ++-- packages/backend/src/models/_.ts | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts index f40bdf3d7318..af5485a46ee9 100644 --- a/packages/backend/src/core/chart/core.ts +++ b/packages/backend/src/core/chart/core.ts @@ -212,8 +212,8 @@ export default abstract class Chart { } { const createEntity = (span: 'hour' | 'day'): EntitySchema => new EntitySchema({ name: - span === 'hour' ? `ChartX${name.replace(/[^a-zA-Z0-9]/g, '')}` : - span === 'day' ? `ChartDayX${name.replace(/[^a-zA-Z0-9]/g, '')}` : + span === 'hour' ? `ChartX${name}` : + span === 'day' ? `ChartDayX${name}` : new Error('not happen') as never, tableName: span === 'hour' ? `__chart__${camelToSnake(name)}` : diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index a639039befb3..97da3a20a589 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -96,9 +96,10 @@ export const miRepository = { return queryBuilder.expressionMap.insertColumns; }, async insertOne(entity, findOptions?) { - const queryBuilder = this.createQueryBuilder().insert().values(entity).returning('*'); + const queryBuilder = this.createQueryBuilder().insert().values(entity); queryBuilder.expressionMap.mainAlias!.name = 't'; - const columnNames = this.createTableColumnNames(queryBuilder); + const columnNames = this.createTableColumnNames(queryBuilder).map(column => `__disambiguation__${column}`); + queryBuilder.returning(columnNames.map(column => `"${column.slice('__disambiguation__'.length)}" AS "${column}"`).join()); const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); builder.expressionMap.mainAlias!.tablePath = 'cte'; this.selectAliasColumnNames(queryBuilder, builder); @@ -114,7 +115,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`); + selectOrAddSelect(`"${builder.alias}"."__disambiguation__${columnName}"`, `"${builder.alias}_${columnName}"`); } }, } satisfies MiRepository; From be8ea15983cf9be0fd53b26fa6a20b317721f278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Wed, 29 May 2024 22:38:38 +0900 Subject: [PATCH 28/62] fix(backend): quote --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 97da3a20a589..c0ee43414714 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -115,7 +115,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(`"${builder.alias}"."__disambiguation__${columnName}"`, `"${builder.alias}_${columnName}"`); + selectOrAddSelect(`"${builder.alias}"."__disambiguation__${columnName}"`, `${builder.alias}_${columnName}`); } }, } satisfies MiRepository; From 7adcccba33686c3af8de78aba95b021eb212534c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 11:08:40 +0900 Subject: [PATCH 29/62] chore: log more --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index c0ee43414714..935c22b4ede9 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -103,7 +103,7 @@ export const miRepository = { const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); builder.expressionMap.mainAlias!.tablePath = 'cte'; this.selectAliasColumnNames(queryBuilder, builder); - console.log(builder.expressionMap.aliases, builder.getQueryAndParameters()); + console.log(builder.expressionMap, builder.getQueryAndParameters()); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From ccba76026f4730eb24f9418dd9c54f517279ff5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 11:16:19 +0900 Subject: [PATCH 30/62] chore: log metadata --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 935c22b4ede9..c78eef30ab4c 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -103,7 +103,7 @@ export const miRepository = { const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); builder.expressionMap.mainAlias!.tablePath = 'cte'; this.selectAliasColumnNames(queryBuilder, builder); - console.log(builder.expressionMap, builder.getQueryAndParameters()); + console.log(builder.expressionMap.mainAlias!.metadata, builder.getQueryAndParameters()); if (findOptions) { return await builder.setFindOptions(findOptions).getOneOrFail(); } From e2b82f7eaabfb872ce0acd8edebe2b4332a5ed69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 11:28:42 +0900 Subject: [PATCH 31/62] chore(backend): use raw --- packages/backend/src/models/_.ts | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index c78eef30ab4c..f98a00a3138f 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -98,16 +98,17 @@ export const miRepository = { async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity); queryBuilder.expressionMap.mainAlias!.name = 't'; - const columnNames = this.createTableColumnNames(queryBuilder).map(column => `__disambiguation__${column}`); - queryBuilder.returning(columnNames.map(column => `"${column.slice('__disambiguation__'.length)}" AS "${column}"`).join()); + const columnNames = this.createTableColumnNames(queryBuilder); + queryBuilder.returning(columnNames.join()); const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); builder.expressionMap.mainAlias!.tablePath = 'cte'; this.selectAliasColumnNames(queryBuilder, builder); - console.log(builder.expressionMap.mainAlias!.metadata, builder.getQueryAndParameters()); if (findOptions) { - return await builder.setFindOptions(findOptions).getOneOrFail(); + builder.setFindOptions(findOptions); } - return await builder.getOneOrFail(); + const raw = await builder.execute(); + console.log(raw); + return raw; }, selectAliasColumnNames(queryBuilder, builder) { let selectOrAddSelect = (selection: string, selectionAliasName?: string) => { @@ -115,7 +116,7 @@ export const miRepository = { return builder.select(selection, selectionAliasName); }; for (const columnName of this.createTableColumnNames(queryBuilder)) { - selectOrAddSelect(`"${builder.alias}"."__disambiguation__${columnName}"`, `${builder.alias}_${columnName}`); + selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`); } }, } satisfies MiRepository; From ae29e6feaca9fe11d44ec76c1e4428e76a877708 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 11:34:53 +0900 Subject: [PATCH 32/62] fix(backend): returning column name --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index f98a00a3138f..344e84ece380 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -99,7 +99,7 @@ export const miRepository = { const queryBuilder = this.createQueryBuilder().insert().values(entity); queryBuilder.expressionMap.mainAlias!.name = 't'; const columnNames = this.createTableColumnNames(queryBuilder); - queryBuilder.returning(columnNames.join()); + queryBuilder.returning(columnNames.reduce((a, c) => `${a}, ${queryBuilder.escape(c)}`, '').slice(2)); const builder = this.createQueryBuilder().addCommonTableExpression(queryBuilder, 'cte', { columnNames }); builder.expressionMap.mainAlias!.tablePath = 'cte'; this.selectAliasColumnNames(queryBuilder, builder); From 08583df144db6ecb964723272c23db94772e7a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 11:47:45 +0900 Subject: [PATCH 33/62] fix(backend): transform --- packages/backend/src/models/_.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 344e84ece380..4550c02bee64 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -4,6 +4,9 @@ */ import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository, SelectQueryBuilder } from 'typeorm'; +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 { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; @@ -107,8 +110,11 @@ export const miRepository = { builder.setFindOptions(findOptions); } const raw = await builder.execute(); - console.log(raw); - return raw; + 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(queryBuilder.expressionMap, queryBuilder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, queryBuilder.expressionMap.mainAlias!); + console.log(raw, relationId, relationCount, result); + return result; }, selectAliasColumnNames(queryBuilder, builder) { let selectOrAddSelect = (selection: string, selectionAliasName?: string) => { From 9d73ccab348d978841510197ec539fef162f5f99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 11:51:22 +0900 Subject: [PATCH 34/62] build(backend): wanna logging --- packages/backend/src/models/_.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 4550c02bee64..eb0b58e8d69b 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -114,6 +114,7 @@ export const miRepository = { const relationCount = await new RelationCountLoader(builder.connection, this.queryRunner, builder.expressionMap.relationCountAttributes).load(raw); const result = new RawSqlResultsToEntityTransformer(queryBuilder.expressionMap, queryBuilder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, queryBuilder.expressionMap.mainAlias!); console.log(raw, relationId, relationCount, result); + throw null; return result; }, selectAliasColumnNames(queryBuilder, builder) { From 559d92f16ddbd391f21e1efde6811afea3381c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 11:58:57 +0900 Subject: [PATCH 35/62] build(backend): transform empty --- packages/backend/src/models/_.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index eb0b58e8d69b..1ed43ed09bef 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -113,9 +113,8 @@ export const miRepository = { 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(queryBuilder.expressionMap, queryBuilder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, queryBuilder.expressionMap.mainAlias!); - console.log(raw, relationId, relationCount, result); + console.log(raw, relationId, relationCount, result, queryBuilder.expressionMap.mainAlias!.metadata.columns); throw null; - return result; }, selectAliasColumnNames(queryBuilder, builder) { let selectOrAddSelect = (selection: string, selectionAliasName?: string) => { From 8dac28ba8091c4720e84cdd54bf9e797db1633a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 12:10:25 +0900 Subject: [PATCH 36/62] build(backend): build alias --- packages/backend/src/models/_.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 1ed43ed09bef..d3d8ca62ff02 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -4,6 +4,7 @@ */ import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository, SelectQueryBuilder } 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'; @@ -113,7 +114,7 @@ export const miRepository = { 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(queryBuilder.expressionMap, queryBuilder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, queryBuilder.expressionMap.mainAlias!); - console.log(raw, relationId, relationCount, result, queryBuilder.expressionMap.mainAlias!.metadata.columns); + console.log(raw, relationId, relationCount, result, queryBuilder.expressionMap.mainAlias!.metadata.primaryColumns.map((column) => DriverUtils.buildAlias(queryBuilder.connection.driver, undefined, queryBuilder.expressionMap.mainAlias!.name, column.databaseName))); throw null; }, selectAliasColumnNames(queryBuilder, builder) { From dbd25edd1689b89c3eb4ef3a6eae2764df893962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 12:13:40 +0900 Subject: [PATCH 37/62] build(backend): restore name --- packages/backend/src/models/_.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index d3d8ca62ff02..ad92f537a542 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -101,6 +101,7 @@ export const miRepository = { }, async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity); + const name = queryBuilder.expressionMap.mainAlias!.name; queryBuilder.expressionMap.mainAlias!.name = 't'; const columnNames = this.createTableColumnNames(queryBuilder); queryBuilder.returning(columnNames.reduce((a, c) => `${a}, ${queryBuilder.escape(c)}`, '').slice(2)); @@ -111,6 +112,7 @@ export const miRepository = { builder.setFindOptions(findOptions); } const raw = await builder.execute(); + queryBuilder.expressionMap.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(queryBuilder.expressionMap, queryBuilder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, queryBuilder.expressionMap.mainAlias!); From 7a2171d6ed221e1b0f7ce542a9d776499fbf95f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 12:45:03 +0900 Subject: [PATCH 38/62] chore: return entity --- packages/backend/src/models/_.ts | 15 +++++++----- packages/backend/test/e2e/reversi-game.ts | 28 +++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) create mode 100644 packages/backend/test/e2e/reversi-game.ts diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index ad92f537a542..2040f3cff838 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -101,23 +101,26 @@ export const miRepository = { }, async insertOne(entity, findOptions?) { const queryBuilder = this.createQueryBuilder().insert().values(entity); - const name = queryBuilder.expressionMap.mainAlias!.name; - queryBuilder.expressionMap.mainAlias!.name = 't'; + // 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.createTableColumnNames(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(); - queryBuilder.expressionMap.mainAlias!.name = name; + 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(queryBuilder.expressionMap, queryBuilder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, queryBuilder.expressionMap.mainAlias!); - console.log(raw, relationId, relationCount, result, queryBuilder.expressionMap.mainAlias!.metadata.primaryColumns.map((column) => DriverUtils.buildAlias(queryBuilder.connection.driver, undefined, queryBuilder.expressionMap.mainAlias!.name, column.databaseName))); - throw null; + const result = new RawSqlResultsToEntityTransformer(queryBuilder.expressionMap, queryBuilder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, mainAlias); + console.log(raw, relationId, relationCount, result, mainAlias.metadata.primaryColumns.map((column) => DriverUtils.buildAlias(queryBuilder.connection.driver, undefined, mainAlias.name, column.databaseName))); + return result[0]; }, selectAliasColumnNames(queryBuilder, builder) { let selectOrAddSelect = (selection: string, selectionAliasName?: string) => { diff --git a/packages/backend/test/e2e/reversi-game.ts b/packages/backend/test/e2e/reversi-game.ts new file mode 100644 index 000000000000..d9a3de94a194 --- /dev/null +++ b/packages/backend/test/e2e/reversi-game.ts @@ -0,0 +1,28 @@ +/* + * 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', async () => { + const response: { body: ReversiMatchResponse } = await api('reversi/match', { userId: bob.id }, alice); + + assert.strictEqual(response.body.user1.id, alice.id); + assert.strictEqual(response.body.user2.id, bob.id); + }); +}); From 8be78e8da628f2f3269d0f2fd1ef6d0d73814673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 13:01:44 +0900 Subject: [PATCH 39/62] fix: test case --- packages/backend/test/e2e/reversi-game.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/backend/test/e2e/reversi-game.ts b/packages/backend/test/e2e/reversi-game.ts index d9a3de94a194..9f264b7045c2 100644 --- a/packages/backend/test/e2e/reversi-game.ts +++ b/packages/backend/test/e2e/reversi-game.ts @@ -19,10 +19,15 @@ describe('ReversiGame', () => { bob = await signup({ username: 'bob' }); }, 1000 * 60 * 2); - test('matches when alice invites bob', async () => { - const response: { body: ReversiMatchResponse } = await api('reversi/match', { userId: bob.id }, alice); - - assert.strictEqual(response.body.user1.id, alice.id); - assert.strictEqual(response.body.user2.id, bob.id); + test('matches when alice invites bob and bob accepts', async () => { + const response1 = await api('reversi/match', { userId: bob.id }, alice); + assert.strictEqual(response1.status, 200); + 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); }); }); From 63de85e7c5ed6950b41d913ee677d04506fcebc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 13:10:07 +0900 Subject: [PATCH 40/62] test(backend): 204 --- packages/backend/test/e2e/reversi-game.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/test/e2e/reversi-game.ts b/packages/backend/test/e2e/reversi-game.ts index 9f264b7045c2..788255beac12 100644 --- a/packages/backend/test/e2e/reversi-game.ts +++ b/packages/backend/test/e2e/reversi-game.ts @@ -21,7 +21,7 @@ describe('ReversiGame', () => { test('matches when alice invites bob and bob accepts', async () => { const response1 = await api('reversi/match', { userId: bob.id }, alice); - assert.strictEqual(response1.status, 200); + 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); From 04792b501ed37207685b18801a75aeac6a833e6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 13:26:34 +0900 Subject: [PATCH 41/62] chore(backend): log sql --- packages/backend/src/models/_.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 2040f3cff838..92ca6f78e748 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -114,6 +114,7 @@ export const miRepository = { if (findOptions) { builder.setFindOptions(findOptions); } + console.log(builder.getQueryAndParameters()); const raw = await builder.execute(); mainAlias.name = name; const relationId = await new RelationIdLoader(builder.connection, this.queryRunner, builder.expressionMap.relationIdAttributes).load(raw); From b969821019acc209a533aae6cf9e8815b27e9988 Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Thu, 30 May 2024 13:41:57 +0900 Subject: [PATCH 42/62] chore(backend): assert user joined --- packages/backend/src/core/ReversiService.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts index 7f939b99c7a6..50d50b270dea 100644 --- a/packages/backend/src/core/ReversiService.ts +++ b/packages/backend/src/core/ReversiService.ts @@ -295,6 +295,9 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit { isLlotheo: false, noIrregularRules: options.noIrregularRules, }, { relations: ['user1', 'user2'] }); + if (game.user1 === gane.user2) { + throw new Error('broken match'); + } this.cacheGame(game); const packed = await this.reversiGameEntityService.packDetail(game); From 9c78aacb87347f9c4a65b6fdbdafe7c341302522 Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Thu, 30 May 2024 13:42:34 +0900 Subject: [PATCH 43/62] fix(backend): typo --- packages/backend/src/core/ReversiService.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts index 50d50b270dea..e863f5f5e30a 100644 --- a/packages/backend/src/core/ReversiService.ts +++ b/packages/backend/src/core/ReversiService.ts @@ -295,7 +295,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit { isLlotheo: false, noIrregularRules: options.noIrregularRules, }, { relations: ['user1', 'user2'] }); - if (game.user1 === gane.user2) { + if (game.user1 === game.user2) { throw new Error('broken match'); } this.cacheGame(game); From 3c22d638d4def98b8f64a586648838a1f6c611a6 Mon Sep 17 00:00:00 2001 From: Acid Chicken Date: Thu, 30 May 2024 13:55:38 +0900 Subject: [PATCH 44/62] chore(backend): log long sql --- packages/backend/src/models/_.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 92ca6f78e748..0bc7ebb8572a 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -114,7 +114,11 @@ export const miRepository = { if (findOptions) { builder.setFindOptions(findOptions); } - console.log(builder.getQueryAndParameters()); + const [query, parameters] = builder.getQueryAndParameters(); + for (let i = 0; i < Math.ceil(query.length / 10000); i++) { + console.log(query.slice(i * 10000, i * 10000 + 10000)); + } + console.log(parameters); const raw = await builder.execute(); mainAlias.name = name; const relationId = await new RelationIdLoader(builder.connection, this.queryRunner, builder.expressionMap.relationIdAttributes).load(raw); From b044db9d45e8443d8feb44d2a12e115ff4bfb749 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 14:42:25 +0900 Subject: [PATCH 45/62] chore(backend): log join --- packages/backend/src/models/_.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 0bc7ebb8572a..b02273d0aa96 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -113,6 +113,9 @@ export const miRepository = { this.selectAliasColumnNames(queryBuilder, builder); if (findOptions) { builder.setFindOptions(findOptions); + // @ts-expect-error -- protected + const joins = builder.joins; + console.log(joins); } const [query, parameters] = builder.getQueryAndParameters(); for (let i = 0; i < Math.ceil(query.length / 10000); i++) { From f50cd8c410baed26328b9179137f9a17af67144e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 14:54:46 +0900 Subject: [PATCH 46/62] chore(backend): log join depth null --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index b02273d0aa96..89b5c851d4cd 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -115,7 +115,7 @@ export const miRepository = { builder.setFindOptions(findOptions); // @ts-expect-error -- protected const joins = builder.joins; - console.log(joins); + console.dir(joins, { depth: null }); } const [query, parameters] = builder.getQueryAndParameters(); for (let i = 0; i < Math.ceil(query.length / 10000); i++) { From 907fc5a4621bf488a2e907cf878be71065044ad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 16:22:44 +0900 Subject: [PATCH 47/62] chore(backend): joinAttributes --- packages/backend/src/models/_.ts | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 89b5c851d4cd..b6b969660359 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -8,6 +8,7 @@ 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 { OrmUtils } from 'typeorm/util/OrmUtils.js'; import { MiAbuseUserReport } from '@/models/AbuseUserReport.js'; import { MiAccessToken } from '@/models/AccessToken.js'; import { MiAd } from '@/models/Ad.js'; @@ -113,9 +114,19 @@ export const miRepository = { this.selectAliasColumnNames(queryBuilder, builder); if (findOptions) { builder.setFindOptions(findOptions); + /* // @ts-expect-error -- protected - const joins = builder.joins; - console.dir(joins, { depth: null }); + builder.findOptions = findOptions; + if (findOptions.relations) { + const relations = Array.isArray(findOptions.relations) ? OrmUtils.propertyPathsToTruthyObject(findOptions.relations) : findOptions.relations; + // @ts-expect-error -- protected + builder.buildRelations(relations, undefined, mainAlias.metadata, mainAlias.name); + } + // @ts-expect-error -- protected + for (const join of builder.joins) { + } + */ + console.log(builder.expressionMap.joinAttributes); } const [query, parameters] = builder.getQueryAndParameters(); for (let i = 0; i < Math.ceil(query.length / 10000); i++) { From cbc806e61d30d02986ff244982405642c69dec2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Thu, 30 May 2024 17:09:46 +0900 Subject: [PATCH 48/62] chore(backend): override createJoinExpression --- packages/backend/src/models/_.ts | 68 ++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 13 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index b6b969660359..7093c2556fb9 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -3,7 +3,7 @@ * SPDX-License-Identifier: AGPL-3.0-only */ -import { FindOneOptions, InsertQueryBuilder, ObjectLiteral, Repository, SelectQueryBuilder } from 'typeorm'; +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'; @@ -114,19 +114,61 @@ export const miRepository = { this.selectAliasColumnNames(queryBuilder, builder); if (findOptions) { builder.setFindOptions(findOptions); - /* // @ts-expect-error -- protected - builder.findOptions = findOptions; - if (findOptions.relations) { - const relations = Array.isArray(findOptions.relations) ? OrmUtils.propertyPathsToTruthyObject(findOptions.relations) : findOptions.relations; - // @ts-expect-error -- protected - builder.buildRelations(relations, undefined, mainAlias.metadata, mainAlias.name); - } - // @ts-expect-error -- protected - for (const join of builder.joins) { - } - */ - console.log(builder.expressionMap.joinAttributes); + builder.createJoinExpression = function(this: SelectQueryBuilder) { + const joins = this.expressionMap.joinAttributes.map((joinAttr) => { + /* eslint-disable @typescript-eslint/no-non-null-assertion */ + const relation = joinAttr.relation!; + const destinationTableName = joinAttr.tablePath; + const destinationTableAlias = joinAttr.alias.name; + let appendedCondition = joinAttr.condition ? ` AND (${joinAttr.condition})` : ''; + const parentAlias = joinAttr.parentAlias; + if (relation.isManyToOne || relation.isOneToOneOwner) { + // JOIN `category` `category` ON `category`.`id` = `post`.`categoryId` + const condition = relation.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${relation.propertyPath}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); + return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ + // @ts-expect-error -- private + this.createTableLockExpression() + } ON ${this.replacePropertyNames(condition + appendedCondition)}`; + } else if (relation.isOneToMany || relation.isOneToOneNotOwner) { + // JOIN `post` `post` ON `post`.`categoryId` = `category`.`id` + const condition = relation.inverseRelation!.joinColumns.map((joinColumn) => { + if (relation.inverseEntityMetadata.tableType === 'entity-child' && relation.inverseEntityMetadata.discriminatorColumn) { + appendedCondition += ` AND ${destinationTableAlias}.${relation.inverseEntityMetadata.discriminatorColumn.databaseName}='${relation.inverseEntityMetadata.discriminatorValue}'`; + } + return `${destinationTableAlias}.${relation.inverseRelation!.propertyPath}.${joinColumn.referencedColumn!.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`; + }).join(' AND '); + if (!condition) { + throw new TypeORMError(`Relation ${relation.entityMetadata.name}.${relation.propertyName} does not have join columns.`); + } + return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ + // @ts-expect-error -- private + this.createTableLockExpression() + } ON ${this.replacePropertyNames(condition + appendedCondition)}`; + } else { + // means many-to-many + const junctionTableName = relation.junctionEntityMetadata!.tablePath; + const junctionAlias = joinAttr.junctionAlias; + let junctionCondition = '', destinationCondition = ''; + if (relation.isOwning) { + junctionCondition = relation.joinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); + destinationCondition = relation.inverseJoinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${junctionAlias}_${joinColumn.propertyPath}`).join(' AND '); + } else { + junctionCondition = relation.inverseRelation!.inverseJoinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); + destinationCondition = relation.inverseRelation!.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${junctionAlias}_${joinColumn.propertyPath}`).join(' AND '); + } + return ` ${joinAttr.direction} JOIN ${this.getTableName(junctionTableName)} ${this.escape(junctionAlias)}${ + // @ts-expect-error -- private + this.createTableLockExpression() + } ON ${this.replacePropertyNames(junctionCondition)} ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ + // @ts-expect-error -- private + this.createTableLockExpression() + } ON ${this.replacePropertyNames(destinationCondition + appendedCondition)}`; + } + /* eslint-enable @typescript-eslint/no-non-null-assertion */ + }); + return joins.join(' '); + }; } const [query, parameters] = builder.getQueryAndParameters(); for (let i = 0; i < Math.ceil(query.length / 10000); i++) { From 9dab282bf743ef7ff901e821af209ced71f2235e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 03:16:27 +0900 Subject: [PATCH 49/62] chore: join log --- packages/backend/src/models/_.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 7093c2556fb9..cf806f07f55f 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -124,14 +124,13 @@ export const miRepository = { let appendedCondition = joinAttr.condition ? ` AND (${joinAttr.condition})` : ''; const parentAlias = joinAttr.parentAlias; if (relation.isManyToOne || relation.isOneToOneOwner) { - // JOIN `category` `category` ON `category`.`id` = `post`.`categoryId` - const condition = relation.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${relation.propertyPath}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); + console.log(relation); + const condition = relation.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${parentAlias}.${relation.propertyPath}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ // @ts-expect-error -- private this.createTableLockExpression() - } ON ${this.replacePropertyNames(condition + appendedCondition)}`; + } ON ${condition}${appendedCondition}`; } else if (relation.isOneToMany || relation.isOneToOneNotOwner) { - // JOIN `post` `post` ON `post`.`categoryId` = `category`.`id` const condition = relation.inverseRelation!.joinColumns.map((joinColumn) => { if (relation.inverseEntityMetadata.tableType === 'entity-child' && relation.inverseEntityMetadata.discriminatorColumn) { appendedCondition += ` AND ${destinationTableAlias}.${relation.inverseEntityMetadata.discriminatorColumn.databaseName}='${relation.inverseEntityMetadata.discriminatorValue}'`; @@ -144,9 +143,8 @@ export const miRepository = { return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ // @ts-expect-error -- private this.createTableLockExpression() - } ON ${this.replacePropertyNames(condition + appendedCondition)}`; + } ON ${condition}${appendedCondition}`; } else { - // means many-to-many const junctionTableName = relation.junctionEntityMetadata!.tablePath; const junctionAlias = joinAttr.junctionAlias; let junctionCondition = '', destinationCondition = ''; @@ -163,7 +161,7 @@ export const miRepository = { } ON ${this.replacePropertyNames(junctionCondition)} ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ // @ts-expect-error -- private this.createTableLockExpression() - } ON ${this.replacePropertyNames(destinationCondition + appendedCondition)}`; + } ON ${destinationCondition}${appendedCondition}`; } /* eslint-enable @typescript-eslint/no-non-null-assertion */ }); From f42d2b9e61f3b367c648492b07e08ba0706fd37c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 13:25:25 +0900 Subject: [PATCH 50/62] fix(backend): escape --- packages/backend/src/models/_.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index cf806f07f55f..56a3cf0f7b54 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -125,7 +125,7 @@ export const miRepository = { const parentAlias = joinAttr.parentAlias; if (relation.isManyToOne || relation.isOneToOneOwner) { console.log(relation); - const condition = relation.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${parentAlias}.${relation.propertyPath}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); + const condition = relation.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}="${parentAlias}_${joinColumn.propertyPath}"`).join(' AND '); return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ // @ts-expect-error -- private this.createTableLockExpression() @@ -135,7 +135,7 @@ export const miRepository = { if (relation.inverseEntityMetadata.tableType === 'entity-child' && relation.inverseEntityMetadata.discriminatorColumn) { appendedCondition += ` AND ${destinationTableAlias}.${relation.inverseEntityMetadata.discriminatorColumn.databaseName}='${relation.inverseEntityMetadata.discriminatorValue}'`; } - return `${destinationTableAlias}.${relation.inverseRelation!.propertyPath}.${joinColumn.referencedColumn!.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`; + return `${destinationTableAlias}.${relation.inverseRelation!.propertyPath}.${joinColumn.referencedColumn!.propertyPath}="${parentAlias}_${joinColumn.propertyPath}"`; }).join(' AND '); if (!condition) { throw new TypeORMError(`Relation ${relation.entityMetadata.name}.${relation.propertyName} does not have join columns.`); @@ -150,15 +150,15 @@ export const miRepository = { let junctionCondition = '', destinationCondition = ''; if (relation.isOwning) { junctionCondition = relation.joinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); - destinationCondition = relation.inverseJoinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${junctionAlias}_${joinColumn.propertyPath}`).join(' AND '); + destinationCondition = relation.inverseJoinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}="${junctionAlias}_${joinColumn.propertyPath}"`).join(' AND '); } else { - junctionCondition = relation.inverseRelation!.inverseJoinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); - destinationCondition = relation.inverseRelation!.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}=${junctionAlias}_${joinColumn.propertyPath}`).join(' AND '); + junctionCondition = relation.inverseRelation!.inverseJoinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}="${parentAlias}_${joinColumn.referencedColumn!.propertyPath}"`).join(' AND '); + destinationCondition = relation.inverseRelation!.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}="${junctionAlias}_${joinColumn.propertyPath}"`).join(' AND '); } return ` ${joinAttr.direction} JOIN ${this.getTableName(junctionTableName)} ${this.escape(junctionAlias)}${ // @ts-expect-error -- private this.createTableLockExpression() - } ON ${this.replacePropertyNames(junctionCondition)} ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ + } ON ${junctionCondition} ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ // @ts-expect-error -- private this.createTableLockExpression() } ON ${destinationCondition}${appendedCondition}`; From 4b26b06cad9694fe430e9ac1ed49f1d3f050bd52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 13:32:36 +0900 Subject: [PATCH 51/62] test(backend): log log --- packages/backend/src/core/chart/core.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts index af5485a46ee9..070de8aadbb3 100644 --- a/packages/backend/src/core/chart/core.ts +++ b/packages/backend/src/core/chart/core.ts @@ -400,6 +400,8 @@ export default abstract class Chart { this.logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): New commit created`); + console.log(log); + return log; } finally { unlock(); From 9d784d965f84a595b3ae4975e5bc31ed287eb742 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 13:37:12 +0900 Subject: [PATCH 52/62] chore(backend): join gonna success? --- packages/backend/src/models/_.ts | 54 +------------------------------- 1 file changed, 1 insertion(+), 53 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 56a3cf0f7b54..418a445952ef 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -114,59 +114,6 @@ export const miRepository = { this.selectAliasColumnNames(queryBuilder, builder); if (findOptions) { builder.setFindOptions(findOptions); - // @ts-expect-error -- protected - builder.createJoinExpression = function(this: SelectQueryBuilder) { - const joins = this.expressionMap.joinAttributes.map((joinAttr) => { - /* eslint-disable @typescript-eslint/no-non-null-assertion */ - const relation = joinAttr.relation!; - const destinationTableName = joinAttr.tablePath; - const destinationTableAlias = joinAttr.alias.name; - let appendedCondition = joinAttr.condition ? ` AND (${joinAttr.condition})` : ''; - const parentAlias = joinAttr.parentAlias; - if (relation.isManyToOne || relation.isOneToOneOwner) { - console.log(relation); - const condition = relation.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}="${parentAlias}_${joinColumn.propertyPath}"`).join(' AND '); - return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ - // @ts-expect-error -- private - this.createTableLockExpression() - } ON ${condition}${appendedCondition}`; - } else if (relation.isOneToMany || relation.isOneToOneNotOwner) { - const condition = relation.inverseRelation!.joinColumns.map((joinColumn) => { - if (relation.inverseEntityMetadata.tableType === 'entity-child' && relation.inverseEntityMetadata.discriminatorColumn) { - appendedCondition += ` AND ${destinationTableAlias}.${relation.inverseEntityMetadata.discriminatorColumn.databaseName}='${relation.inverseEntityMetadata.discriminatorValue}'`; - } - return `${destinationTableAlias}.${relation.inverseRelation!.propertyPath}.${joinColumn.referencedColumn!.propertyPath}="${parentAlias}_${joinColumn.propertyPath}"`; - }).join(' AND '); - if (!condition) { - throw new TypeORMError(`Relation ${relation.entityMetadata.name}.${relation.propertyName} does not have join columns.`); - } - return ` ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ - // @ts-expect-error -- private - this.createTableLockExpression() - } ON ${condition}${appendedCondition}`; - } else { - const junctionTableName = relation.junctionEntityMetadata!.tablePath; - const junctionAlias = joinAttr.junctionAlias; - let junctionCondition = '', destinationCondition = ''; - if (relation.isOwning) { - junctionCondition = relation.joinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}=${parentAlias}_${joinColumn.referencedColumn!.propertyPath}`).join(' AND '); - destinationCondition = relation.inverseJoinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}="${junctionAlias}_${joinColumn.propertyPath}"`).join(' AND '); - } else { - junctionCondition = relation.inverseRelation!.inverseJoinColumns.map((joinColumn) => `${junctionAlias}.${joinColumn.propertyPath}="${parentAlias}_${joinColumn.referencedColumn!.propertyPath}"`).join(' AND '); - destinationCondition = relation.inverseRelation!.joinColumns.map((joinColumn) => `${destinationTableAlias}.${joinColumn.referencedColumn!.propertyPath}="${junctionAlias}_${joinColumn.propertyPath}"`).join(' AND '); - } - return ` ${joinAttr.direction} JOIN ${this.getTableName(junctionTableName)} ${this.escape(junctionAlias)}${ - // @ts-expect-error -- private - this.createTableLockExpression() - } ON ${junctionCondition} ${joinAttr.direction} JOIN ${this.getTableName(destinationTableName)} ${this.escape(destinationTableAlias)}${ - // @ts-expect-error -- private - this.createTableLockExpression() - } ON ${destinationCondition}${appendedCondition}`; - } - /* eslint-enable @typescript-eslint/no-non-null-assertion */ - }); - return joins.join(' '); - }; } const [query, parameters] = builder.getQueryAndParameters(); for (let i = 0; i < Math.ceil(query.length / 10000); i++) { @@ -174,6 +121,7 @@ export const miRepository = { } console.log(parameters); const raw = await builder.execute(); + console.log(raw); 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); From 11d9be1b6bfa7c3faf05d31b222b445c0fbe0b45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 14:43:52 +0900 Subject: [PATCH 53/62] chore(backend): relations --- packages/backend/src/models/_.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 418a445952ef..d9ddc6c98371 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -8,6 +8,7 @@ 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'; @@ -122,11 +123,12 @@ export const miRepository = { console.log(parameters); const raw = await builder.execute(); console.log(raw); + console.log(builder.expressionMap.relationMetadata, builder.expressionMap.relationIdAttributes, builder.expressionMap.relationCountAttributes, builder.expressionMap.relationPropertyPath); 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(queryBuilder.expressionMap, queryBuilder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, mainAlias); - console.log(raw, relationId, relationCount, result, mainAlias.metadata.primaryColumns.map((column) => DriverUtils.buildAlias(queryBuilder.connection.driver, undefined, mainAlias.name, column.databaseName))); + const result = new RawSqlResultsToEntityTransformer(builder.expressionMap, builder.connection.driver, relationId, relationCount, this.queryRunner).transform(raw, mainAlias); + console.log(raw, relationId, relationCount, result, mainAlias.metadata.primaryColumns.map((column) => DriverUtils.buildAlias(builder.connection.driver, undefined, mainAlias.name, column.databaseName))); return result[0]; }, selectAliasColumnNames(queryBuilder, builder) { From c4d8c2232a7285742e59c33b94935559c26a2d89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 14:47:06 +0900 Subject: [PATCH 54/62] chore(backend): undefined --- packages/backend/src/models/_.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index d9ddc6c98371..1a6270c52d23 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -115,6 +115,7 @@ export const miRepository = { this.selectAliasColumnNames(queryBuilder, builder); if (findOptions) { builder.setFindOptions(findOptions); + console.log(builder.expressionMap.relationMetadata, builder.expressionMap.relationIdAttributes, builder.expressionMap.relationCountAttributes, builder.expressionMap.relationPropertyPath); } const [query, parameters] = builder.getQueryAndParameters(); for (let i = 0; i < Math.ceil(query.length / 10000); i++) { @@ -123,7 +124,6 @@ export const miRepository = { console.log(parameters); const raw = await builder.execute(); console.log(raw); - console.log(builder.expressionMap.relationMetadata, builder.expressionMap.relationIdAttributes, builder.expressionMap.relationCountAttributes, builder.expressionMap.relationPropertyPath); 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); From 0be3f56a1613575c92ae8a4aa1d8fbd6bc433714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 18:15:37 +0900 Subject: [PATCH 55/62] chore(backend): target --- packages/backend/src/models/_.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 1a6270c52d23..60f47f9f029e 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -115,13 +115,13 @@ export const miRepository = { this.selectAliasColumnNames(queryBuilder, builder); if (findOptions) { builder.setFindOptions(findOptions); - console.log(builder.expressionMap.relationMetadata, builder.expressionMap.relationIdAttributes, builder.expressionMap.relationCountAttributes, builder.expressionMap.relationPropertyPath); - } - const [query, parameters] = builder.getQueryAndParameters(); - for (let i = 0; i < Math.ceil(query.length / 10000); i++) { - console.log(query.slice(i * 10000, i * 10000 + 10000)); + console.log(builder.expressionMap.relationIdAttributes, builder.expressionMap.relationCountAttributes, builder.expressionMap.relationPropertyPath); + const [query, parameters] = builder.getQueryAndParameters(); + for (let i = 0; i < Math.ceil(query.length / 10000); i++) { + console.log(query.slice(i * 10000, i * 10000 + 10000)); + } + console.log(parameters); } - console.log(parameters); const raw = await builder.execute(); console.log(raw); mainAlias.name = name; From 52cd2bb2f9af2604dc1e606e9518bd160c3048e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 18:24:24 +0900 Subject: [PATCH 56/62] chore(backend): remove log --- packages/backend/src/models/_.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 60f47f9f029e..11bc586c2067 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -115,20 +115,12 @@ export const miRepository = { this.selectAliasColumnNames(queryBuilder, builder); if (findOptions) { builder.setFindOptions(findOptions); - console.log(builder.expressionMap.relationIdAttributes, builder.expressionMap.relationCountAttributes, builder.expressionMap.relationPropertyPath); - const [query, parameters] = builder.getQueryAndParameters(); - for (let i = 0; i < Math.ceil(query.length / 10000); i++) { - console.log(query.slice(i * 10000, i * 10000 + 10000)); - } - console.log(parameters); } const raw = await builder.execute(); - console.log(raw); 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); - console.log(raw, relationId, relationCount, result, mainAlias.metadata.primaryColumns.map((column) => DriverUtils.buildAlias(builder.connection.driver, undefined, mainAlias.name, column.databaseName))); return result[0]; }, selectAliasColumnNames(queryBuilder, builder) { From bbed86162fd88f53616834542d2a8d1adbea9999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 18:33:28 +0900 Subject: [PATCH 57/62] chore(backend): log chart update --- packages/backend/src/core/chart/core.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts index 070de8aadbb3..ec50135e1673 100644 --- a/packages/backend/src/core/chart/core.ts +++ b/packages/backend/src/core/chart/core.ts @@ -431,6 +431,7 @@ export default abstract class Chart { // これを回避するための実装は複雑になりそうなため、一旦保留。 const update = async (logHour: RawRecord, logDay: RawRecord): Promise => { + console.log(logHour, logDay); const finalDiffs = {} as Record; for (const diff of this.buffer.filter(q => q.group == null || (q.group === logHour.group)).map(q => q.diff)) { From 7a219c0bedea199a51825fb49a77ec5153631b73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 19:15:14 +0900 Subject: [PATCH 58/62] chore(backend): log columns --- packages/backend/src/models/_.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 11bc586c2067..9d7dcb525fc3 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -117,6 +117,7 @@ export const miRepository = { builder.setFindOptions(findOptions); } const raw = await builder.execute(); + console.log(columnNames, builder.getQueryAndParameters(), raw); 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); From 6a765db92579978eedb11e99abf10cefdb4aa73b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 19:23:46 +0900 Subject: [PATCH 59/62] chore(backend): check hasMetadata --- packages/backend/src/models/_.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 9d7dcb525fc3..cd07d0f2b035 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -87,6 +87,7 @@ export interface MiRepository { export const miRepository = { createTableColumnNames(queryBuilder) { + console.log(queryBuilder.expressionMap.mainAlias?.hasMetadata); // @ts-expect-error -- protected const insertedColumns = queryBuilder.getInsertedColumns(); if (insertedColumns.length) { From 882e65e4868fac07378cf7c4259a7b671fe29bc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 19:59:48 +0900 Subject: [PATCH 60/62] chore(backend): unshift id when not included --- packages/backend/src/models/_.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index cd07d0f2b035..64d0d862965e 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -87,7 +87,6 @@ export interface MiRepository { export const miRepository = { createTableColumnNames(queryBuilder) { - console.log(queryBuilder.expressionMap.mainAlias?.hasMetadata); // @ts-expect-error -- protected const insertedColumns = queryBuilder.getInsertedColumns(); if (insertedColumns.length) { @@ -109,6 +108,9 @@ export const miRepository = { const name = mainAlias.name; mainAlias.name = 't'; const columnNames = this.createTableColumnNames(queryBuilder); + if (!columnNames.includes('id')) { + columnNames.unshift('id'); + } 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 From b759732349f77c29e54d8e296bbc1fc6f65f9942 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 20:09:08 +0900 Subject: [PATCH 61/62] chore(backend): missing select --- packages/backend/src/models/_.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 64d0d862965e..0b8a40a23d53 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -81,6 +81,7 @@ import type { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialE export interface MiRepository { createTableColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; + createTableColumnNamesWithPrimaryKey(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder): string[]; insertOne(this: Repository & MiRepository, entity: QueryDeepPartialEntity, findOptions?: Pick, 'relations'>): Promise; selectAliasColumnNames(this: Repository & MiRepository, queryBuilder: InsertQueryBuilder, builder: SelectQueryBuilder): void; } @@ -101,16 +102,20 @@ export const miRepository = { } 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.createTableColumnNames(queryBuilder); - if (!columnNames.includes('id')) { - columnNames.unshift('id'); - } + 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 @@ -132,7 +137,7 @@ export const miRepository = { selectOrAddSelect = (selection, selectionAliasName) => builder.addSelect(selection, selectionAliasName); return builder.select(selection, selectionAliasName); }; - for (const columnName of this.createTableColumnNames(queryBuilder)) { + for (const columnName of this.createTableColumnNamesWithPrimaryKey(queryBuilder)) { selectOrAddSelect(`${builder.alias}.${columnName}`, `${builder.alias}_${columnName}`); } }, From 120b60cb0577267fba789e17484cbcaf415e6eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Acid=20Chicken=20=28=E7=A1=AB=E9=85=B8=E9=B6=8F=29?= Date: Fri, 31 May 2024 20:16:28 +0900 Subject: [PATCH 62/62] chore(backend): remove debug code --- packages/backend/src/core/ReversiService.ts | 3 --- packages/backend/src/core/chart/core.ts | 3 --- packages/backend/src/models/_.ts | 1 - 3 files changed, 7 deletions(-) diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts index e863f5f5e30a..7f939b99c7a6 100644 --- a/packages/backend/src/core/ReversiService.ts +++ b/packages/backend/src/core/ReversiService.ts @@ -295,9 +295,6 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit { isLlotheo: false, noIrregularRules: options.noIrregularRules, }, { relations: ['user1', 'user2'] }); - if (game.user1 === game.user2) { - throw new Error('broken match'); - } this.cacheGame(game); const packed = await this.reversiGameEntityService.packDetail(game); diff --git a/packages/backend/src/core/chart/core.ts b/packages/backend/src/core/chart/core.ts index ec50135e1673..af5485a46ee9 100644 --- a/packages/backend/src/core/chart/core.ts +++ b/packages/backend/src/core/chart/core.ts @@ -400,8 +400,6 @@ export default abstract class Chart { this.logger.info(`${this.name + (group ? `:${group}` : '')}(${span}): New commit created`); - console.log(log); - return log; } finally { unlock(); @@ -431,7 +429,6 @@ export default abstract class Chart { // これを回避するための実装は複雑になりそうなため、一旦保留。 const update = async (logHour: RawRecord, logDay: RawRecord): Promise => { - console.log(logHour, logDay); const finalDiffs = {} as Record; for (const diff of this.buffer.filter(q => q.group == null || (q.group === logHour.group)).map(q => q.diff)) { diff --git a/packages/backend/src/models/_.ts b/packages/backend/src/models/_.ts index 0b8a40a23d53..2e6a41586e45 100644 --- a/packages/backend/src/models/_.ts +++ b/packages/backend/src/models/_.ts @@ -125,7 +125,6 @@ export const miRepository = { builder.setFindOptions(findOptions); } const raw = await builder.execute(); - console.log(columnNames, builder.getQueryAndParameters(), raw); 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);