From dbdb0df0a914308c109c58015ff8ab24c8318b8e Mon Sep 17 00:00:00 2001 From: tamaina Date: Wed, 22 Sep 2021 22:35:55 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20PackedHoge=E5=9E=8B=E3=82=92Packed=E5=9E=8B=E3=81=AB=E6=9B=B8=E3=81=8D=E6=8F=9B=E3=81=88?= =?UTF-8?q?=E3=82=8B=20(#7792)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * packedNotificationSchemaを更新 * read:gallery, write:gallery, read:gallery-likes, write:gallery-likesに翻訳を追加 * fix * add header, choice, invitation * test * fix * yatta * remove no longer needed "as PackedUser/PackedNote" * clean up * add simple-schema * fix lint * define items in full Schema * revert https://github.com/misskey-dev/misskey/pull/7772#discussion_r706627736 * user packとnote packの型不整合を修正 * add prelude/types.ts * emoji * signin * game * matching * fix * add emoji schema * add reversiGame * add reversiMatching * remove signin schema (use Signin entity) * add Packed type * note-reaction * user * user-group * user-list * note * app, messaging-message * notification * drive-file * drive-folder * following * muting * blocking * hashtag * page * app (with modifying schema) * import user? * channel * antenna * clip * gallery-post * emoji * Packed * reversi-matching * add changelog * add changelog * revert fix --- CHANGELOG.md | 2 + src/misc/check-hit-antenna.ts | 4 +- src/misc/schema.ts | 10 +- src/models/repositories/antenna.ts | 6 +- src/models/repositories/app.ts | 15 +- src/models/repositories/blocking.ts | 6 +- src/models/repositories/channel.ts | 6 +- src/models/repositories/clip.ts | 6 +- src/models/repositories/drive-file.ts | 10 +- src/models/repositories/drive-folder.ts | 6 +- src/models/repositories/emoji.ts | 41 ++++- src/models/repositories/following.ts | 6 +- src/models/repositories/gallery-post.ts | 6 +- src/models/repositories/games/reversi/game.ts | 150 +++++++++++++++++- .../repositories/games/reversi/matching.ts | 45 +++++- src/models/repositories/hashtag.ts | 6 +- src/models/repositories/messaging-message.ts | 6 +- src/models/repositories/muting.ts | 6 +- src/models/repositories/note-reaction.ts | 6 +- src/models/repositories/note.ts | 8 +- src/models/repositories/notification.ts | 6 +- src/models/repositories/page.ts | 6 +- src/models/repositories/user-group.ts | 6 +- src/models/repositories/user-list.ts | 6 +- src/models/repositories/user.ts | 6 +- src/server/api/stream/channels/channel.ts | 4 +- .../api/stream/channels/global-timeline.ts | 4 +- src/server/api/stream/channels/hashtag.ts | 4 +- .../api/stream/channels/home-timeline.ts | 4 +- .../api/stream/channels/hybrid-timeline.ts | 4 +- .../api/stream/channels/local-timeline.ts | 4 +- src/server/api/stream/channels/user-list.ts | 4 +- src/server/api/stream/index.ts | 8 +- src/services/note/read.ts | 12 +- src/services/push-notification.ts | 5 +- 35 files changed, 312 insertions(+), 122 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a0e75404..8ad00eeca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ - UIの改善 - MFMにsparklesエフェクトを追加 - 非ログイン自は更新ダイアログを出さないように +- refactor: PackedHoge型をPacked<'Hoge'>型に書き換える +- refactor: スキーマのないpack関数にスキーマを定義 ### Bugfixes - アカウントデータのエクスポート/インポート処理ができない問題を修正 diff --git a/src/misc/check-hit-antenna.ts b/src/misc/check-hit-antenna.ts index 38965f4b0..3789054b2 100644 --- a/src/misc/check-hit-antenna.ts +++ b/src/misc/check-hit-antenna.ts @@ -3,13 +3,13 @@ import { Note } from '@/models/entities/note'; import { User } from '@/models/entities/user'; import { UserListJoinings, UserGroupJoinings } from '@/models/index'; import { getFullApAccount } from './convert-host'; -import { PackedNote } from '../models/repositories/note'; import { parseAcct } from '@/misc/acct'; +import { Packed } from './schema'; /** * noteUserFollowers / antennaUserFollowing はどちらか一方が指定されていればよい */ -export async function checkHitAntenna(antenna: Antenna, note: (Note | PackedNote), noteUser: { username: string; host: string | null; }, noteUserFollowers?: User['id'][], antennaUserFollowing?: User['id'][]): Promise { +export async function checkHitAntenna(antenna: Antenna, note: (Note | Packed<'Note'>), noteUser: { username: string; host: string | null; }, noteUserFollowers?: User['id'][], antennaUserFollowing?: User['id'][]): Promise { if (note.visibility === 'specified') return false; if (note.visibility === 'followers') { diff --git a/src/misc/schema.ts b/src/misc/schema.ts index d27c9eff9..4131875ef 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -21,6 +21,9 @@ import { packedClipSchema } from '@/models/repositories/clip'; import { packedFederationInstanceSchema } from '@/models/repositories/federation-instance'; import { packedQueueCountSchema } from '@/models/repositories/queue'; import { packedGalleryPostSchema } from '@/models/repositories/gallery-post'; +import { packedEmojiSchema } from '@/models/repositories/emoji'; +import { packedReversiGameSchema } from '@/models/repositories/games/reversi/game'; +import { packedReversiMatchingSchema } from '@/models/repositories/games/reversi/matching'; export const refs = { User: packedUserSchema, @@ -45,8 +48,13 @@ export const refs = { Clip: packedClipSchema, FederationInstance: packedFederationInstanceSchema, GalleryPost: packedGalleryPostSchema, + Emoji: packedEmojiSchema, + ReversiGame: packedReversiGameSchema, + ReversiMatching: packedReversiMatchingSchema, }; +export type Packed = ObjType<(typeof refs[x])['properties']>; + export interface Schema extends SimpleSchema { items?: Schema; properties?: Obj; @@ -92,7 +100,7 @@ export type SchemaType

= p['type'] extends 'array' ? NullOrUndefined>[]> : p['type'] extends 'object' ? ( p['ref'] extends keyof typeof refs - ? NullOrUndefined> + ? NullOrUndefined> : NullOrUndefined>> ) : p['type'] extends 'any' ? NullOrUndefined : diff --git a/src/models/repositories/antenna.ts b/src/models/repositories/antenna.ts index e61eed5e0..657de5558 100644 --- a/src/models/repositories/antenna.ts +++ b/src/models/repositories/antenna.ts @@ -1,15 +1,13 @@ import { EntityRepository, Repository } from 'typeorm'; import { Antenna } from '@/models/entities/antenna'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { AntennaNotes, UserGroupJoinings } from '../index'; -export type PackedAntenna = SchemaType; - @EntityRepository(Antenna) export class AntennaRepository extends Repository { public async pack( src: Antenna['id'] | Antenna, - ): Promise { + ): Promise> { const antenna = typeof src === 'object' ? src : await this.findOneOrFail(src); const hasUnreadNote = (await AntennaNotes.findOne({ antennaId: antenna.id, read: false })) != null; diff --git a/src/models/repositories/app.ts b/src/models/repositories/app.ts index 2287bd439..0226edad1 100644 --- a/src/models/repositories/app.ts +++ b/src/models/repositories/app.ts @@ -1,9 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { App } from '@/models/entities/app'; import { AccessTokens } from '../index'; -import { SchemaType } from '@/misc/schema'; - -export type PackedApp = SchemaType; +import { Packed } from '@/misc/schema'; +import { User } from '../entities/user'; @EntityRepository(App) export class AppRepository extends Repository { @@ -15,7 +14,7 @@ export class AppRepository extends Repository { includeSecret?: boolean, includeProfileImageIds?: boolean } - ): Promise { + ): Promise> { const opts = Object.assign({ detail: false, includeSecret: false, @@ -52,13 +51,9 @@ export const packedAppSchema = { type: 'string' as const, optional: false as const, nullable: false as const }, - createdAt: { + callbackUrl: { type: 'string' as const, - optional: false as const, nullable: false as const - }, - lastUsedAt: { - type: 'string' as const, - optional: false as const, nullable: false as const + optional: false as const, nullable: true as const }, permission: { type: 'array' as const, diff --git a/src/models/repositories/blocking.ts b/src/models/repositories/blocking.ts index 515b3a6b1..ac60c9a4c 100644 --- a/src/models/repositories/blocking.ts +++ b/src/models/repositories/blocking.ts @@ -2,17 +2,15 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../index'; import { Blocking } from '@/models/entities/blocking'; import { awaitAll } from '@/prelude/await-all'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { User } from '@/models/entities/user'; -export type PackedBlocking = SchemaType; - @EntityRepository(Blocking) export class BlockingRepository extends Repository { public async pack( src: Blocking['id'] | Blocking, me?: { id: User['id'] } | null | undefined - ): Promise { + ): Promise> { const blocking = typeof src === 'object' ? src : await this.findOneOrFail(src); return await awaitAll({ diff --git a/src/models/repositories/channel.ts b/src/models/repositories/channel.ts index 4bb829f57..5c7d09547 100644 --- a/src/models/repositories/channel.ts +++ b/src/models/repositories/channel.ts @@ -1,17 +1,15 @@ import { EntityRepository, Repository } from 'typeorm'; import { Channel } from '@/models/entities/channel'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { DriveFiles, ChannelFollowings, NoteUnreads } from '../index'; import { User } from '@/models/entities/user'; -export type PackedChannel = SchemaType; - @EntityRepository(Channel) export class ChannelRepository extends Repository { public async pack( src: Channel['id'] | Channel, me?: { id: User['id'] } | null | undefined, - ): Promise { + ): Promise> { const channel = typeof src === 'object' ? src : await this.findOneOrFail(src); const meId = me ? me.id : null; diff --git a/src/models/repositories/clip.ts b/src/models/repositories/clip.ts index e3d718bef..7892811d4 100644 --- a/src/models/repositories/clip.ts +++ b/src/models/repositories/clip.ts @@ -1,16 +1,14 @@ import { EntityRepository, Repository } from 'typeorm'; import { Clip } from '@/models/entities/clip'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { Users } from '../index'; import { awaitAll } from '@/prelude/await-all'; -export type PackedClip = SchemaType; - @EntityRepository(Clip) export class ClipRepository extends Repository { public async pack( src: Clip['id'] | Clip, - ): Promise { + ): Promise> { const clip = typeof src === 'object' ? src : await this.findOneOrFail(src); return await awaitAll({ diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts index 63bd020cb..ddf9a46af 100644 --- a/src/models/repositories/drive-file.ts +++ b/src/models/repositories/drive-file.ts @@ -4,14 +4,12 @@ import { Users, DriveFolders } from '../index'; import { User } from '@/models/entities/user'; import { toPuny } from '@/misc/convert-host'; import { awaitAll } from '@/prelude/await-all'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import config from '@/config/index'; import { query, appendQuery } from '@/prelude/url'; import { Meta } from '@/models/entities/meta'; import { fetchMeta } from '@/misc/fetch-meta'; -export type PackedDriveFile = SchemaType; - type PackOptions = { detail?: boolean, self?: boolean, @@ -99,12 +97,12 @@ export class DriveFileRepository extends Repository { return parseInt(sum, 10) || 0; } - public async pack(src: DriveFile['id'], options?: PackOptions): Promise; - public async pack(src: DriveFile, options?: PackOptions): Promise; + public async pack(src: DriveFile['id'], options?: PackOptions): Promise | null>; + public async pack(src: DriveFile, options?: PackOptions): Promise>; public async pack( src: DriveFile['id'] | DriveFile, options?: PackOptions - ): Promise { + ): Promise | null> { const opts = Object.assign({ detail: false, self: false diff --git a/src/models/repositories/drive-folder.ts b/src/models/repositories/drive-folder.ts index bc73018f2..8ef6f01b5 100644 --- a/src/models/repositories/drive-folder.ts +++ b/src/models/repositories/drive-folder.ts @@ -2,9 +2,7 @@ import { EntityRepository, Repository } from 'typeorm'; import { DriveFolders, DriveFiles } from '../index'; import { DriveFolder } from '@/models/entities/drive-folder'; import { awaitAll } from '@/prelude/await-all'; -import { SchemaType } from '@/misc/schema'; - -export type PackedDriveFolder = SchemaType; +import { Packed } from '@/misc/schema'; @EntityRepository(DriveFolder) export class DriveFolderRepository extends Repository { @@ -20,7 +18,7 @@ export class DriveFolderRepository extends Repository { options?: { detail: boolean } - ): Promise { + ): Promise> { const opts = Object.assign({ detail: false }, options); diff --git a/src/models/repositories/emoji.ts b/src/models/repositories/emoji.ts index c3d7184ec..7985c27ab 100644 --- a/src/models/repositories/emoji.ts +++ b/src/models/repositories/emoji.ts @@ -1,11 +1,12 @@ import { EntityRepository, Repository } from 'typeorm'; import { Emoji } from '@/models/entities/emoji'; +import { Packed } from '@/misc/schema'; @EntityRepository(Emoji) export class EmojiRepository extends Repository { public async pack( src: Emoji['id'] | Emoji, - ) { + ): Promise> { const emoji = typeof src === 'object' ? src : await this.findOneOrFail(src); return { @@ -24,3 +25,41 @@ export class EmojiRepository extends Repository { return Promise.all(emojis.map(x => this.pack(x))); } } + +export const packedEmojiSchema = { + type: 'object' as const, + optional: false as const, nullable: false as const, + properties: { + id: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + aliases: { + type: 'array' as const, + optional: false as const, nullable: false as const, + items: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + }, + }, + name: { + type: 'string' as const, + optional: false as const, nullable: false as const, + }, + category: { + type: 'string' as const, + optional: false as const, nullable: true as const, + }, + host: { + type: 'string' as const, + optional: false as const, nullable: true as const, + }, + url: { + type: 'string' as const, + optional: false as const, nullable: false as const, + }, + } +}; diff --git a/src/models/repositories/following.ts b/src/models/repositories/following.ts index 24ddd0d67..b1f716069 100644 --- a/src/models/repositories/following.ts +++ b/src/models/repositories/following.ts @@ -2,7 +2,7 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../index'; import { Following } from '@/models/entities/following'; import { awaitAll } from '@/prelude/await-all'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { User } from '@/models/entities/user'; type LocalFollowerFollowing = Following & { @@ -29,8 +29,6 @@ type RemoteFolloweeFollowing = Following & { followeeSharedInbox: string; }; -export type PackedFollowing = SchemaType; - @EntityRepository(Following) export class FollowingRepository extends Repository { public isLocalFollower(following: Following): following is LocalFollowerFollowing { @@ -56,7 +54,7 @@ export class FollowingRepository extends Repository { populateFollowee?: boolean; populateFollower?: boolean; } - ): Promise { + ): Promise> { const following = typeof src === 'object' ? src : await this.findOneOrFail(src); if (opts == null) opts = {}; diff --git a/src/models/repositories/gallery-post.ts b/src/models/repositories/gallery-post.ts index afa22e9ed..4f666ff25 100644 --- a/src/models/repositories/gallery-post.ts +++ b/src/models/repositories/gallery-post.ts @@ -1,18 +1,16 @@ import { EntityRepository, Repository } from 'typeorm'; import { GalleryPost } from '@/models/entities/gallery-post'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { Users, DriveFiles, GalleryLikes } from '../index'; import { awaitAll } from '@/prelude/await-all'; import { User } from '@/models/entities/user'; -export type PackedGalleryPost = SchemaType; - @EntityRepository(GalleryPost) export class GalleryPostRepository extends Repository { public async pack( src: GalleryPost['id'] | GalleryPost, me?: { id: User['id'] } | null | undefined, - ): Promise { + ): Promise> { const meId = me ? me.id : null; const post = typeof src === 'object' ? src : await this.findOneOrFail(src); diff --git a/src/models/repositories/games/reversi/game.ts b/src/models/repositories/games/reversi/game.ts index dc91ad51b..9adb386fa 100644 --- a/src/models/repositories/games/reversi/game.ts +++ b/src/models/repositories/games/reversi/game.ts @@ -2,6 +2,7 @@ import { User } from '@/models/entities/user'; import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../../../index'; import { ReversiGame } from '@/models/entities/games/reversi/game'; +import { Packed } from '@/misc/schema'; @EntityRepository(ReversiGame) export class ReversiGameRepository extends Repository { @@ -11,7 +12,7 @@ export class ReversiGameRepository extends Repository { options?: { detail?: boolean } - ) { + ): Promise> { const opts = Object.assign({ detail: true }, options); @@ -20,8 +21,8 @@ export class ReversiGameRepository extends Repository { return { id: game.id, - createdAt: game.createdAt, - startedAt: game.startedAt, + createdAt: game.createdAt.toISOString(), + startedAt: game.startedAt && game.startedAt.toISOString(), isStarted: game.isStarted, isEnded: game.isEnded, form1: game.form1, @@ -41,9 +42,150 @@ export class ReversiGameRepository extends Repository { canPutEverywhere: game.canPutEverywhere, loopedBoard: game.loopedBoard, ...(opts.detail ? { - logs: game.logs, + logs: game.logs.map(log => ({ + at: log.at.toISOString(), + color: log.color, + pos: log.pos + })), map: game.map, } : {}) }; } } + +export const packedReversiGameSchema = { + type: 'object' as const, + optional: false as const, nullable: false as const, + properties: { + id: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + createdAt: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'date-time', + }, + startedAt: { + type: 'string' as const, + optional: false as const, nullable: true as const, + format: 'date-time', + }, + isStarted: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + isEnded: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + form1: { + type: 'any' as const, + optional: false as const, nullable: true as const, + }, + form2: { + type: 'any' as const, + optional: false as const, nullable: true as const, + }, + user1Accepted: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + user2Accepted: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + user1Id: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + user2Id: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + user1: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'User' as const, + }, + user2: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'User' as const, + }, + winnerId: { + type: 'string' as const, + optional: false as const, nullable: true as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + winner: { + type: 'object' as const, + optional: false as const, nullable: true as const, + ref: 'User' as const, + }, + surrendered: { + type: 'string' as const, + optional: false as const, nullable: true as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + black: { + type: 'number' as const, + optional: false as const, nullable: true as const, + }, + bw: { + type: 'string' as const, + optional: false as const, nullable: false as const, + }, + isLlotheo: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + canPutEverywhere: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + loopedBoard: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + logs: { + type: 'array' as const, + optional: true as const, nullable: false as const, + items: { + type: 'object' as const, + optional: true as const, nullable: false as const, + properties: { + at: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'date-time', + }, + color: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, + pos: { + type: 'number' as const, + optional: false as const, nullable: false as const, + }, + } + } + }, + map: { + type: 'array' as const, + optional: true as const, nullable: false as const, + items: { + type: 'string' as const, + optional: false as const, nullable: false as const, + } + } + } +}; diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts index 148221dee..b4515800d 100644 --- a/src/models/repositories/games/reversi/matching.ts +++ b/src/models/repositories/games/reversi/matching.ts @@ -3,18 +3,19 @@ import { ReversiMatching } from '@/models/entities/games/reversi/matching'; import { Users } from '../../../index'; import { awaitAll } from '@/prelude/await-all'; import { User } from '@/models/entities/user'; +import { Packed } from '@/misc/schema'; @EntityRepository(ReversiMatching) export class ReversiMatchingRepository extends Repository { public async pack( src: ReversiMatching['id'] | ReversiMatching, me: { id: User['id'] } - ) { + ): Promise> { const matching = typeof src === 'object' ? src : await this.findOneOrFail(src); return await awaitAll({ id: matching.id, - createdAt: matching.createdAt, + createdAt: matching.createdAt.toISOString(), parentId: matching.parentId, parent: Users.pack(matching.parentId, me, { detail: true @@ -26,3 +27,43 @@ export class ReversiMatchingRepository extends Repository { }); } } + +export const packedReversiMatchingSchema = { + type: 'object' as const, + optional: false as const, nullable: false as const, + properties: { + id: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + createdAt: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'date-time', + }, + parentId: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + parent: { + type: 'object' as const, + optional: false as const, nullable: true as const, + ref: 'User' as const, + }, + childId: { + type: 'string' as const, + optional: false as const, nullable: false as const, + format: 'id', + example: 'xxxxxxxxxx', + }, + child: { + type: 'object' as const, + optional: false as const, nullable: false as const, + ref: 'User' as const, + }, + } +}; diff --git a/src/models/repositories/hashtag.ts b/src/models/repositories/hashtag.ts index ee42ad16b..d52f6ba7c 100644 --- a/src/models/repositories/hashtag.ts +++ b/src/models/repositories/hashtag.ts @@ -1,14 +1,12 @@ import { EntityRepository, Repository } from 'typeorm'; import { Hashtag } from '@/models/entities/hashtag'; -import { SchemaType } from '@/misc/schema'; - -export type PackedHashtag = SchemaType; +import { Packed } from '@/misc/schema'; @EntityRepository(Hashtag) export class HashtagRepository extends Repository { public async pack( src: Hashtag, - ): Promise { + ): Promise> { return { tag: src.name, mentionedUsersCount: src.mentionedUsersCount, diff --git a/src/models/repositories/messaging-message.ts b/src/models/repositories/messaging-message.ts index f97905af2..abdff6368 100644 --- a/src/models/repositories/messaging-message.ts +++ b/src/models/repositories/messaging-message.ts @@ -1,11 +1,9 @@ import { EntityRepository, Repository } from 'typeorm'; import { MessagingMessage } from '@/models/entities/messaging-message'; import { Users, DriveFiles, UserGroups } from '../index'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { User } from '@/models/entities/user'; -export type PackedMessagingMessage = SchemaType; - @EntityRepository(MessagingMessage) export class MessagingMessageRepository extends Repository { public validateText(text: string): boolean { @@ -19,7 +17,7 @@ export class MessagingMessageRepository extends Repository { populateRecipient?: boolean, populateGroup?: boolean, } - ): Promise { + ): Promise> { const opts = options || { populateRecipient: true, populateGroup: true, diff --git a/src/models/repositories/muting.ts b/src/models/repositories/muting.ts index d957b1792..869afd3c4 100644 --- a/src/models/repositories/muting.ts +++ b/src/models/repositories/muting.ts @@ -2,17 +2,15 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../index'; import { Muting } from '@/models/entities/muting'; import { awaitAll } from '@/prelude/await-all'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { User } from '@/models/entities/user'; -export type PackedMuting = SchemaType; - @EntityRepository(Muting) export class MutingRepository extends Repository { public async pack( src: Muting['id'] | Muting, me?: { id: User['id'] } | null | undefined - ): Promise { + ): Promise> { const muting = typeof src === 'object' ? src : await this.findOneOrFail(src); return await awaitAll({ diff --git a/src/models/repositories/note-reaction.ts b/src/models/repositories/note-reaction.ts index e73a83210..ba74076f6 100644 --- a/src/models/repositories/note-reaction.ts +++ b/src/models/repositories/note-reaction.ts @@ -1,18 +1,16 @@ import { EntityRepository, Repository } from 'typeorm'; import { NoteReaction } from '@/models/entities/note-reaction'; import { Users } from '../index'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { convertLegacyReaction } from '@/misc/reaction-lib'; import { User } from '@/models/entities/user'; -export type PackedNoteReaction = SchemaType; - @EntityRepository(NoteReaction) export class NoteReactionRepository extends Repository { public async pack( src: NoteReaction['id'] | NoteReaction, me?: { id: User['id'] } | null | undefined - ): Promise { + ): Promise> { const reaction = typeof src === 'object' ? src : await this.findOneOrFail(src); return { diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index 376a09d0c..c0ac22b2d 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -3,15 +3,13 @@ import * as mfm from 'mfm-js'; import { Note } from '@/models/entities/note'; import { User } from '@/models/entities/user'; import { Users, PollVotes, DriveFiles, NoteReactions, Followings, Polls, Channels } from '../index'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { nyaize } from '@/misc/nyaize'; import { awaitAll } from '@/prelude/await-all'; import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '@/misc/reaction-lib'; import { NoteReaction } from '@/models/entities/note-reaction'; import { aggregateNoteEmojis, populateEmojis, prefetchEmojis } from '@/misc/populate-emojis'; -export type PackedNote = SchemaType; - @EntityRepository(Note) export class NoteRepository extends Repository { public validateCw(x: string) { @@ -67,7 +65,7 @@ export class NoteRepository extends Repository { return true; } - private async hideNote(packedNote: PackedNote, meId: User['id'] | null) { + private async hideNote(packedNote: Packed<'Note'>, meId: User['id'] | null) { // TODO: isVisibleForMe を使うようにしても良さそう(型違うけど) let hide = false; @@ -137,7 +135,7 @@ export class NoteRepository extends Repository { myReactions: Map; }; } - ): Promise { + ): Promise> { const opts = Object.assign({ detail: true, skipHide: false diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index b7f9e3643..d1cf9b087 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -2,15 +2,13 @@ import { EntityRepository, In, Repository } from 'typeorm'; import { Users, Notes, UserGroupInvitations, AccessTokens, NoteReactions } from '../index'; import { Notification } from '@/models/entities/notification'; import { awaitAll } from '@/prelude/await-all'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { Note } from '@/models/entities/note'; import { NoteReaction } from '@/models/entities/note-reaction'; import { User } from '@/models/entities/user'; import { aggregateNoteEmojis, prefetchEmojis } from '@/misc/populate-emojis'; import { notificationTypes } from '@/types'; -export type PackedNotification = SchemaType; - @EntityRepository(Notification) export class NotificationRepository extends Repository { public async pack( @@ -20,7 +18,7 @@ export class NotificationRepository extends Repository { myReactions: Map; }; } - ): Promise { + ): Promise> { const notification = typeof src === 'object' ? src : await this.findOneOrFail(src); const token = notification.appAccessTokenId ? await AccessTokens.findOneOrFail(notification.appAccessTokenId) : null; diff --git a/src/models/repositories/page.ts b/src/models/repositories/page.ts index 1a61e2c99..3a3642d7e 100644 --- a/src/models/repositories/page.ts +++ b/src/models/repositories/page.ts @@ -1,19 +1,17 @@ import { EntityRepository, Repository } from 'typeorm'; import { Page } from '@/models/entities/page'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { Users, DriveFiles, PageLikes } from '../index'; import { awaitAll } from '@/prelude/await-all'; import { DriveFile } from '@/models/entities/drive-file'; import { User } from '@/models/entities/user'; -export type PackedPage = SchemaType; - @EntityRepository(Page) export class PageRepository extends Repository { public async pack( src: Page['id'] | Page, me?: { id: User['id'] } | null | undefined, - ): Promise { + ): Promise> { const meId = me ? me.id : null; const page = typeof src === 'object' ? src : await this.findOneOrFail(src); diff --git a/src/models/repositories/user-group.ts b/src/models/repositories/user-group.ts index a76ac7b9d..b38a2fb50 100644 --- a/src/models/repositories/user-group.ts +++ b/src/models/repositories/user-group.ts @@ -1,15 +1,13 @@ import { EntityRepository, Repository } from 'typeorm'; import { UserGroup } from '@/models/entities/user-group'; import { UserGroupJoinings } from '../index'; -import { SchemaType } from '@/misc/schema'; - -export type PackedUserGroup = SchemaType; +import { Packed } from '@/misc/schema'; @EntityRepository(UserGroup) export class UserGroupRepository extends Repository { public async pack( src: UserGroup['id'] | UserGroup, - ): Promise { + ): Promise> { const userGroup = typeof src === 'object' ? src : await this.findOneOrFail(src); const users = await UserGroupJoinings.find({ diff --git a/src/models/repositories/user-list.ts b/src/models/repositories/user-list.ts index 809dbe026..331c278e6 100644 --- a/src/models/repositories/user-list.ts +++ b/src/models/repositories/user-list.ts @@ -1,15 +1,13 @@ import { EntityRepository, Repository } from 'typeorm'; import { UserList } from '@/models/entities/user-list'; import { UserListJoinings } from '../index'; -import { SchemaType } from '@/misc/schema'; - -export type PackedUserList = SchemaType; +import { Packed } from '@/misc/schema'; @EntityRepository(UserList) export class UserListRepository extends Repository { public async pack( src: UserList['id'] | UserList, - ): Promise { + ): Promise> { const userList = typeof src === 'object' ? src : await this.findOneOrFail(src); const users = await UserListJoinings.find({ diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index 39c90cf5e..b6f27e32e 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -3,14 +3,12 @@ import { EntityRepository, Repository, In, Not } from 'typeorm'; import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; import { Notes, NoteUnreads, FollowRequests, Notifications, MessagingMessages, UserNotePinings, Followings, Blockings, Mutings, UserProfiles, UserSecurityKeys, UserGroupJoinings, Pages, Announcements, AnnouncementReads, Antennas, AntennaNotes, ChannelFollowings, Instances } from '../index'; import config from '@/config/index'; -import { SchemaType } from '@/misc/schema'; +import { Packed } from '@/misc/schema'; import { awaitAll } from '@/prelude/await-all'; import { populateEmojis } from '@/misc/populate-emojis'; import { getAntennas } from '@/misc/antenna-cache'; import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const'; -export type PackedUser = SchemaType; - @EntityRepository(User) export class UserRepository extends Repository { public async getRelation(me: User['id'], target: User['id']) { @@ -164,7 +162,7 @@ export class UserRepository extends Repository { detail?: boolean, includeSecrets?: boolean, } - ): Promise { + ): Promise> { const opts = Object.assign({ detail: false, includeSecrets: false diff --git a/src/server/api/stream/channels/channel.ts b/src/server/api/stream/channels/channel.ts index e6a9a6c69..72ddbf93b 100644 --- a/src/server/api/stream/channels/channel.ts +++ b/src/server/api/stream/channels/channel.ts @@ -3,8 +3,8 @@ import Channel from '../channel'; import { Notes, Users } from '@/models/index'; import { isMutedUserRelated } from '@/misc/is-muted-user-related'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; -import { PackedNote } from '@/models/repositories/note'; import { User } from '@/models/entities/user'; +import { Packed } from '@/misc/schema'; export default class extends Channel { public readonly chName = 'channel'; @@ -25,7 +25,7 @@ export default class extends Channel { } @autobind - private async onNote(note: PackedNote) { + private async onNote(note: Packed<'Note'>) { if (note.channelId !== this.channelId) return; // リプライなら再pack diff --git a/src/server/api/stream/channels/global-timeline.ts b/src/server/api/stream/channels/global-timeline.ts index 384ed6140..f5983ab47 100644 --- a/src/server/api/stream/channels/global-timeline.ts +++ b/src/server/api/stream/channels/global-timeline.ts @@ -3,9 +3,9 @@ import { isMutedUserRelated } from '@/misc/is-muted-user-related'; import Channel from '../channel'; import { fetchMeta } from '@/misc/fetch-meta'; import { Notes } from '@/models/index'; -import { PackedNote } from '@/models/repositories/note'; import { checkWordMute } from '@/misc/check-word-mute'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; +import { Packed } from '@/misc/schema'; export default class extends Channel { public readonly chName = 'globalTimeline'; @@ -24,7 +24,7 @@ export default class extends Channel { } @autobind - private async onNote(note: PackedNote) { + private async onNote(note: Packed<'Note'>) { if (note.visibility !== 'public') return; if (note.channelId != null) return; diff --git a/src/server/api/stream/channels/hashtag.ts b/src/server/api/stream/channels/hashtag.ts index 997ab75f6..281be4f2e 100644 --- a/src/server/api/stream/channels/hashtag.ts +++ b/src/server/api/stream/channels/hashtag.ts @@ -2,9 +2,9 @@ import autobind from 'autobind-decorator'; import { isMutedUserRelated } from '@/misc/is-muted-user-related'; import Channel from '../channel'; import { Notes } from '@/models/index'; -import { PackedNote } from '@/models/repositories/note'; import { normalizeForSearch } from '@/misc/normalize-for-search'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; +import { Packed } from '@/misc/schema'; export default class extends Channel { public readonly chName = 'hashtag'; @@ -23,7 +23,7 @@ export default class extends Channel { } @autobind - private async onNote(note: PackedNote) { + private async onNote(note: Packed<'Note'>) { const noteTags = note.tags ? note.tags.map((t: string) => t.toLowerCase()) : []; const matched = this.q.some(tags => tags.every(tag => noteTags.includes(normalizeForSearch(tag)))); if (!matched) return; diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts index 0e21ab552..52e9aec25 100644 --- a/src/server/api/stream/channels/home-timeline.ts +++ b/src/server/api/stream/channels/home-timeline.ts @@ -2,9 +2,9 @@ import autobind from 'autobind-decorator'; import { isMutedUserRelated } from '@/misc/is-muted-user-related'; import Channel from '../channel'; import { Notes } from '@/models/index'; -import { PackedNote } from '@/models/repositories/note'; import { checkWordMute } from '@/misc/check-word-mute'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; +import { Packed } from '@/misc/schema'; export default class extends Channel { public readonly chName = 'homeTimeline'; @@ -18,7 +18,7 @@ export default class extends Channel { } @autobind - private async onNote(note: PackedNote) { + private async onNote(note: Packed<'Note'>) { if (note.channelId) { if (!this.followingChannels.has(note.channelId)) return; } else { diff --git a/src/server/api/stream/channels/hybrid-timeline.ts b/src/server/api/stream/channels/hybrid-timeline.ts index 0b28ff616..51f95fc0c 100644 --- a/src/server/api/stream/channels/hybrid-timeline.ts +++ b/src/server/api/stream/channels/hybrid-timeline.ts @@ -3,9 +3,9 @@ import { isMutedUserRelated } from '@/misc/is-muted-user-related'; import Channel from '../channel'; import { fetchMeta } from '@/misc/fetch-meta'; import { Notes } from '@/models/index'; -import { PackedNote } from '@/models/repositories/note'; import { checkWordMute } from '@/misc/check-word-mute'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; +import { Packed } from '@/misc/schema'; export default class extends Channel { public readonly chName = 'hybridTimeline'; @@ -22,7 +22,7 @@ export default class extends Channel { } @autobind - private async onNote(note: PackedNote) { + private async onNote(note: Packed<'Note'>) { // チャンネルの投稿ではなく、自分自身の投稿 または // チャンネルの投稿ではなく、その投稿のユーザーをフォローしている または // チャンネルの投稿ではなく、全体公開のローカルの投稿 または diff --git a/src/server/api/stream/channels/local-timeline.ts b/src/server/api/stream/channels/local-timeline.ts index 20061410c..a6166c2be 100644 --- a/src/server/api/stream/channels/local-timeline.ts +++ b/src/server/api/stream/channels/local-timeline.ts @@ -3,9 +3,9 @@ import { isMutedUserRelated } from '@/misc/is-muted-user-related'; import Channel from '../channel'; import { fetchMeta } from '@/misc/fetch-meta'; import { Notes } from '@/models/index'; -import { PackedNote } from '@/models/repositories/note'; import { checkWordMute } from '@/misc/check-word-mute'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; +import { Packed } from '@/misc/schema'; export default class extends Channel { public readonly chName = 'localTimeline'; @@ -24,7 +24,7 @@ export default class extends Channel { } @autobind - private async onNote(note: PackedNote) { + private async onNote(note: Packed<'Note'>) { if (note.user.host !== null) return; if (note.visibility !== 'public') return; if (note.channelId != null && !this.followingChannels.has(note.channelId)) return; diff --git a/src/server/api/stream/channels/user-list.ts b/src/server/api/stream/channels/user-list.ts index 0ca83cd65..63b254605 100644 --- a/src/server/api/stream/channels/user-list.ts +++ b/src/server/api/stream/channels/user-list.ts @@ -3,8 +3,8 @@ import Channel from '../channel'; import { Notes, UserListJoinings, UserLists } from '@/models/index'; import { isMutedUserRelated } from '@/misc/is-muted-user-related'; import { User } from '@/models/entities/user'; -import { PackedNote } from '@/models/repositories/note'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; +import { Packed } from '@/misc/schema'; export default class extends Channel { public readonly chName = 'userList'; @@ -47,7 +47,7 @@ export default class extends Channel { } @autobind - private async onNote(note: PackedNote) { + private async onNote(note: Packed<'Note'>) { if (!this.listUsers.includes(note.userId)) return; if (['followers', 'specified'].includes(note.visibility)) { diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index f83bc9331..ccd555e14 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -14,7 +14,7 @@ import { AccessToken } from '@/models/entities/access-token'; import { UserProfile } from '@/models/entities/user-profile'; import { publishChannelStream, publishGroupMessagingStream, publishMessagingStream } from '@/services/stream'; import { UserGroup } from '@/models/entities/user-group'; -import { PackedNote } from '@/models/repositories/note'; +import { Packed } from '@/misc/schema'; /** * Main stream connection @@ -31,7 +31,7 @@ export default class Connection { public subscriber: EventEmitter; private channels: Channel[] = []; private subscribingNotes: any = {}; - private cachedNotes: PackedNote[] = []; + private cachedNotes: Packed<'Note'>[] = []; constructor( wsConnection: websocket.connection, @@ -150,8 +150,8 @@ export default class Connection { } @autobind - public cacheNote(note: PackedNote) { - const add = (note: PackedNote) => { + public cacheNote(note: Packed<'Note'>) { + const add = (note: Packed<'Note'>) => { const existIndex = this.cachedNotes.findIndex(n => n.id === note.id); if (existIndex > -1) { this.cachedNotes[existIndex] = note; diff --git a/src/services/note/read.ts b/src/services/note/read.ts index b5e7de797..f25f86da9 100644 --- a/src/services/note/read.ts +++ b/src/services/note/read.ts @@ -6,15 +6,15 @@ import { Not, IsNull, In } from 'typeorm'; import { Channel } from '@/models/entities/channel'; import { checkHitAntenna } from '@/misc/check-hit-antenna'; import { getAntennas } from '@/misc/antenna-cache'; -import { PackedNote } from '@/models/repositories/note'; import { readNotificationByQuery } from '@/server/api/common/read-notification'; +import { Packed } from '@/misc/schema'; /** * Mark notes as read */ export default async function( userId: User['id'], - notes: (Note | PackedNote)[], + notes: (Note | Packed<'Note'>)[], info?: { following: Set; followingChannels: Set; @@ -34,10 +34,10 @@ export default async function( })).map(x => x.followeeId)); const myAntennas = (await getAntennas()).filter(a => a.userId === userId); - const readMentions: (Note | PackedNote)[] = []; - const readSpecifiedNotes: (Note | PackedNote)[] = []; - const readChannelNotes: (Note | PackedNote)[] = []; - const readAntennaNotes: (Note | PackedNote)[] = []; + const readMentions: (Note | Packed<'Note'>)[] = []; + const readSpecifiedNotes: (Note | Packed<'Note'>)[] = []; + const readChannelNotes: (Note | Packed<'Note'>)[] = []; + const readAntennaNotes: (Note | Packed<'Note'>)[] = []; for (const note of notes) { if (note.mentions && note.mentions.includes(userId)) { diff --git a/src/services/push-notification.ts b/src/services/push-notification.ts index 5bd749969..5949d11b3 100644 --- a/src/services/push-notification.ts +++ b/src/services/push-notification.ts @@ -2,11 +2,10 @@ import * as push from 'web-push'; import config from '@/config/index'; import { SwSubscriptions } from '@/models/index'; import { fetchMeta } from '@/misc/fetch-meta'; -import { PackedNotification } from '../models/repositories/notification'; -import { PackedMessagingMessage } from '../models/repositories/messaging-message'; +import { Packed } from '@/misc/schema'; type notificationType = 'notification' | 'unreadMessagingMessage'; -type notificationBody = PackedNotification | PackedMessagingMessage; +type notificationBody = Packed<'Notification'> | Packed<'MessagingMessage'>; export default async function(userId: string, type: notificationType, body: notificationBody) { const meta = await fetchMeta();