From 987c98faecac7dd1c0747cf0351315b6f18d0c5c Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 5 Sep 2021 23:47:41 +0900 Subject: [PATCH 01/91] wip --- package.json | 1 + src/server/api/stream/index.ts | 9 +++--- src/server/api/stream/types.ts | 50 ++++++++++++++++++++++++++++++++++ yarn.lock | 5 ++++ 4 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 src/server/api/stream/types.ts diff --git a/package.json b/package.json index ebb4d90897..0f93ae03e9 100644 --- a/package.json +++ b/package.json @@ -209,6 +209,7 @@ "seedrandom": "3.0.5", "sharp": "0.29.0", "speakeasy": "2.0.0", + "strict-event-emitter-types": "2.0.0", "stringz": "2.1.0", "style-loader": "3.2.1", "summaly": "2.4.1", diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 469f28f11c..13011b193e 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -15,6 +15,7 @@ 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 { StreamEventEmitter, UserEvent } from './types'; /** * Main stream connection @@ -28,7 +29,7 @@ export default class Connection { public followingChannels: Set = new Set(); public token?: AccessToken; private wsConnection: websocket.connection; - public subscriber: EventEmitter; + public subscriber: StreamEventEmitter; private channels: Channel[] = []; private subscribingNotes: any = {}; private cachedNotes: PackedNote[] = []; @@ -57,14 +58,14 @@ export default class Connection { this.updateFollowingChannels(); this.updateUserProfile(); - this.subscriber.on(`user:${this.user.id}`, ({ type, body }) => { - this.onUserEvent(type, body); + this.subscriber.on(`user:${this.user.id}`, (ev) => { + this.onUserEvent(ev); }); } } @autobind - private onUserEvent(type: string, body: any) { + private onUserEvent({ type, body }: UserEvent) { switch (type) { case 'follow': this.following.add(body.id); diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts new file mode 100644 index 0000000000..92b3f0fdb5 --- /dev/null +++ b/src/server/api/stream/types.ts @@ -0,0 +1,50 @@ +import { User } from '@/models/entities/user'; +import { EventEmitter } from 'events'; +import Emitter from 'strict-event-emitter-types'; +import StreamTypes from 'misskey-js/built/streaming.types'; +import { Channel } from '@/models/entities/channel'; +import { UserProfile } from '@/models/entities/user-profile'; +import { PackedUser } from '@/models/repositories/user'; + +type Payload void> = T extends (payload: infer P) => void ? P : never; + +// https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type +type EventUnionFromDictionary< + T extends object, + U = { [K in keyof T]: { type: K; body: T[K]} } +> = U[keyof U]; + +export type BroadcastStream = { + name: 'broadcast'; + type: T; + body: Payload; +}; + +export interface UserEventTypes { + terminate: {}; + followChannel: Channel; + unfollowChannel: Channel; + updateUserProfile: UserProfile; + mute: User; + unmute: User; + follow: PackedUser; + unfollow: PackedUser; + userAdded: PackedUser; +}; + +// UserList userRemoved: PackedUser; + +export type UserEventName = `user:${User['id']}`; +export type UserEvent = EventUnionFromDictionary; + +interface StreamEvents { + 'broadcast': (e: BroadcastStream) => void; +} + +interface AuthenticatedStreamEvents { + [key: UserEventName]: (e: UserEvent) => void; + [key: `mainStream:${User['id']}`]: (e: { type: string; body: any }) => void; + [key: `driveStream:${User['id']}`]: (e: { type: string; body: any }) => void; +} + +export type StreamEventEmitter = Emitter; diff --git a/yarn.lock b/yarn.lock index 8151dfe089..33f9f22454 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10249,6 +10249,11 @@ streamsearch@0.1.2: resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" integrity sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo= +strict-event-emitter-types@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz#05e15549cb4da1694478a53543e4e2f4abcf277f" + integrity sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA== + strict-uri-encode@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" From 225805da8a524611f273384517f19217a6696346 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 5 Sep 2021 23:55:01 +0900 Subject: [PATCH 02/91] wip --- src/server/api/stream/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 92b3f0fdb5..74a0db8e53 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -42,7 +42,7 @@ interface StreamEvents { } interface AuthenticatedStreamEvents { - [key: UserEventName]: (e: UserEvent) => void; + [key: UserEventName]: (e: UserEvent) => void; [key: `mainStream:${User['id']}`]: (e: { type: string; body: any }) => void; [key: `driveStream:${User['id']}`]: (e: { type: string; body: any }) => void; } From f74f4ffc6acd46e453f1c0b9234b5248513cfc6a Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 5 Sep 2021 23:55:32 +0900 Subject: [PATCH 03/91] wip --- src/server/api/stream/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 13011b193e..e9f5bf9d15 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -58,7 +58,7 @@ export default class Connection { this.updateFollowingChannels(); this.updateUserProfile(); - this.subscriber.on(`user:${this.user.id}`, (ev) => { + this.subscriber.on(`user:${this.user.id}`, ev => { this.onUserEvent(ev); }); } From 08576c49de16435d980a2724e980c138515b578b Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 00:11:31 +0900 Subject: [PATCH 04/91] :v: --- src/server/api/stream/index.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index e9f5bf9d15..c2f0870f11 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -65,36 +65,36 @@ export default class Connection { } @autobind - private onUserEvent({ type, body }: UserEvent) { - switch (type) { + private onUserEvent(ev: UserEvent) { // { type, body }と展開すると型も展開されてしまう + switch (ev.type) { case 'follow': - this.following.add(body.id); + this.following.add(ev.body.id); break; case 'unfollow': - this.following.delete(body.id); + this.following.delete(ev.body.id); break; case 'mute': - this.muting.add(body.id); + this.muting.add(ev.body.id); break; case 'unmute': - this.muting.delete(body.id); + this.muting.delete(ev.body.id); break; // TODO: block events case 'followChannel': - this.followingChannels.add(body.id); + this.followingChannels.add(ev.body.id); break; case 'unfollowChannel': - this.followingChannels.delete(body.id); + this.followingChannels.delete(ev.body.id); break; case 'updateUserProfile': - this.userProfile = body; + this.userProfile = ev.body; break; case 'terminate': From 06c0373be924d5b970353746ddba7ce4f4428d5c Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 00:55:40 +0900 Subject: [PATCH 05/91] add main stream --- src/server/api/stream/channels/main.ts | 25 ++++++------ src/server/api/stream/index.ts | 4 +- src/server/api/stream/types.ts | 53 ++++++++++++++++++++------ 3 files changed, 55 insertions(+), 27 deletions(-) diff --git a/src/server/api/stream/channels/main.ts b/src/server/api/stream/channels/main.ts index b99cb931da..d1dce76dd9 100644 --- a/src/server/api/stream/channels/main.ts +++ b/src/server/api/stream/channels/main.ts @@ -11,35 +11,34 @@ export default class extends Channel { public async init(params: any) { // Subscribe main stream channel this.subscriber.on(`mainStream:${this.user!.id}`, async data => { - const { type } = data; - let { body } = data; - - switch (type) { + switch (data.type) { case 'notification': { - if (this.muting.has(body.userId)) return; - if (body.note && body.note.isHidden) { - const note = await Notes.pack(body.note.id, this.user, { + if (data.body.userId && this.muting.has(data.body.userId)) return; + + // ???? + if (data.body.note && data.body.note.isHidden) { + const note = await Notes.pack(data.body.note.id, this.user, { detail: true }); this.connection.cacheNote(note); - body.note = note; + data.body.note = note; } break; } case 'mention': { - if (this.muting.has(body.userId)) return; - if (body.isHidden) { - const note = await Notes.pack(body.id, this.user, { + if (this.muting.has(data.body.userId)) return; + if (data.body.isHidden) { + const note = await Notes.pack(data.body.id, this.user, { detail: true }); this.connection.cacheNote(note); - body = note; + data.body = note; } break; } } - this.send(type, body); + this.send(data.type, data.body); }); } } diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index c2f0870f11..5bd021c814 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -15,7 +15,7 @@ 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 { StreamEventEmitter, UserEvent } from './types'; +import { StreamEventEmitter, UserEvents } from './types'; /** * Main stream connection @@ -65,7 +65,7 @@ export default class Connection { } @autobind - private onUserEvent(ev: UserEvent) { // { type, body }と展開すると型も展開されてしまう + private onUserEvent(ev: UserEvents) { // { type, body }と展開すると型も展開されてしまう switch (ev.type) { case 'follow': this.following.add(ev.body.id); diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 74a0db8e53..549af96fa8 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -5,6 +5,8 @@ import StreamTypes from 'misskey-js/built/streaming.types'; import { Channel } from '@/models/entities/channel'; import { UserProfile } from '@/models/entities/user-profile'; import { PackedUser } from '@/models/repositories/user'; +import { PackedNotification } from '@/models/repositories/notification'; +import { PackedNote } from '@/models/repositories/note'; type Payload void> = T extends (payload: infer P) => void ? P : never; @@ -14,11 +16,12 @@ type EventUnionFromDictionary< U = { [K in keyof T]: { type: K; body: T[K]} } > = U[keyof U]; -export type BroadcastStream = { - name: 'broadcast'; - type: T; - body: Payload; -}; +type EventUnionFromMkJSTypes< + T extends { [key: string]: ((payload: any) => void) | (() => void) }, + U = { [K in keyof T]: { type: K; body: Payload} } +> = U[keyof U] + +export type BroadcastStream = EventUnionFromMkJSTypes; export interface UserEventTypes { terminate: {}; @@ -31,19 +34,45 @@ export interface UserEventTypes { unfollow: PackedUser; userAdded: PackedUser; }; - -// UserList userRemoved: PackedUser; - export type UserEventName = `user:${User['id']}`; -export type UserEvent = EventUnionFromDictionary; +export type UserEvents = EventUnionFromDictionary; + +export interface mainStreamTypes { + notification: PackedNotification; + mention: PackedNote; + reply: PackedNote; + renote: PackedNote; + follow: PackedUser; + followed: PackedUser; + unfollow: PackedUser; + meUpdated: PackedUser; + pageEvent: Payload; + urlUploadFinished: Payload; + readAllNotifications: never; + unreadNotification: never; + unreadMention: never; + readAllUnreadMentions: never; + unreadSpecifiedNote: never; + readAllUnreadSpecifiedNotes: never; + readAllMessagingMessages: never; + unreadMessagingMessage: never; + readAllAntennas: never; + unreadAntenna: never; + readAllAnnouncements: never; + readAllChannels: never; + unreadChannel: never; + myTokenRegenerated: never; +}; +export type mainStreamName = `mainStream:${User['id']}`; +export type mainStreams = EventUnionFromDictionary; interface StreamEvents { - 'broadcast': (e: BroadcastStream) => void; + 'broadcast': (e: BroadcastStream) => void; } interface AuthenticatedStreamEvents { - [key: UserEventName]: (e: UserEvent) => void; - [key: `mainStream:${User['id']}`]: (e: { type: string; body: any }) => void; + [key: UserEventName]: (e: UserEvents) => void; + [key: mainStreamName]: (e: mainStreams) => void; [key: `driveStream:${User['id']}`]: (e: { type: string; body: any }) => void; } From ba1c57c7bd29232e2054565ee768052149268801 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 01:23:30 +0900 Subject: [PATCH 06/91] =?UTF-8?q?packedNotificationSchema=E3=82=92?= =?UTF-8?q?=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/models/repositories/notification.ts | 34 ++++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index 55af96b6d7..4d13940c76 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -7,6 +7,7 @@ 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; @@ -124,20 +125,41 @@ export const packedNotificationSchema = { optional: false as const, nullable: false as const, format: 'date-time', }, + isRead: { + type: 'boolean' as const, + optional: false as const, nullable: false as const, + }, type: { type: 'string' as const, optional: false as const, nullable: false as const, - enum: ['follow', 'followRequestAccepted', 'receiveFollowRequest', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote'], - }, - userId: { - type: 'string' as const, - optional: true as const, nullable: true as const, - format: 'id', + enum: [...notificationTypes], }, user: { type: 'object' as const, ref: 'User', optional: true as const, nullable: true as const, }, + userId: { + type: 'string' as const, + optional: true as const, nullable: true as const, + format: 'id', + }, + note: { + type: 'object' as const, + ref: 'Note', + optional: true as const, nullable: true as const, + }, + reaction: { + type: 'string' as const, + optional: true as const, nullable: true as const, + }, + body: { + type: 'string' as const, + optional: true as const, nullable: true as const, + }, + icon: { + type: 'string' as const, + optional: true as const, nullable: true as const, + }, } }; From 9a089e584e88186ca1fd49db5ca17e23be8be7a8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 01:23:50 +0900 Subject: [PATCH 07/91] =?UTF-8?q?read:gallery,=20write:gallery,=20read:gal?= =?UTF-8?q?lery-likes,=20write:gallery-likes=E3=81=AB=E7=BF=BB=E8=A8=B3?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ja-JP.yml | 4 ++++ src/misc/api-permissions.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e22f50668f..e5747d5124 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1150,6 +1150,10 @@ _permissions: "write:user-groups": "ユーザーグループを操作する" "read:channels": "チャンネルを見る" "write:channels": "チャンネルを操作する" + "read:gallery": "ギャラリーを見る" + "write:gallery": "ギャラリーを操作する" + "read:gallery-likes": "ギャラリーのいいねを見る" + "write:gallery-likes": "ギャラリーのいいねを操作する" _auth: shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" diff --git a/src/misc/api-permissions.ts b/src/misc/api-permissions.ts index eb20c3d289..160cdf9fd6 100644 --- a/src/misc/api-permissions.ts +++ b/src/misc/api-permissions.ts @@ -32,3 +32,4 @@ export const kinds = [ 'read:gallery-likes', 'write:gallery-likes', ]; +// IF YOU ADD KINDS(PERMISSIONS), YOU MUST ADD TRANSLATIONS (under _permissions). From 3bde3e523dedb0b7620cd4ef603f3d50315db7c0 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 01:35:00 +0900 Subject: [PATCH 08/91] fix --- locales/ja-JP.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e5747d5124..b9623ef0d0 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1150,10 +1150,10 @@ _permissions: "write:user-groups": "ユーザーグループを操作する" "read:channels": "チャンネルを見る" "write:channels": "チャンネルを操作する" - "read:gallery": "ギャラリーを見る" - "write:gallery": "ギャラリーを操作する" - "read:gallery-likes": "ギャラリーのいいねを見る" - "write:gallery-likes": "ギャラリーのいいねを操作する" + "read:gallery": "ギャラリーを見る" + "write:gallery": "ギャラリーを操作する" + "read:gallery-likes": "ギャラリーのいいねを見る" + "write:gallery-likes": "ギャラリーのいいねを操作する" _auth: shareAccess: "「{name}」がアカウントにアクセスすることを許可しますか?" From 110de167e8e440f50e00765e302502f54b14eb12 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 01:38:48 +0900 Subject: [PATCH 09/91] ok --- src/server/api/stream/channels/main.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server/api/stream/channels/main.ts b/src/server/api/stream/channels/main.ts index d1dce76dd9..131ac30472 100644 --- a/src/server/api/stream/channels/main.ts +++ b/src/server/api/stream/channels/main.ts @@ -15,7 +15,6 @@ export default class extends Channel { case 'notification': { if (data.body.userId && this.muting.has(data.body.userId)) return; - // ???? if (data.body.note && data.body.note.isHidden) { const note = await Notes.pack(data.body.note.id, this.user, { detail: true From 47e0e32aa31c0d4e3da85da2294a1503f3a5588b Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 01:58:07 +0900 Subject: [PATCH 10/91] add header, choice, invitation --- src/models/repositories/notification.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index 4d13940c76..ed9de7ef4c 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -153,10 +153,22 @@ export const packedNotificationSchema = { type: 'string' as const, optional: true as const, nullable: true as const, }, + choice: { + type: 'number' as const, + optional: true as const, nullable: true as const, + }, + invitation: { + type: 'object' as const, + optional: true as const, nullable: true as const, + }, body: { type: 'string' as const, optional: true as const, nullable: true as const, }, + header: { + type: 'string' as const, + optional: true as const, nullable: true as const, + }, icon: { type: 'string' as const, optional: true as const, nullable: true as const, From 75015c70446ac131955fa8ca592607e6c7ae3d9d Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 01:58:07 +0900 Subject: [PATCH 11/91] add header, choice, invitation --- src/models/repositories/notification.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index 4d13940c76..ed9de7ef4c 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -153,10 +153,22 @@ export const packedNotificationSchema = { type: 'string' as const, optional: true as const, nullable: true as const, }, + choice: { + type: 'number' as const, + optional: true as const, nullable: true as const, + }, + invitation: { + type: 'object' as const, + optional: true as const, nullable: true as const, + }, body: { type: 'string' as const, optional: true as const, nullable: true as const, }, + header: { + type: 'string' as const, + optional: true as const, nullable: true as const, + }, icon: { type: 'string' as const, optional: true as const, nullable: true as const, From ee03cd616020725e0f0478731704bfbfbe990efc Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 02:33:16 +0900 Subject: [PATCH 12/91] test --- src/misc/schema.ts | 13 ++++++++++++- src/models/repositories/blocking.ts | 2 +- src/models/repositories/notification.ts | 13 +++++++++++++ 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index e14e6e0dd7..8854ab5303 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -1,3 +1,6 @@ +import { packedNoteSchema } from "@/models/repositories/note"; +import { packedNotificationSchema } from "@/models/repositories/notification"; + export type Schema = { type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; nullable: boolean; @@ -43,11 +46,19 @@ type NullOrUndefined

= ? (T | undefined) : T; +export const refs = { + Note: packedNoteSchema, + Notification: packedNotificationSchema, +}; + export type SchemaType

= p['type'] extends 'number' ? NullOrUndefined : p['type'] extends 'string' ? NullOrUndefined : p['type'] extends 'boolean' ? NullOrUndefined : p['type'] extends 'array' ? NullOrUndefined>[]> : - p['type'] extends 'object' ? NullOrUndefined>> : + p['type'] extends 'object' ? + ( p['ref'] extends keyof typeof refs ? + NullOrUndefined> : + NullOrUndefined>> ) : p['type'] extends 'any' ? NullOrUndefined : any; diff --git a/src/models/repositories/blocking.ts b/src/models/repositories/blocking.ts index dd3a10905c..515b3a6b16 100644 --- a/src/models/repositories/blocking.ts +++ b/src/models/repositories/blocking.ts @@ -56,7 +56,7 @@ export const packedBlockingSchema = { blockee: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, } }; diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index ed9de7ef4c..584e3d8061 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -145,6 +145,19 @@ export const packedNotificationSchema = { format: 'id', }, note: { + type: 'object' as const, + ref: 'Note' as const, + optional: true as const, nullable: true as const, + }, + reaction: { + type: 'string' as const, + optional: true as const, nullable: true as const, + }, + choice: { + type: 'number' as const, + optional: true as const, nullable: true as const, + }, + invitation: { type: 'object' as const, ref: 'Note', optional: true as const, nullable: true as const, From 7ab97004d9d3630218e8f4a1754e2db1b0510cb4 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 02:49:21 +0900 Subject: [PATCH 13/91] fix --- src/models/repositories/notification.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index 584e3d8061..983fdaf6e8 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -162,18 +162,6 @@ export const packedNotificationSchema = { ref: 'Note', optional: true as const, nullable: true as const, }, - reaction: { - type: 'string' as const, - optional: true as const, nullable: true as const, - }, - choice: { - type: 'number' as const, - optional: true as const, nullable: true as const, - }, - invitation: { - type: 'object' as const, - optional: true as const, nullable: true as const, - }, body: { type: 'string' as const, optional: true as const, nullable: true as const, From d200424c6783b46906f520585ebbb763e291fd1c Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 02:49:38 +0900 Subject: [PATCH 14/91] fix --- src/models/repositories/notification.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index 584e3d8061..983fdaf6e8 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -162,18 +162,6 @@ export const packedNotificationSchema = { ref: 'Note', optional: true as const, nullable: true as const, }, - reaction: { - type: 'string' as const, - optional: true as const, nullable: true as const, - }, - choice: { - type: 'number' as const, - optional: true as const, nullable: true as const, - }, - invitation: { - type: 'object' as const, - optional: true as const, nullable: true as const, - }, body: { type: 'string' as const, optional: true as const, nullable: true as const, From c86ac1c6eca687f510fbbea26ab8b5040eadc0ab Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 03:26:19 +0900 Subject: [PATCH 15/91] yatta --- src/misc/schema.ts | 66 ++++++++++++++++---- src/models/repositories/clip.ts | 2 +- src/models/repositories/drive-file.ts | 4 +- src/models/repositories/drive-folder.ts | 2 +- src/models/repositories/following.ts | 4 +- src/models/repositories/gallery-post.ts | 6 +- src/models/repositories/messaging-message.ts | 8 +-- src/models/repositories/muting.ts | 2 +- src/models/repositories/note-favorite.ts | 2 +- src/models/repositories/note-reaction.ts | 2 +- src/models/repositories/note.ts | 12 ++-- src/models/repositories/notification.ts | 3 +- src/models/repositories/page.ts | 2 +- src/models/repositories/user.ts | 4 +- src/server/api/openapi/schemas.ts | 49 ++------------- 15 files changed, 84 insertions(+), 84 deletions(-) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index 8854ab5303..c4ca80249d 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -1,5 +1,50 @@ -import { packedNoteSchema } from "@/models/repositories/note"; -import { packedNotificationSchema } from "@/models/repositories/notification"; +import { packedUserSchema } from '@/models/repositories/user'; +import { packedNoteSchema } from '@/models/repositories/note'; +import { packedUserListSchema } from '@/models/repositories/user-list'; +import { packedAppSchema } from '@/models/repositories/app'; +import { packedMessagingMessageSchema } from '@/models/repositories/messaging-message'; +import { packedNotificationSchema } from '@/models/repositories/notification'; +import { packedDriveFileSchema } from '@/models/repositories/drive-file'; +import { packedDriveFolderSchema } from '@/models/repositories/drive-folder'; +import { packedFollowingSchema } from '@/models/repositories/following'; +import { packedMutingSchema } from '@/models/repositories/muting'; +import { packedBlockingSchema } from '@/models/repositories/blocking'; +import { packedNoteReactionSchema } from '@/models/repositories/note-reaction'; +import { packedHashtagSchema } from '@/models/repositories/hashtag'; +import { packedPageSchema } from '@/models/repositories/page'; +import { packedUserGroupSchema } from '@/models/repositories/user-group'; +import { packedNoteFavoriteSchema } from '@/models/repositories/note-favorite'; +import { packedChannelSchema } from '@/models/repositories/channel'; +import { packedAntennaSchema } from '@/models/repositories/antenna'; +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'; + +export const refs = { + User: packedUserSchema, + UserList: packedUserListSchema, + UserGroup: packedUserGroupSchema, + App: packedAppSchema, + MessagingMessage: packedMessagingMessageSchema, + Note: packedNoteSchema, + NoteReaction: packedNoteReactionSchema, + NoteFavorite: packedNoteFavoriteSchema, + Notification: packedNotificationSchema, + DriveFile: packedDriveFileSchema, + DriveFolder: packedDriveFolderSchema, + Following: packedFollowingSchema, + Muting: packedMutingSchema, + Blocking: packedBlockingSchema, + Hashtag: packedHashtagSchema, + Page: packedPageSchema, + Channel: packedChannelSchema, + QueueCount: packedQueueCountSchema, + Antenna: packedAntennaSchema, + Clip: packedClipSchema, + FederationInstance: packedFederationInstanceSchema, + GalleryPost: packedGalleryPostSchema, +}; export type Schema = { type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; @@ -10,8 +55,9 @@ export type Schema = { description?: string; example?: any; format?: string; - ref?: string; + ref?: keyof typeof refs; enum?: string[]; + default?: boolean | null; }; type NonUndefinedPropertyNames = { @@ -46,19 +92,15 @@ type NullOrUndefined

= ? (T | undefined) : T; -export const refs = { - Note: packedNoteSchema, - Notification: packedNotificationSchema, -}; - export type SchemaType

= p['type'] extends 'number' ? NullOrUndefined : p['type'] extends 'string' ? NullOrUndefined : p['type'] extends 'boolean' ? NullOrUndefined : p['type'] extends 'array' ? NullOrUndefined>[]> : - p['type'] extends 'object' ? - ( p['ref'] extends keyof typeof refs ? - NullOrUndefined> : - NullOrUndefined>> ) : + p['type'] extends 'object' ? ( + p['ref'] extends keyof typeof refs + ? NullOrUndefined> + : NullOrUndefined>> + ) : p['type'] extends 'any' ? NullOrUndefined : any; diff --git a/src/models/repositories/clip.ts b/src/models/repositories/clip.ts index 49dc3a332e..e3d718bef4 100644 --- a/src/models/repositories/clip.ts +++ b/src/models/repositories/clip.ts @@ -53,7 +53,7 @@ export const packedClipSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: false as const, nullable: false as const, }, name: { diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts index 42a60ff03c..63bd020cbe 100644 --- a/src/models/repositories/drive-file.ts +++ b/src/models/repositories/drive-file.ts @@ -234,7 +234,7 @@ export const packedDriveFileSchema = { folder: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'DriveFolder' + ref: 'DriveFolder' as const, }, userId: { type: 'string' as const, @@ -245,7 +245,7 @@ export const packedDriveFileSchema = { user: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'User' + ref: 'User' as const, } }, }; diff --git a/src/models/repositories/drive-folder.ts b/src/models/repositories/drive-folder.ts index 4228284f82..bc73018f29 100644 --- a/src/models/repositories/drive-folder.ts +++ b/src/models/repositories/drive-folder.ts @@ -87,7 +87,7 @@ export const packedDriveFolderSchema = { parent: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'DriveFolder' + ref: 'DriveFolder' as const, }, }, }; diff --git a/src/models/repositories/following.ts b/src/models/repositories/following.ts index 3bb120bc4b..24ddd0d676 100644 --- a/src/models/repositories/following.ts +++ b/src/models/repositories/following.ts @@ -110,7 +110,7 @@ export const packedFollowingSchema = { followee: { type: 'object' as const, optional: true as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, followerId: { type: 'string' as const, @@ -120,7 +120,7 @@ export const packedFollowingSchema = { follower: { type: 'object' as const, optional: true as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, } }; diff --git a/src/models/repositories/gallery-post.ts b/src/models/repositories/gallery-post.ts index 03edb35213..afa22e9edf 100644 --- a/src/models/repositories/gallery-post.ts +++ b/src/models/repositories/gallery-post.ts @@ -1,6 +1,6 @@ import { EntityRepository, Repository } from 'typeorm'; import { GalleryPost } from '@/models/entities/gallery-post'; -import { SchemaType } from '../../misc/schema'; +import { SchemaType } from '@/misc/schema'; import { Users, DriveFiles, GalleryLikes } from '../index'; import { awaitAll } from '@/prelude/await-all'; import { User } from '@/models/entities/user'; @@ -76,7 +76,7 @@ export const packedGalleryPostSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: false as const, nullable: false as const, }, fileIds: { @@ -94,7 +94,7 @@ export const packedGalleryPostSchema = { items: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'DriveFile' + ref: 'DriveFile' as const, } }, tags: { diff --git a/src/models/repositories/messaging-message.ts b/src/models/repositories/messaging-message.ts index 1a4a8eecc4..f97905af2f 100644 --- a/src/models/repositories/messaging-message.ts +++ b/src/models/repositories/messaging-message.ts @@ -67,7 +67,7 @@ export const packedMessagingMessageSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: true as const, nullable: false as const, }, text: { @@ -82,7 +82,7 @@ export const packedMessagingMessageSchema = { file: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'DriveFile', + ref: 'DriveFile' as const, }, recipientId: { type: 'string' as const, @@ -92,7 +92,7 @@ export const packedMessagingMessageSchema = { recipient: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'User' + ref: 'User' as const, }, groupId: { type: 'string' as const, @@ -102,7 +102,7 @@ export const packedMessagingMessageSchema = { group: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'UserGroup' + ref: 'UserGroup' as const, }, isRead: { type: 'boolean' as const, diff --git a/src/models/repositories/muting.ts b/src/models/repositories/muting.ts index e46f4ae448..d957b1792d 100644 --- a/src/models/repositories/muting.ts +++ b/src/models/repositories/muting.ts @@ -56,7 +56,7 @@ export const packedMutingSchema = { mutee: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, } }; diff --git a/src/models/repositories/note-favorite.ts b/src/models/repositories/note-favorite.ts index 3248c32ded..47586a9116 100644 --- a/src/models/repositories/note-favorite.ts +++ b/src/models/repositories/note-favorite.ts @@ -45,7 +45,7 @@ export const packedNoteFavoriteSchema = { note: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'Note', + ref: 'Note' as const, }, noteId: { type: 'string' as const, diff --git a/src/models/repositories/note-reaction.ts b/src/models/repositories/note-reaction.ts index c349edf182..e73a832109 100644 --- a/src/models/repositories/note-reaction.ts +++ b/src/models/repositories/note-reaction.ts @@ -42,7 +42,7 @@ export const packedNoteReactionSchema = { user: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'User', + ref: 'User' as const, }, type: { type: 'string' as const, diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index 9e0f5e55f0..ac4df222dc 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -3,7 +3,7 @@ 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 { Schema, SchemaType } from '@/misc/schema'; import { nyaize } from '@/misc/nyaize'; import { awaitAll } from '@/prelude/await-all'; import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '@/misc/reaction-lib'; @@ -353,7 +353,7 @@ export const packedNoteSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: false as const, nullable: false as const, }, replyId: { @@ -371,12 +371,12 @@ export const packedNoteSchema = { reply: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'Note' + ref: 'Note' as const, }, renote: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'Note' + ref: 'Note' as const, }, viaMobile: { type: 'boolean' as const, @@ -423,7 +423,7 @@ export const packedNoteSchema = { items: { type: 'object' as const, optional: false as const, nullable: false as const, - ref: 'DriveFile' + ref: 'DriveFile' as const, } }, tags: { @@ -447,7 +447,7 @@ export const packedNoteSchema = { channel: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'Channel' + ref: 'Channel' as const, }, localOnly: { type: 'boolean' as const, diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index 983fdaf6e8..b7f9e3643c 100644 --- a/src/models/repositories/notification.ts +++ b/src/models/repositories/notification.ts @@ -136,7 +136,7 @@ export const packedNotificationSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: true as const, nullable: true as const, }, userId: { @@ -159,7 +159,6 @@ export const packedNotificationSchema = { }, invitation: { type: 'object' as const, - ref: 'Note', optional: true as const, nullable: true as const, }, body: { diff --git a/src/models/repositories/page.ts b/src/models/repositories/page.ts index 757aaa5a3f..1a61e2c99c 100644 --- a/src/models/repositories/page.ts +++ b/src/models/repositories/page.ts @@ -137,7 +137,7 @@ export const packedPageSchema = { }, user: { type: 'object' as const, - ref: 'User', + ref: 'User' as const, optional: false as const, nullable: false as const, }, } diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index d4bb995ce2..4a6534b557 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -520,7 +520,7 @@ export const packedUserSchema = { items: { type: 'object' as const, nullable: false as const, optional: false as const, - ref: 'Note' + ref: 'Note' as const, } }, pinnedPageId: { @@ -530,7 +530,7 @@ export const packedUserSchema = { pinnedPage: { type: 'object' as const, nullable: true as const, optional: false as const, - ref: 'Page' + ref: 'Page' as const, }, twoFactorEnabled: { type: 'boolean' as const, diff --git a/src/server/api/openapi/schemas.ts b/src/server/api/openapi/schemas.ts index 5402dc6f48..12fc207c47 100644 --- a/src/server/api/openapi/schemas.ts +++ b/src/server/api/openapi/schemas.ts @@ -1,26 +1,4 @@ -import { packedUserSchema } from '@/models/repositories/user'; -import { Schema } from '@/misc/schema'; -import { packedNoteSchema } from '@/models/repositories/note'; -import { packedUserListSchema } from '@/models/repositories/user-list'; -import { packedAppSchema } from '@/models/repositories/app'; -import { packedMessagingMessageSchema } from '@/models/repositories/messaging-message'; -import { packedNotificationSchema } from '@/models/repositories/notification'; -import { packedDriveFileSchema } from '@/models/repositories/drive-file'; -import { packedDriveFolderSchema } from '@/models/repositories/drive-folder'; -import { packedFollowingSchema } from '@/models/repositories/following'; -import { packedMutingSchema } from '@/models/repositories/muting'; -import { packedBlockingSchema } from '@/models/repositories/blocking'; -import { packedNoteReactionSchema } from '@/models/repositories/note-reaction'; -import { packedHashtagSchema } from '@/models/repositories/hashtag'; -import { packedPageSchema } from '@/models/repositories/page'; -import { packedUserGroupSchema } from '@/models/repositories/user-group'; -import { packedNoteFavoriteSchema } from '@/models/repositories/note-favorite'; -import { packedChannelSchema } from '@/models/repositories/channel'; -import { packedAntennaSchema } from '@/models/repositories/antenna'; -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 { refs, Schema } from '@/misc/schema'; export function convertSchemaToOpenApiSchema(schema: Schema) { const res: any = schema; @@ -72,26 +50,7 @@ export const schemas = { required: ['error'] }, - User: convertSchemaToOpenApiSchema(packedUserSchema), - UserList: convertSchemaToOpenApiSchema(packedUserListSchema), - UserGroup: convertSchemaToOpenApiSchema(packedUserGroupSchema), - App: convertSchemaToOpenApiSchema(packedAppSchema), - MessagingMessage: convertSchemaToOpenApiSchema(packedMessagingMessageSchema), - Note: convertSchemaToOpenApiSchema(packedNoteSchema), - NoteReaction: convertSchemaToOpenApiSchema(packedNoteReactionSchema), - NoteFavorite: convertSchemaToOpenApiSchema(packedNoteFavoriteSchema), - Notification: convertSchemaToOpenApiSchema(packedNotificationSchema), - DriveFile: convertSchemaToOpenApiSchema(packedDriveFileSchema), - DriveFolder: convertSchemaToOpenApiSchema(packedDriveFolderSchema), - Following: convertSchemaToOpenApiSchema(packedFollowingSchema), - Muting: convertSchemaToOpenApiSchema(packedMutingSchema), - Blocking: convertSchemaToOpenApiSchema(packedBlockingSchema), - Hashtag: convertSchemaToOpenApiSchema(packedHashtagSchema), - Page: convertSchemaToOpenApiSchema(packedPageSchema), - Channel: convertSchemaToOpenApiSchema(packedChannelSchema), - QueueCount: convertSchemaToOpenApiSchema(packedQueueCountSchema), - Antenna: convertSchemaToOpenApiSchema(packedAntennaSchema), - Clip: convertSchemaToOpenApiSchema(packedClipSchema), - FederationInstance: convertSchemaToOpenApiSchema(packedFederationInstanceSchema), - GalleryPost: convertSchemaToOpenApiSchema(packedGalleryPostSchema), + ...Object.fromEntries( + Object.entries(refs).map(([key, schema]) => [key, convertSchemaToOpenApiSchema(schema)]) + ), }; From 93fd76f84127c6e0523d6eb731c2a9fcf2f4c349 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 03:32:52 +0900 Subject: [PATCH 16/91] remove no longer needed "as PackedUser/PackedNote" --- src/models/repositories/note.ts | 2 +- src/server/api/stream/channels/global-timeline.ts | 2 +- src/server/api/stream/channels/home-timeline.ts | 2 +- src/server/api/stream/channels/hybrid-timeline.ts | 5 ++--- src/server/api/stream/channels/local-timeline.ts | 5 ++--- src/server/api/stream/index.ts | 4 ++-- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index ac4df222dc..52f841b526 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -95,7 +95,7 @@ export class NoteRepository extends Repository { hide = true; } else if (meId === packedNote.userId) { hide = false; - } else if (packedNote.reply && (meId === (packedNote.reply as PackedNote).userId)) { + } else if (packedNote.reply && (meId === packedNote.reply.userId)) { // 自分の投稿に対するリプライ hide = false; } else if (packedNote.mentions && packedNote.mentions.some(id => meId === id)) { diff --git a/src/server/api/stream/channels/global-timeline.ts b/src/server/api/stream/channels/global-timeline.ts index 2cb138966f..384ed61409 100644 --- a/src/server/api/stream/channels/global-timeline.ts +++ b/src/server/api/stream/channels/global-timeline.ts @@ -43,7 +43,7 @@ export default class extends Channel { // 関係ない返信は除外 if (note.reply) { - const reply = note.reply as PackedNote; + const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts index c7a9728741..0e21ab552e 100644 --- a/src/server/api/stream/channels/home-timeline.ts +++ b/src/server/api/stream/channels/home-timeline.ts @@ -51,7 +51,7 @@ export default class extends Channel { // 関係ない返信は除外 if (note.reply) { - const reply = note.reply as PackedNote; + const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } diff --git a/src/server/api/stream/channels/hybrid-timeline.ts b/src/server/api/stream/channels/hybrid-timeline.ts index 5c454764ec..0b28ff616b 100644 --- a/src/server/api/stream/channels/hybrid-timeline.ts +++ b/src/server/api/stream/channels/hybrid-timeline.ts @@ -4,7 +4,6 @@ import Channel from '../channel'; import { fetchMeta } from '@/misc/fetch-meta'; import { Notes } from '@/models/index'; import { PackedNote } from '@/models/repositories/note'; -import { PackedUser } from '@/models/repositories/user'; import { checkWordMute } from '@/misc/check-word-mute'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; @@ -31,7 +30,7 @@ export default class extends Channel { if (!( (note.channelId == null && this.user!.id === note.userId) || (note.channelId == null && this.following.has(note.userId)) || - (note.channelId == null && ((note.user as PackedUser).host == null && note.visibility === 'public')) || + (note.channelId == null && (note.user.host == null && note.visibility === 'public')) || (note.channelId != null && this.followingChannels.has(note.channelId)) )) return; @@ -60,7 +59,7 @@ export default class extends Channel { // 関係ない返信は除外 if (note.reply) { - const reply = note.reply as PackedNote; + const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } diff --git a/src/server/api/stream/channels/local-timeline.ts b/src/server/api/stream/channels/local-timeline.ts index 4bf0d02ed3..20061410c4 100644 --- a/src/server/api/stream/channels/local-timeline.ts +++ b/src/server/api/stream/channels/local-timeline.ts @@ -4,7 +4,6 @@ import Channel from '../channel'; import { fetchMeta } from '@/misc/fetch-meta'; import { Notes } from '@/models/index'; import { PackedNote } from '@/models/repositories/note'; -import { PackedUser } from '@/models/repositories/user'; import { checkWordMute } from '@/misc/check-word-mute'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; @@ -26,7 +25,7 @@ export default class extends Channel { @autobind private async onNote(note: PackedNote) { - if ((note.user as PackedUser).host !== null) return; + if (note.user.host !== null) return; if (note.visibility !== 'public') return; if (note.channelId != null && !this.followingChannels.has(note.channelId)) return; @@ -45,7 +44,7 @@ export default class extends Channel { // 関係ない返信は除外 if (note.reply) { - const reply = note.reply as PackedNote; + const reply = note.reply; // 「チャンネル接続主への返信」でもなければ、「チャンネル接続主が行った返信」でもなければ、「投稿者の投稿者自身への返信」でもない場合 if (reply.userId !== this.user!.id && note.userId !== this.user!.id && reply.userId !== note.userId) return; } diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 469f28f11c..f83bc9331e 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -165,8 +165,8 @@ export default class Connection { }; add(note); - if (note.reply) add(note.reply as PackedNote); - if (note.renote) add(note.renote as PackedNote); + if (note.reply) add(note.reply); + if (note.renote) add(note.renote); } @autobind From f89a326d7f56eacfbfd77062d7250b008f657279 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 03:34:21 +0900 Subject: [PATCH 17/91] clean up --- src/models/repositories/note.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index 52f841b526..77fedd791f 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -3,7 +3,7 @@ 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 { Schema, SchemaType } from '@/misc/schema'; +import { SchemaType } from '@/misc/schema'; import { nyaize } from '@/misc/nyaize'; import { awaitAll } from '@/prelude/await-all'; import { convertLegacyReaction, convertLegacyReactions, decodeReaction } from '@/misc/reaction-lib'; From abbeb9a0718759c8d92bd2ec4db51010ee64767f Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 12:59:51 +0900 Subject: [PATCH 18/91] add simple-schema --- src/misc/schema.ts | 14 +++----------- src/misc/simple-schema.ts | 15 +++++++++++++++ src/server/api/endpoints.ts | 4 ++-- src/services/chart/core.ts | 14 +++++++------- test/utils.ts | 2 +- 5 files changed, 28 insertions(+), 21 deletions(-) create mode 100644 src/misc/simple-schema.ts diff --git a/src/misc/schema.ts b/src/misc/schema.ts index c4ca80249d..f6fb128751 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -1,3 +1,4 @@ +import { SimpleObj, SimpleSchema } from './simple-schema'; import { packedUserSchema } from '@/models/repositories/user'; import { packedNoteSchema } from '@/models/repositories/note'; import { packedUserListSchema } from '@/models/repositories/user-list'; @@ -46,18 +47,9 @@ export const refs = { GalleryPost: packedGalleryPostSchema, }; -export type Schema = { - type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; - nullable: boolean; - optional: boolean; - items?: Schema; +export interface Schema extends SimpleSchema { properties?: Obj; - description?: string; - example?: any; - format?: string; ref?: keyof typeof refs; - enum?: string[]; - default?: boolean | null; }; type NonUndefinedPropertyNames = { @@ -71,7 +63,7 @@ type UndefinedPropertyNames = { type OnlyRequired = Pick>; type OnlyOptional = Pick>; -export type Obj = { [key: string]: Schema }; +export interface Obj extends SimpleObj { [key: string]: Schema }; export type ObjType = { [P in keyof OnlyOptional]?: SchemaType } & diff --git a/src/misc/simple-schema.ts b/src/misc/simple-schema.ts new file mode 100644 index 0000000000..83590edbf2 --- /dev/null +++ b/src/misc/simple-schema.ts @@ -0,0 +1,15 @@ +export interface SimpleSchema { + type: 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; + nullable: boolean; + optional: boolean; + items?: SimpleSchema; + properties?: SimpleObj; + description?: string; + example?: any; + format?: string; + ref?: string; + enum?: string[]; + default?: boolean | null; +}; + +export type SimpleObj = { [key: string]: SimpleSchema }; diff --git a/src/server/api/endpoints.ts b/src/server/api/endpoints.ts index 640b14ed6a..6d9d2b0782 100644 --- a/src/server/api/endpoints.ts +++ b/src/server/api/endpoints.ts @@ -3,7 +3,7 @@ import { dirname } from 'path'; import { Context } from 'cafy'; import * as path from 'path'; import * as glob from 'glob'; -import { Schema } from '@/misc/schema'; +import { SimpleSchema } from '@/misc/simple-schema'; //const _filename = fileURLToPath(import.meta.url); const _filename = __filename; @@ -34,7 +34,7 @@ export interface IEndpointMeta { }; }; - res?: Schema; + res?: SimpleSchema; /** * このエンドポイントにリクエストするのにユーザー情報が必須か否か diff --git a/src/services/chart/core.ts b/src/services/chart/core.ts index eee7d20efb..c0d3280c2b 100644 --- a/src/services/chart/core.ts +++ b/src/services/chart/core.ts @@ -7,7 +7,7 @@ import * as nestedProperty from 'nested-property'; import autobind from 'autobind-decorator'; import Logger from '../logger'; -import { Schema } from '@/misc/schema'; +import { SimpleSchema } from '@/misc/simple-schema'; import { EntitySchema, getRepository, Repository, LessThan, Between } from 'typeorm'; import { dateUTC, isTimeSame, isTimeBefore, subtractTime, addTime } from '@/prelude/time'; import { getChartInsertLock } from '@/misc/app-lock'; @@ -56,7 +56,7 @@ export default abstract class Chart> { diff: DeepPartial; group: string | null; }[] = []; - public schema: Schema; + public schema: SimpleSchema; protected repository: Repository; protected abstract genNewLog(latest: T): DeepPartial; @@ -69,7 +69,7 @@ export default abstract class Chart> { protected abstract fetchActual(group: string | null): Promise>; @autobind - private static convertSchemaToFlatColumnDefinitions(schema: Schema) { + private static convertSchemaToFlatColumnDefinitions(schema: SimpleSchema) { const columns = {} as any; const flatColumns = (x: Obj, path?: string) => { for (const [k, v] of Object.entries(x)) { @@ -181,7 +181,7 @@ export default abstract class Chart> { } @autobind - public static schemaToEntity(name: string, schema: Schema): EntitySchema { + public static schemaToEntity(name: string, schema: SimpleSchema): EntitySchema { return new EntitySchema({ name: `__chart__${camelToSnake(name)}`, columns: { @@ -211,7 +211,7 @@ export default abstract class Chart> { }); } - constructor(name: string, schema: Schema, grouped = false) { + constructor(name: string, schema: SimpleSchema, grouped = false) { this.name = name; this.schema = schema; const entity = Chart.schemaToEntity(name, schema); @@ -546,8 +546,8 @@ export default abstract class Chart> { } } -export function convertLog(logSchema: Schema): Schema { - const v: Schema = JSON.parse(JSON.stringify(logSchema)); // copy +export function convertLog(logSchema: SimpleSchema): SimpleSchema { + const v: SimpleSchema = JSON.parse(JSON.stringify(logSchema)); // copy if (v.type === 'number') { v.type = 'array'; v.items = { diff --git a/test/utils.ts b/test/utils.ts index 1a0c54463d..253c410bf0 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -158,7 +158,7 @@ export async function initTestDb(justBorrow = false, initEntities?: any[]) { await conn.close(); } catch (e) {} - return await createConnection({ + return createConnection({ type: 'postgres', host: config.db.host, port: config.db.port, From 02dbdc54c310be173550709a4ae43b885800c92d Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 13:08:51 +0900 Subject: [PATCH 19/91] fix lint --- src/misc/schema.ts | 4 ++-- src/misc/simple-schema.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index f6fb128751..90d4c3b715 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -50,7 +50,7 @@ export const refs = { export interface Schema extends SimpleSchema { properties?: Obj; ref?: keyof typeof refs; -}; +} type NonUndefinedPropertyNames = { [K in keyof T]: T[K]['optional'] extends true ? never : K @@ -63,7 +63,7 @@ type UndefinedPropertyNames = { type OnlyRequired = Pick>; type OnlyOptional = Pick>; -export interface Obj extends SimpleObj { [key: string]: Schema }; +export interface Obj extends SimpleObj { [key: string]: Schema; } export type ObjType = { [P in keyof OnlyOptional]?: SchemaType } & diff --git a/src/misc/simple-schema.ts b/src/misc/simple-schema.ts index 83590edbf2..abbb348e24 100644 --- a/src/misc/simple-schema.ts +++ b/src/misc/simple-schema.ts @@ -10,6 +10,6 @@ export interface SimpleSchema { ref?: string; enum?: string[]; default?: boolean | null; -}; +} -export type SimpleObj = { [key: string]: SimpleSchema }; +export interface SimpleObj { [key: string]: SimpleSchema; } From ca82538e10c34cc7266fd2d2dc8795a439f33e9a Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 17:16:30 +0900 Subject: [PATCH 20/91] fix lint --- src/server/api/stream/types.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 549af96fa8..e0c76306bd 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -19,7 +19,7 @@ type EventUnionFromDictionary< type EventUnionFromMkJSTypes< T extends { [key: string]: ((payload: any) => void) | (() => void) }, U = { [K in keyof T]: { type: K; body: Payload} } -> = U[keyof U] +> = U[keyof U]; export type BroadcastStream = EventUnionFromMkJSTypes; @@ -33,11 +33,11 @@ export interface UserEventTypes { follow: PackedUser; unfollow: PackedUser; userAdded: PackedUser; -}; +} export type UserEventName = `user:${User['id']}`; export type UserEvents = EventUnionFromDictionary; -export interface mainStreamTypes { +export interface MainStreamTypes { notification: PackedNotification; mention: PackedNote; reply: PackedNote; @@ -62,9 +62,9 @@ export interface mainStreamTypes { readAllChannels: never; unreadChannel: never; myTokenRegenerated: never; -}; +} export type mainStreamName = `mainStream:${User['id']}`; -export type mainStreams = EventUnionFromDictionary; +export type mainStreams = EventUnionFromDictionary; interface StreamEvents { 'broadcast': (e: BroadcastStream) => void; From dd175a8e6ee0093d2711bd1bcde9ea7f5fc099fc Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 17:56:17 +0900 Subject: [PATCH 21/91] wip --- src/server/api/stream/index.ts | 4 +- src/server/api/stream/types.ts | 95 ++++++++++++++++++++++++++++++---- 2 files changed, 87 insertions(+), 12 deletions(-) diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 0101e6e079..b2cecb4470 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -15,7 +15,7 @@ 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 { StreamEventEmitter, UserEvents } from './types'; +import { StreamEventEmitter, UserStreams } from './types'; /** * Main stream connection @@ -65,7 +65,7 @@ export default class Connection { } @autobind - private onUserEvent(ev: UserEvents) { // { type, body }と展開すると型も展開されてしまう + private onUserEvent(ev: UserStreams) { // { type, body }と展開すると型も展開されてしまう switch (ev.type) { case 'follow': this.following.add(ev.body.id); diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index e0c76306bd..3803e6dcea 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -7,23 +7,46 @@ import { UserProfile } from '@/models/entities/user-profile'; import { PackedUser } from '@/models/repositories/user'; import { PackedNotification } from '@/models/repositories/notification'; import { PackedNote } from '@/models/repositories/note'; +import { Antenna } from '@/models/entities/antenna'; +import { DriveFile } from '@/models/entities/drive-file'; +import { PackedDriveFile } from '@/models/repositories/drive-file'; +import { PackedDriveFolder } from '@/models/repositories/drive-folder'; +import { DriveFolder } from '@/models/entities/drive-folder'; +import { Note } from '@/models/entities/note'; +import { Emoji } from '@/models/entities/emoji'; -type Payload void> = T extends (payload: infer P) => void ? P : never; - +// 辞書(interface or type)から{ type, body }ユニオンを定義 // https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type type EventUnionFromDictionary< T extends object, U = { [K in keyof T]: { type: K; body: T[K]} } > = U[keyof U]; +// (payload: P) => void からPを取り出す +type Payload void> = T extends (payload: infer P) => void ? P : never; + +// misskey.jsのstreaming.typesの辞書から{ type, body }ユニオンを定義 type EventUnionFromMkJSTypes< T extends { [key: string]: ((payload: any) => void) | (() => void) }, U = { [K in keyof T]: { type: K; body: Payload} } > = U[keyof U]; -export type BroadcastStream = EventUnionFromMkJSTypes; +//#region Stream type-body definitions -export interface UserEventTypes { +// internal +export interface InternalStreamTypes { + antennaCreated: Antenna; + antennaDeleted: Antenna; + antennaUpdated: Antenna; +} +export type InternalStreams = EventUnionFromDictionary; + +// broadcast +export type BroadcastStreams = EventUnionFromMkJSTypes; + +// user +export type UserEventName = `user:${User['id']}`; +export interface UserStreamTypes { terminate: {}; followChannel: Channel; unfollowChannel: Channel; @@ -34,9 +57,10 @@ export interface UserEventTypes { unfollow: PackedUser; userAdded: PackedUser; } -export type UserEventName = `user:${User['id']}`; -export type UserEvents = EventUnionFromDictionary; +export type UserStreams = EventUnionFromDictionary; +// main +export type mainStreamName = `mainStream:${User['id']}`; export interface MainStreamTypes { notification: PackedNotification; mention: PackedNote; @@ -63,17 +87,68 @@ export interface MainStreamTypes { unreadChannel: never; myTokenRegenerated: never; } -export type mainStreamName = `mainStream:${User['id']}`; export type mainStreams = EventUnionFromDictionary; +// drive +export type driveStreamName = `driveStream:${User['id']}`; +export interface DriveStreamTypes { + fileCreated: PackedDriveFile; + fileDeleted: DriveFile['id']; + fileUpdated: PackedDriveFile; + folderCreated: PackedDriveFolder; + folderDeleted: DriveFolder['id']; + folderUpdated: PackedDriveFolder; +} +export type driveStreams= EventUnionFromDictionary; + +// note +export type noteStreamName = `noteStream:${Note['id']}`; +export interface NoteStreamTypes { + pollVoted: { + id: Note['id']; + body: { + choice: number; + userId: User['id']; + }; + }; + deleted: { + id: Note['id']; + body: { + deletedAt: Date; + }; + }; + reacted: { + id: Note['id']; + body: { + reaction: string; + emoji?: Emoji; + userId: User['id']; + }; + }; + unreacted: { + id: Note['id']; + body: { + reaction: string; + userId: User['id']; + } + }; +} +export type noteStreams = EventUnionFromDictionary; + +//#endregion + +//#region API event definitions interface StreamEvents { - 'broadcast': (e: BroadcastStream) => void; + 'broadcast': (e: BroadcastStreams) => void; + 'internal': (e: InternalStreams) => void; } interface AuthenticatedStreamEvents { - [key: UserEventName]: (e: UserEvents) => void; + [key: UserEventName]: (e: UserStreams) => void; [key: mainStreamName]: (e: mainStreams) => void; - [key: `driveStream:${User['id']}`]: (e: { type: string; body: any }) => void; + [key: driveStreamName]: (e: driveStreams) => void; + [key: noteStreamName]: (e: noteStreams) => void; } export type StreamEventEmitter = Emitter; +//#endregion From 70740c5e6d516dd5dceae35b68b4ea8189fb4d4e Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 18:29:23 +0900 Subject: [PATCH 22/91] wip! --- src/server/api/stream/types.ts | 67 +++++++++++++++++----------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 3803e6dcea..e35a810ac7 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -32,20 +32,12 @@ type EventUnionFromMkJSTypes< > = U[keyof U]; //#region Stream type-body definitions - -// internal export interface InternalStreamTypes { antennaCreated: Antenna; antennaDeleted: Antenna; antennaUpdated: Antenna; } -export type InternalStreams = EventUnionFromDictionary; -// broadcast -export type BroadcastStreams = EventUnionFromMkJSTypes; - -// user -export type UserEventName = `user:${User['id']}`; export interface UserStreamTypes { terminate: {}; followChannel: Channel; @@ -57,10 +49,7 @@ export interface UserStreamTypes { unfollow: PackedUser; userAdded: PackedUser; } -export type UserStreams = EventUnionFromDictionary; -// main -export type mainStreamName = `mainStream:${User['id']}`; export interface MainStreamTypes { notification: PackedNotification; mention: PackedNote; @@ -87,10 +76,7 @@ export interface MainStreamTypes { unreadChannel: never; myTokenRegenerated: never; } -export type mainStreams = EventUnionFromDictionary; -// drive -export type driveStreamName = `driveStream:${User['id']}`; export interface DriveStreamTypes { fileCreated: PackedDriveFile; fileDeleted: DriveFile['id']; @@ -99,10 +85,7 @@ export interface DriveStreamTypes { folderDeleted: DriveFolder['id']; folderUpdated: PackedDriveFolder; } -export type driveStreams= EventUnionFromDictionary; -// note -export type noteStreamName = `noteStream:${Note['id']}`; export interface NoteStreamTypes { pollVoted: { id: Note['id']; @@ -133,22 +116,40 @@ export interface NoteStreamTypes { } }; } -export type noteStreams = EventUnionFromDictionary; + +//#endregion +//#region 名前とメッセージのペアを中間生成 +interface StreamMessages { + internal: { + name: 'internal'; + spec: EventUnionFromDictionary; + }; + broadcast: { + name: 'bloadcast'; + spec: EventUnionFromMkJSTypes; + }; + user: { + name: `user:${User['id']}`; + spec: EventUnionFromDictionary; + }; + main: { + name: `mainStream:${User['id']}`; + spec: EventUnionFromDictionary; + }; + drive: { + name: `driveStream:${User['id']}`; + spec: EventUnionFromDictionary; + }; + note: { + name: `noteStream:${Note['id']}`; + spec: EventUnionFromDictionary; + } +} //#endregion -//#region API event definitions -interface StreamEvents { - 'broadcast': (e: BroadcastStreams) => void; - 'internal': (e: InternalStreams) => void; -} - -interface AuthenticatedStreamEvents { - [key: UserEventName]: (e: UserStreams) => void; - [key: mainStreamName]: (e: mainStreams) => void; - [key: driveStreamName]: (e: driveStreams) => void; - [key: noteStreamName]: (e: noteStreams) => void; -} - -export type StreamEventEmitter = Emitter; -//#endregion +// API event definitions +type Events = { + [x in S[T]['name']]: (e: S[T]['spec']) => void +}; +export type StreamEventEmitter = Emitter>; From ac3dbcb11444f6707b3062f3f9a0491c250e451d Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 20:20:39 +0900 Subject: [PATCH 23/91] wip --- src/server/api/stream/types.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index e35a810ac7..32ba414b30 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -149,7 +149,5 @@ interface StreamMessages { //#endregion // API event definitions -type Events = { - [x in S[T]['name']]: (e: S[T]['spec']) => void -}; -export type StreamEventEmitter = Emitter>; +type EventsGenerater = { [key in StreamMessages[K]['name']]: (e: StreamMessages[K]['spec']) => void }; +export type StreamEventEmitter = Emitter>; From 35007055852f28da86cc4cbebdc97bd0373f2561 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 20:21:05 +0900 Subject: [PATCH 24/91] fix --- src/server/api/stream/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 32ba414b30..18eba58538 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -125,7 +125,7 @@ interface StreamMessages { spec: EventUnionFromDictionary; }; broadcast: { - name: 'bloadcast'; + name: 'broadcast'; spec: EventUnionFromMkJSTypes; }; user: { From f4652ec4ac6e1ee3a9daa85586a7685c3907381e Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 22:12:07 +0900 Subject: [PATCH 25/91] wip --- src/models/repositories/emoji.ts | 2 + src/models/repositories/games/reversi/game.ts | 2 + .../repositories/games/reversi/matching.ts | 2 + .../api/common/read-messaging-message.ts | 2 +- src/server/api/endpoints/antennas/update.ts | 2 +- src/server/api/stream/channels/channel.ts | 2 +- src/server/api/stream/types.ts | 154 ++++++++++++++++-- src/services/stream.ts | 9 +- 8 files changed, 158 insertions(+), 17 deletions(-) diff --git a/src/models/repositories/emoji.ts b/src/models/repositories/emoji.ts index c3d7184ec9..1bbe6b8215 100644 --- a/src/models/repositories/emoji.ts +++ b/src/models/repositories/emoji.ts @@ -1,6 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Emoji } from '@/models/entities/emoji'; +export type PackedEmoji = FIXME; + @EntityRepository(Emoji) export class EmojiRepository extends Repository { public async pack( diff --git a/src/models/repositories/games/reversi/game.ts b/src/models/repositories/games/reversi/game.ts index dc91ad51b8..eb2561be91 100644 --- a/src/models/repositories/games/reversi/game.ts +++ b/src/models/repositories/games/reversi/game.ts @@ -3,6 +3,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../../../index'; import { ReversiGame } from '@/models/entities/games/reversi/game'; +export type PackedReversiGame = FIXME; + @EntityRepository(ReversiGame) export class ReversiGameRepository extends Repository { public async pack( diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts index 148221dee5..91615091ac 100644 --- a/src/models/repositories/games/reversi/matching.ts +++ b/src/models/repositories/games/reversi/matching.ts @@ -4,6 +4,8 @@ import { Users } from '../../../index'; import { awaitAll } from '@/prelude/await-all'; import { User } from '@/models/entities/user'; +export type PackedReversiMatching = FIXME; + @EntityRepository(ReversiMatching) export class ReversiMatchingRepository extends Repository { public async pack( diff --git a/src/server/api/common/read-messaging-message.ts b/src/server/api/common/read-messaging-message.ts index 1dce76d2a9..33f41b2770 100644 --- a/src/server/api/common/read-messaging-message.ts +++ b/src/server/api/common/read-messaging-message.ts @@ -77,7 +77,7 @@ export async function readGroupMessagingMessage( id: In(messageIds) }); - const reads = []; + const reads: MessagingMessage['id'][] = []; for (const message of messages) { if (message.userId === userId) continue; diff --git a/src/server/api/endpoints/antennas/update.ts b/src/server/api/endpoints/antennas/update.ts index ff13e89bcc..d69b4feee6 100644 --- a/src/server/api/endpoints/antennas/update.ts +++ b/src/server/api/endpoints/antennas/update.ts @@ -137,7 +137,7 @@ export default define(meta, async (ps, user) => { notify: ps.notify, }); - publishInternalEvent('antennaUpdated', Antennas.findOneOrFail(antenna.id)); + publishInternalEvent('antennaUpdated', await Antennas.findOneOrFail(antenna.id)); return await Antennas.pack(antenna.id); }); diff --git a/src/server/api/stream/channels/channel.ts b/src/server/api/stream/channels/channel.ts index e6a9a6c696..a5692563f3 100644 --- a/src/server/api/stream/channels/channel.ts +++ b/src/server/api/stream/channels/channel.ts @@ -19,7 +19,7 @@ export default class extends Channel { this.channelId = params.channelId as string; // Subscribe stream - this.subscriber.on('notesStream', this.onNote); + this.subscriber.on('notesStream', e => this.onNote(e)); this.subscriber.on(`channelStream:${this.channelId}`, this.onEvent); this.emitTypersIntervalId = setInterval(this.emitTypers, 5000); } diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 18eba58538..7d2e918af6 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -1,7 +1,6 @@ import { User } from '@/models/entities/user'; import { EventEmitter } from 'events'; import Emitter from 'strict-event-emitter-types'; -import StreamTypes from 'misskey-js/built/streaming.types'; import { Channel } from '@/models/entities/channel'; import { UserProfile } from '@/models/entities/user-profile'; import { PackedUser } from '@/models/repositories/user'; @@ -14,6 +13,16 @@ import { PackedDriveFolder } from '@/models/repositories/drive-folder'; import { DriveFolder } from '@/models/entities/drive-folder'; import { Note } from '@/models/entities/note'; import { Emoji } from '@/models/entities/emoji'; +import { UserList } from '@/models/entities/user-list'; +import { MessagingMessage } from '@/models/entities/messaging-message'; +import { PackedMessagingMessage } from '@/models/repositories/messaging-message'; +import { UserGroup } from '@/models/entities/user-group'; +import { PackedReversiGame } from '@/models/repositories/games/reversi/game'; +import { PackedReversiMatching } from '@/models/repositories/games/reversi/matching'; +import { ReversiGame } from '@/models/entities/games/reversi/game'; +import { AbuseUserReport } from '@/models/entities/abuse-user-report'; +import { PackedEmoji } from '@/models/repositories/emoji'; +import StreamTypes from 'misskey-js/built/streaming.types'; // 辞書(interface or type)から{ type, body }ユニオンを定義 // https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type @@ -25,12 +34,6 @@ type EventUnionFromDictionary< // (payload: P) => void からPを取り出す type Payload void> = T extends (payload: infer P) => void ? P : never; -// misskey.jsのstreaming.typesの辞書から{ type, body }ユニオンを定義 -type EventUnionFromMkJSTypes< - T extends { [key: string]: ((payload: any) => void) | (() => void) }, - U = { [K in keyof T]: { type: K; body: Payload} } -> = U[keyof U]; - //#region Stream type-body definitions export interface InternalStreamTypes { antennaCreated: Antenna; @@ -38,6 +41,10 @@ export interface InternalStreamTypes { antennaUpdated: Antenna; } +export interface BroadcastTypes { + emojiAdded: PackedEmoji; +}; + export interface UserStreamTypes { terminate: {}; followChannel: Channel; @@ -75,6 +82,7 @@ export interface MainStreamTypes { readAllChannels: never; unreadChannel: never; myTokenRegenerated: never; + reversiInvited: PackedReversiMatching; } export interface DriveStreamTypes { @@ -117,7 +125,92 @@ export interface NoteStreamTypes { }; } +export interface ChannelStreamTypes { + typing: User['id']; +} + +export interface UserListStreamTypes { + userAdded: PackedUser; + userRemoved: PackedUser; +} + +export interface AntennaStreamTypes { + note: Note; +} + +export interface MessagingStreamTypes { + read: MessagingMessage['id'][]; + typing: User['id']; + message: PackedMessagingMessage; + deleted: MessagingMessage['id']; +} + +export interface GroupMessagingStreamTypes { + read: { + ids: MessagingMessage['id'][]; + userId: User['id']; + }; + typing: User['id']; + message: PackedMessagingMessage; + deleted: MessagingMessage['id']; +} + +export interface MessagingIndexStreamTypes { + read: MessagingMessage['id'][]; + message: PackedMessagingMessage; +} + +export interface ReversiStreamTypes { + matched: PackedReversiGame; + invited: PackedReversiMatching; +} + +export interface ReversiGameStreamTypes { + started: PackedReversiGame; + ended: { + winnerId: User['id'], + game: PackedReversiGame; + }; + updateSettings: { + key: string; + value: FIXME; + }; + initForm: { + userId: User['id']; + form: FIXME; + }; + updateForm: { + userId: User['id']; + id: string; + value: FIXME; + }; + message: { + userId: User['id']; + message: FIXME; + }; + changeAccepts: { + user1: boolean; + user2: boolean; + }; + set: { + at: Date; + color: boolean; + pos: number; + next: boolean; + }; + watching: User['id']; +} + +export interface AdminStreamTypes { + newAbuseUserReport: { + id: AbuseUserReport['id']; + targetUserId: User['id'], + reporterId: User['id'], + comment: string; + } +} //#endregion + //#region 名前とメッセージのペアを中間生成 interface StreamMessages { internal: { @@ -126,7 +219,7 @@ interface StreamMessages { }; broadcast: { name: 'broadcast'; - spec: EventUnionFromMkJSTypes; + spec: EventUnionFromDictionary; }; user: { name: `user:${User['id']}`; @@ -143,11 +236,52 @@ interface StreamMessages { note: { name: `noteStream:${Note['id']}`; spec: EventUnionFromDictionary; + }; + channel: { + name: `channelStream:${Channel['id']}`; + spec: EventUnionFromDictionary; + }; + userList: { + name: `userListStream:${UserList['id']}`; + spec: EventUnionFromDictionary; + }; + antenna: { + name: `antennaStream:${Antenna['id']}`; + spec: EventUnionFromDictionary; + }; + messaging: { + name: `messagingStream:${User['id']}-${User['id']}`; + spec: EventUnionFromDictionary; + }; + groupMessaging: { + name: `messagingStream:${UserGroup['id']}`; + spec: EventUnionFromDictionary; + }; + messagingIndex: { + name: `messagingIndexStream:${User['id']}`; + spec: EventUnionFromDictionary; + }; + reversi: { + name: `reversiStream:${User['id']}`; + spec: EventUnionFromDictionary; + }; + reversiGame: { + name: `reversiGameStream:${ReversiGame['id']}`; + spec: EventUnionFromDictionary; + }; + admin: { + name: `adminStream:${User['id']}`; + spec: EventUnionFromDictionary; } + // and notesStream (specにPackedNoteを突っ込むとなぜかバグる) } - //#endregion // API event definitions type EventsGenerater = { [key in StreamMessages[K]['name']]: (e: StreamMessages[K]['spec']) => void }; -export type StreamEventEmitter = Emitter>; +type NotesStreamEvent = { notesStream: (e: PackedNote) => void }; +export type StreamEventEmitter = Emitter & NotesStreamEvent>; + +// Channel Union +type ChannelsUnionGenerater = StreamMessages[K]['name']; +export type Channels = ChannelsUnionGenerater | 'notesStream'; diff --git a/src/services/stream.ts b/src/services/stream.ts index 4db1a77395..20c019f57d 100644 --- a/src/services/stream.ts +++ b/src/services/stream.ts @@ -7,9 +7,10 @@ import { UserGroup } from '@/models/entities/user-group'; import config from '@/config/index'; import { Antenna } from '@/models/entities/antenna'; import { Channel } from '@/models/entities/channel'; +import { BroadcastTypes, Channels, InternalStreamTypes, UserStreamTypes } from '@/server/api/stream/types'; class Publisher { - private publish = (channel: string, type: string | null, value?: any): void => { + private publish = (channel: Channels, type: string | null, value?: any): void => { const message = type == null ? value : value == null ? { type: type, body: null } : { type: type, body: value }; @@ -20,15 +21,15 @@ class Publisher { })); } - public publishInternalEvent = (type: string, value?: any): void => { + public publishInternalEvent = (type: K, value: InternalStreamTypes[K]): void => { this.publish('internal', type, typeof value === 'undefined' ? null : value); } - public publishUserEvent = (userId: User['id'], type: string, value?: any): void => { + public publishUserEvent = (userId: User['id'], type: K, value: UserStreamTypes[K]): void => { this.publish(`user:${userId}`, type, typeof value === 'undefined' ? null : value); } - public publishBroadcastStream = (type: string, value?: any): void => { + public publishBroadcastStream = (type: K, value: BroadcastTypes[K]): void => { this.publish('broadcast', type, typeof value === 'undefined' ? null : value); } From 5db28922d04c9496dc6482421eeaeeeba6f97d57 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 22:47:27 +0900 Subject: [PATCH 26/91] wip --- src/models/repositories/emoji.ts | 3 +- src/models/repositories/games/reversi/game.ts | 3 +- .../repositories/games/reversi/matching.ts | 3 +- src/models/repositories/signin.ts | 5 +- src/prelude/types.ts | 1 + src/server/api/stream/types.ts | 59 +++++++++++++------ src/services/stream.ts | 6 +- 7 files changed, 54 insertions(+), 26 deletions(-) create mode 100644 src/prelude/types.ts diff --git a/src/models/repositories/emoji.ts b/src/models/repositories/emoji.ts index 1bbe6b8215..2dc5f5282a 100644 --- a/src/models/repositories/emoji.ts +++ b/src/models/repositories/emoji.ts @@ -1,7 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Emoji } from '@/models/entities/emoji'; +import { Resolved } from '@/prelude/types'; -export type PackedEmoji = FIXME; +export type PackedEmoji = Resolved>; @EntityRepository(Emoji) export class EmojiRepository extends Repository { diff --git a/src/models/repositories/games/reversi/game.ts b/src/models/repositories/games/reversi/game.ts index eb2561be91..10433bf58f 100644 --- a/src/models/repositories/games/reversi/game.ts +++ b/src/models/repositories/games/reversi/game.ts @@ -2,8 +2,9 @@ import { User } from '@/models/entities/user'; import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../../../index'; import { ReversiGame } from '@/models/entities/games/reversi/game'; +import { Resolved } from '@/prelude/types'; -export type PackedReversiGame = FIXME; +export type PackedReversiGame = Resolved>; @EntityRepository(ReversiGame) export class ReversiGameRepository extends Repository { diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts index 91615091ac..2696f1f8ea 100644 --- a/src/models/repositories/games/reversi/matching.ts +++ b/src/models/repositories/games/reversi/matching.ts @@ -3,8 +3,9 @@ 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 { Resolved } from '@/prelude/types'; -export type PackedReversiMatching = FIXME; +export type PackedReversiMatching = Resolved>; @EntityRepository(ReversiMatching) export class ReversiMatchingRepository extends Repository { diff --git a/src/models/repositories/signin.ts b/src/models/repositories/signin.ts index 9942d2d962..79d23241a7 100644 --- a/src/models/repositories/signin.ts +++ b/src/models/repositories/signin.ts @@ -1,10 +1,13 @@ import { EntityRepository, Repository } from 'typeorm'; import { Signin } from '@/models/entities/signin'; +import { Resolved } from '@/prelude/types'; + +export type PackedSignin = Resolved>; @EntityRepository(Signin) export class SigninRepository extends Repository { public async pack( - src: any, + src: Signin, ) { return src; } diff --git a/src/prelude/types.ts b/src/prelude/types.ts new file mode 100644 index 0000000000..d004d0ff31 --- /dev/null +++ b/src/prelude/types.ts @@ -0,0 +1 @@ +export type Resolved

> = P extends Promise ? R : never; diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 7d2e918af6..db947bd1f4 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -23,6 +23,8 @@ import { ReversiGame } from '@/models/entities/games/reversi/game'; import { AbuseUserReport } from '@/models/entities/abuse-user-report'; import { PackedEmoji } from '@/models/repositories/emoji'; import StreamTypes from 'misskey-js/built/streaming.types'; +import { PackedSignin } from '@/models/repositories/signin'; +import { Page } from '@/models/entities/page'; // 辞書(interface or type)から{ type, body }ユニオンを定義 // https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type @@ -43,7 +45,7 @@ export interface InternalStreamTypes { export interface BroadcastTypes { emojiAdded: PackedEmoji; -}; +} export interface UserStreamTypes { terminate: {}; @@ -66,23 +68,42 @@ export interface MainStreamTypes { followed: PackedUser; unfollow: PackedUser; meUpdated: PackedUser; - pageEvent: Payload; - urlUploadFinished: Payload; - readAllNotifications: never; - unreadNotification: never; - unreadMention: never; - readAllUnreadMentions: never; - unreadSpecifiedNote: never; - readAllUnreadSpecifiedNotes: never; - readAllMessagingMessages: never; - unreadMessagingMessage: never; - readAllAntennas: never; - unreadAntenna: never; - readAllAnnouncements: never; - readAllChannels: never; - unreadChannel: never; - myTokenRegenerated: never; + pageEvent: { + pageId: Page['id']; + event: string; + var: any; + userId: User['id']; + user: PackedUser; + }; + urlUploadFinished: { + marker?: string | null; + file: PackedDriveFile; + }; + readAllNotifications: undefined; + unreadNotification: PackedNotification; + unreadMention: Note['id']; + readAllUnreadMentions: undefined; + unreadSpecifiedNote: Note['id']; + readAllUnreadSpecifiedNotes: undefined; + readAllMessagingMessages: undefined; + messagingMessage: PackedMessagingMessage; + unreadMessagingMessage: PackedMessagingMessage; + readAllAntennas: undefined; + unreadAntenna: Antenna; + readAllAnnouncements: undefined; + readAllChannels: undefined; + unreadChannel: Note['id']; + myTokenRegenerated: undefined; + reversiNoInvites: undefined; reversiInvited: PackedReversiMatching; + signin: PackedSignin; + registryUpdated: { + scope?: string[]; + key: string; + value: any | null; + }; + driveFileCreated: PackedDriveFile; + readAntenna: Antenna; } export interface DriveStreamTypes { @@ -207,7 +228,7 @@ export interface AdminStreamTypes { targetUserId: User['id'], reporterId: User['id'], comment: string; - } + }; } //#endregion @@ -272,7 +293,7 @@ interface StreamMessages { admin: { name: `adminStream:${User['id']}`; spec: EventUnionFromDictionary; - } + }; // and notesStream (specにPackedNoteを突っ込むとなぜかバグる) } //#endregion diff --git a/src/services/stream.ts b/src/services/stream.ts index 20c019f57d..3b0c90d75c 100644 --- a/src/services/stream.ts +++ b/src/services/stream.ts @@ -7,7 +7,7 @@ import { UserGroup } from '@/models/entities/user-group'; import config from '@/config/index'; import { Antenna } from '@/models/entities/antenna'; import { Channel } from '@/models/entities/channel'; -import { BroadcastTypes, Channels, InternalStreamTypes, UserStreamTypes } from '@/server/api/stream/types'; +import { BroadcastTypes, Channels, InternalStreamTypes, MainStreamTypes, UserStreamTypes } from '@/server/api/stream/types'; class Publisher { private publish = (channel: Channels, type: string | null, value?: any): void => { @@ -25,7 +25,7 @@ class Publisher { this.publish('internal', type, typeof value === 'undefined' ? null : value); } - public publishUserEvent = (userId: User['id'], type: K, value: UserStreamTypes[K]): void => { + public publishUserEvent = (userId: User['id'], type: K, value?: UserStreamTypes[K]): void => { this.publish(`user:${userId}`, type, typeof value === 'undefined' ? null : value); } @@ -33,7 +33,7 @@ class Publisher { this.publish('broadcast', type, typeof value === 'undefined' ? null : value); } - public publishMainStream = (userId: User['id'], type: string, value?: any): void => { + public publishMainStream = (userId: User['id'], type: K, value?: MainStreamTypes[K]): void => { this.publish(`mainStream:${userId}`, type, typeof value === 'undefined' ? null : value); } From f6853b22547426a58f68d8e89361daef60f81d71 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 22:48:12 +0900 Subject: [PATCH 27/91] :v: --- src/server/api/stream/types.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index db947bd1f4..17acc95379 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -22,7 +22,6 @@ import { PackedReversiMatching } from '@/models/repositories/games/reversi/match import { ReversiGame } from '@/models/entities/games/reversi/game'; import { AbuseUserReport } from '@/models/entities/abuse-user-report'; import { PackedEmoji } from '@/models/repositories/emoji'; -import StreamTypes from 'misskey-js/built/streaming.types'; import { PackedSignin } from '@/models/repositories/signin'; import { Page } from '@/models/entities/page'; From 4793d1cc56e5d0778f54a1a4b45fc3cdc09ea172 Mon Sep 17 00:00:00 2001 From: tamaina Date: Mon, 6 Sep 2021 23:18:16 +0900 Subject: [PATCH 28/91] =?UTF-8?q?=E9=80=81=E4=BF=A1=E5=81=B4=E3=81=AB?= =?UTF-8?q?=E5=9E=8B=E3=82=A8=E3=83=A9=E3=83=BC=E3=81=8C=E3=81=AA=E3=81=84?= =?UTF-8?q?=E3=81=93=E3=81=A8=E3=82=923=E5=9B=9E=E7=A2=BA=E8=AA=8D?= =?UTF-8?q?=E3=81=97=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/server/api/stream/types.ts | 59 +++++++++++++++------------------- src/services/stream.ts | 46 ++++++++++++++++++-------- 2 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 17acc95379..b78b894977 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -1,27 +1,27 @@ -import { User } from '@/models/entities/user'; import { EventEmitter } from 'events'; import Emitter from 'strict-event-emitter-types'; import { Channel } from '@/models/entities/channel'; +import { User } from '@/models/entities/user'; import { UserProfile } from '@/models/entities/user-profile'; import { PackedUser } from '@/models/repositories/user'; import { PackedNotification } from '@/models/repositories/notification'; +import { Note } from '@/models/entities/note'; import { PackedNote } from '@/models/repositories/note'; import { Antenna } from '@/models/entities/antenna'; import { DriveFile } from '@/models/entities/drive-file'; import { PackedDriveFile } from '@/models/repositories/drive-file'; -import { PackedDriveFolder } from '@/models/repositories/drive-folder'; import { DriveFolder } from '@/models/entities/drive-folder'; -import { Note } from '@/models/entities/note'; +import { PackedDriveFolder } from '@/models/repositories/drive-folder'; import { Emoji } from '@/models/entities/emoji'; +import { PackedEmoji } from '@/models/repositories/emoji'; import { UserList } from '@/models/entities/user-list'; import { MessagingMessage } from '@/models/entities/messaging-message'; import { PackedMessagingMessage } from '@/models/repositories/messaging-message'; import { UserGroup } from '@/models/entities/user-group'; +import { ReversiGame } from '@/models/entities/games/reversi/game'; import { PackedReversiGame } from '@/models/repositories/games/reversi/game'; import { PackedReversiMatching } from '@/models/repositories/games/reversi/matching'; -import { ReversiGame } from '@/models/entities/games/reversi/game'; import { AbuseUserReport } from '@/models/entities/abuse-user-report'; -import { PackedEmoji } from '@/models/repositories/emoji'; import { PackedSignin } from '@/models/repositories/signin'; import { Page } from '@/models/entities/page'; @@ -32,9 +32,6 @@ type EventUnionFromDictionary< U = { [K in keyof T]: { type: K; body: T[K]} } > = U[keyof U]; -// (payload: P) => void からPを取り出す -type Payload void> = T extends (payload: infer P) => void ? P : never; - //#region Stream type-body definitions export interface InternalStreamTypes { antennaCreated: Antenna; @@ -43,7 +40,9 @@ export interface InternalStreamTypes { } export interface BroadcastTypes { - emojiAdded: PackedEmoji; + emojiAdded: { + emoji: PackedEmoji; + }; } export interface UserStreamTypes { @@ -116,34 +115,28 @@ export interface DriveStreamTypes { export interface NoteStreamTypes { pollVoted: { - id: Note['id']; - body: { - choice: number; - userId: User['id']; - }; + choice: number; + userId: User['id']; }; deleted: { - id: Note['id']; - body: { - deletedAt: Date; - }; + deletedAt: Date; }; reacted: { - id: Note['id']; - body: { - reaction: string; - emoji?: Emoji; - userId: User['id']; - }; + reaction: string; + emoji?: Emoji; + userId: User['id']; }; unreacted: { - id: Note['id']; - body: { - reaction: string; - userId: User['id']; - } + reaction: string; + userId: User['id']; }; } +type NoteStreamEventTypes = { + [key in keyof NoteStreamTypes]: { + id: Note['id']; + body: NoteStreamTypes[key]; + }; +}; export interface ChannelStreamTypes { typing: User['id']; @@ -188,7 +181,7 @@ export interface ReversiStreamTypes { export interface ReversiGameStreamTypes { started: PackedReversiGame; ended: { - winnerId: User['id'], + winnerId?: User['id'] | null, game: PackedReversiGame; }; updateSettings: { @@ -255,7 +248,7 @@ interface StreamMessages { }; note: { name: `noteStream:${Note['id']}`; - spec: EventUnionFromDictionary; + spec: EventUnionFromDictionary; }; channel: { name: `channelStream:${Channel['id']}`; @@ -302,6 +295,6 @@ type EventsGenerater = { [key in StreamMessages[ type NotesStreamEvent = { notesStream: (e: PackedNote) => void }; export type StreamEventEmitter = Emitter & NotesStreamEvent>; -// Channel Union +// provide stream channels union type ChannelsUnionGenerater = StreamMessages[K]['name']; -export type Channels = ChannelsUnionGenerater | 'notesStream'; +export type StreamChannels = ChannelsUnionGenerater | 'notesStream'; diff --git a/src/services/stream.ts b/src/services/stream.ts index 3b0c90d75c..3c5ef36399 100644 --- a/src/services/stream.ts +++ b/src/services/stream.ts @@ -7,10 +7,28 @@ import { UserGroup } from '@/models/entities/user-group'; import config from '@/config/index'; import { Antenna } from '@/models/entities/antenna'; import { Channel } from '@/models/entities/channel'; -import { BroadcastTypes, Channels, InternalStreamTypes, MainStreamTypes, UserStreamTypes } from '@/server/api/stream/types'; +import { + StreamChannels, + AdminStreamTypes, + AntennaStreamTypes, + BroadcastTypes, + ChannelStreamTypes, + DriveStreamTypes, + GroupMessagingStreamTypes, + InternalStreamTypes, + MainStreamTypes, + MessagingIndexStreamTypes, + MessagingStreamTypes, + NoteStreamTypes, + ReversiGameStreamTypes, + ReversiStreamTypes, + UserListStreamTypes, + UserStreamTypes +} from '@/server/api/stream/types'; +import { PackedNote } from '@/models/repositories/note'; class Publisher { - private publish = (channel: Channels, type: string | null, value?: any): void => { + private publish = (channel: StreamChannels, type: string | null, value?: any): void => { const message = type == null ? value : value == null ? { type: type, body: null } : { type: type, body: value }; @@ -37,54 +55,54 @@ class Publisher { this.publish(`mainStream:${userId}`, type, typeof value === 'undefined' ? null : value); } - public publishDriveStream = (userId: User['id'], type: string, value?: any): void => { + public publishDriveStream = (userId: User['id'], type: K, value?: DriveStreamTypes[K]): void => { this.publish(`driveStream:${userId}`, type, typeof value === 'undefined' ? null : value); } - public publishNoteStream = (noteId: Note['id'], type: string, value: any): void => { + public publishNoteStream = (noteId: Note['id'], type: K, value: NoteStreamTypes[K]): void => { this.publish(`noteStream:${noteId}`, type, { id: noteId, body: value }); } - public publishChannelStream = (channelId: Channel['id'], type: string, value?: any): void => { + public publishChannelStream = (channelId: Channel['id'], type: K, value?: ChannelStreamTypes[K]): void => { this.publish(`channelStream:${channelId}`, type, typeof value === 'undefined' ? null : value); } - public publishUserListStream = (listId: UserList['id'], type: string, value?: any): void => { + public publishUserListStream = (listId: UserList['id'], type: K, value?: UserListStreamTypes[K]): void => { this.publish(`userListStream:${listId}`, type, typeof value === 'undefined' ? null : value); } - public publishAntennaStream = (antennaId: Antenna['id'], type: string, value?: any): void => { + public publishAntennaStream = (antennaId: Antenna['id'], type: K, value?: AntennaStreamTypes[K]): void => { this.publish(`antennaStream:${antennaId}`, type, typeof value === 'undefined' ? null : value); } - public publishMessagingStream = (userId: User['id'], otherpartyId: User['id'], type: string, value?: any): void => { + public publishMessagingStream = (userId: User['id'], otherpartyId: User['id'], type: K, value?: MessagingStreamTypes[K]): void => { this.publish(`messagingStream:${userId}-${otherpartyId}`, type, typeof value === 'undefined' ? null : value); } - public publishGroupMessagingStream = (groupId: UserGroup['id'], type: string, value?: any): void => { + public publishGroupMessagingStream = (groupId: UserGroup['id'], type: K, value?: GroupMessagingStreamTypes[K]): void => { this.publish(`messagingStream:${groupId}`, type, typeof value === 'undefined' ? null : value); } - public publishMessagingIndexStream = (userId: User['id'], type: string, value?: any): void => { + public publishMessagingIndexStream = (userId: User['id'], type: K, value?: MessagingIndexStreamTypes[K]): void => { this.publish(`messagingIndexStream:${userId}`, type, typeof value === 'undefined' ? null : value); } - public publishReversiStream = (userId: User['id'], type: string, value?: any): void => { + public publishReversiStream = (userId: User['id'], type: K, value?: ReversiStreamTypes[K]): void => { this.publish(`reversiStream:${userId}`, type, typeof value === 'undefined' ? null : value); } - public publishReversiGameStream = (gameId: ReversiGame['id'], type: string, value?: any): void => { + public publishReversiGameStream = (gameId: ReversiGame['id'], type: K, value?: ReversiGameStreamTypes[K]): void => { this.publish(`reversiGameStream:${gameId}`, type, typeof value === 'undefined' ? null : value); } - public publishNotesStream = (note: any): void => { + public publishNotesStream = (note: PackedNote): void => { this.publish('notesStream', null, note); } - public publishAdminStream = (userId: User['id'], type: string, value?: any): void => { + public publishAdminStream = (userId: User['id'], type: K, value?: AdminStreamTypes[K]): void => { this.publish(`adminStream:${userId}`, type, typeof value === 'undefined' ? null : value); } } From be47a120d75996864b6bc8a2f393a3ed87aebbb2 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 02:40:38 +0900 Subject: [PATCH 29/91] :v: --- src/server/api/stream/channels/messaging.ts | 6 ++++-- src/server/api/stream/index.ts | 8 ++++---- src/server/api/stream/types.ts | 20 +++++++++++--------- 3 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/server/api/stream/channels/messaging.ts b/src/server/api/stream/channels/messaging.ts index 015b0a7650..a75181d6d7 100644 --- a/src/server/api/stream/channels/messaging.ts +++ b/src/server/api/stream/channels/messaging.ts @@ -3,6 +3,8 @@ import { readUserMessagingMessage, readGroupMessagingMessage, deliverReadActivit import Channel from '../channel'; import { UserGroupJoinings, Users, MessagingMessages } from '@/models/index'; import { User, ILocalUser, IRemoteUser } from '@/models/entities/user'; +import { UserGroup } from '@/models/entities/user-group'; +import { StreamMessages } from '../types'; export default class extends Channel { public readonly chName = 'messaging'; @@ -12,7 +14,7 @@ export default class extends Channel { private otherpartyId: string | null; private otherparty: User | null; private groupId: string | null; - private subCh: string; + private subCh: `messagingStream:${User['id']}-${User['id']}` | `messagingStream:${UserGroup['id']}`; private typers: Record = {}; private emitTypersIntervalId: ReturnType; @@ -45,7 +47,7 @@ export default class extends Channel { } @autobind - private onEvent(data: any) { + private onEvent(data: StreamMessages['messaging']['spec'] | StreamMessages['groupMessaging']['spec']) { if (data.type === 'typing') { const id = data.body; const begin = this.typers[id] == null; diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index b2cecb4470..89d9889220 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -15,7 +15,7 @@ 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 { StreamEventEmitter, UserStreams } from './types'; +import { StreamEventEmitter, StreamMessages } from './types'; /** * Main stream connection @@ -47,8 +47,8 @@ export default class Connection { this.wsConnection.on('message', this.onWsConnectionMessage); - this.subscriber.on('broadcast', async ({ type, body }) => { - this.onBroadcastMessage(type, body); + this.subscriber.on('broadcast', async ev => { + this.onBroadcastMessage(ev.type, ev.body); }); if (this.user) { @@ -65,7 +65,7 @@ export default class Connection { } @autobind - private onUserEvent(ev: UserStreams) { // { type, body }と展開すると型も展開されてしまう + private onUserEvent(ev: StreamMessages['user']['spec']) { // { type, body }と展開すると型も展開されてしまう switch (ev.type) { case 'follow': this.following.add(ev.body.id); diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index b78b894977..eb80c2e913 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -29,7 +29,7 @@ import { Page } from '@/models/entities/page'; // https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type type EventUnionFromDictionary< T extends object, - U = { [K in keyof T]: { type: K; body: T[K]} } + U = { [K in keyof T]: { type: K; body: T[K]; } } > = U[keyof U]; //#region Stream type-body definitions @@ -225,7 +225,7 @@ export interface AdminStreamTypes { //#endregion //#region 名前とメッセージのペアを中間生成 -interface StreamMessages { +export type StreamMessages = { internal: { name: 'internal'; spec: EventUnionFromDictionary; @@ -286,15 +286,17 @@ interface StreamMessages { name: `adminStream:${User['id']}`; spec: EventUnionFromDictionary; }; - // and notesStream (specにPackedNoteを突っ込むとなぜかバグる) -} + notes: { + name: 'notesStream'; + spec: PackedNote; + }; +}; //#endregion // API event definitions -type EventsGenerater = { [key in StreamMessages[K]['name']]: (e: StreamMessages[K]['spec']) => void }; -type NotesStreamEvent = { notesStream: (e: PackedNote) => void }; -export type StreamEventEmitter = Emitter & NotesStreamEvent>; +type EventsDictionary = { [x in keyof StreamMessages]: { [y in StreamMessages[x]['name']]: (e: StreamMessages[x]['spec']) => void } }; +type Events = (D extends any ? (k: D) => void : never) extends ((k: infer E) => void) ? E : never; +export type StreamEventEmitter = Emitter>; // provide stream channels union -type ChannelsUnionGenerater = StreamMessages[K]['name']; -export type StreamChannels = ChannelsUnionGenerater | 'notesStream'; +export type StreamChannels = StreamMessages[keyof StreamMessages]['name'] | 'notesStream'; From fd55e2b5b5c9599eec19ed58a6c6e4ca9ed000c7 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 03:31:56 +0900 Subject: [PATCH 30/91] wip --- src/server/api/stream/types.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index eb80c2e913..b497458ce5 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -294,9 +294,13 @@ export type StreamMessages = { //#endregion // API event definitions -type EventsDictionary = { [x in keyof StreamMessages]: { [y in StreamMessages[x]['name']]: (e: StreamMessages[x]['spec']) => void } }; -type Events = (D extends any ? (k: D) => void : never) extends ((k: infer E) => void) ? E : never; -export type StreamEventEmitter = Emitter>; +// ストリームごとのEmitterの辞書を用意 +type EventsDictionary = { [x in keyof StreamMessages]: Emitter void }> }; +// 共用体型を交差型にする型 https://stackoverflow.com/questions/54938141/typescript-convert-union-to-intersection +type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; +// Emitter辞書をストリームごとに共用体型にし、UnionToIntersectionで交差型にする +export type StreamEventEmitter = UnionToIntersection; +// そうしないとなぜかユニオン型が増えまくり、ts(2590)にひっかかる // provide stream channels union export type StreamChannels = StreamMessages[keyof StreamMessages]['name'] | 'notesStream'; From b22972f7009ca97bb62a79e054960e5464f814c8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 03:35:36 +0900 Subject: [PATCH 31/91] update typescript --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ab24a1c7ec..4d25898e4e 100644 --- a/package.json +++ b/package.json @@ -229,7 +229,7 @@ "tslint-sonarts": "1.9.0", "twemoji-parser": "13.1.0", "typeorm": "0.2.37", - "typescript": "4.3.5", + "typescript": "4.4.2", "ulid": "2.3.0", "uuid": "8.3.2", "v-debounce": "0.1.2", diff --git a/yarn.lock b/yarn.lock index 33f9f22454..fde80ff8d6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -11174,10 +11174,10 @@ typeorm@0.2.37: yargs "^17.0.1" zen-observable-ts "^1.0.0" -typescript@4.3.5: - version "4.3.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.3.5.tgz#4d1c37cc16e893973c45a06886b7113234f119f4" - integrity sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA== +typescript@4.4.2: + version "4.4.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.2.tgz#6d618640d430e3569a1dfb44f7d7e600ced3ee86" + integrity sha512-gzP+t5W4hdy4c+68bfcv0t400HVJMMd2+H9B7gae1nQlBzCqvrXX+6GL/b3GAgyTH966pzrZ70/fRjwAtZksSQ== uc.micro@^1.0.1, uc.micro@^1.0.5: version "1.0.6" From 714f9f20325a71175cdc4c4cc2f7240b817152e8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 03:47:50 +0900 Subject: [PATCH 32/91] define items in full Schema --- src/misc/schema.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index 90d4c3b715..d27c9eff99 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -48,6 +48,7 @@ export const refs = { }; export interface Schema extends SimpleSchema { + items?: Schema; properties?: Obj; ref?: keyof typeof refs; } From 1590cf000fd282d0f0c600acab740e2f64bb5f06 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 03:58:58 +0900 Subject: [PATCH 33/91] edit comment --- src/server/api/stream/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index b497458ce5..2670d1ac87 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -300,7 +300,7 @@ type EventsDictionary = { [x in keyof StreamMessages]: Emitter = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; // Emitter辞書をストリームごとに共用体型にし、UnionToIntersectionで交差型にする export type StreamEventEmitter = UnionToIntersection; -// そうしないとなぜかユニオン型が増えまくり、ts(2590)にひっかかる +// そうしないとユニオンが増大してts(2590)にひっかかる // provide stream channels union export type StreamChannels = StreamMessages[keyof StreamMessages]['name'] | 'notesStream'; From cd36102b9002a0d6b15c3678871f95eb269f241a Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 04:01:06 +0900 Subject: [PATCH 34/91] edit comment --- src/server/api/stream/types.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 2670d1ac87..2d44154559 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -224,7 +224,7 @@ export interface AdminStreamTypes { } //#endregion -//#region 名前とメッセージのペアを中間生成 +// name/messages(spec) pairs dictionary export type StreamMessages = { internal: { name: 'internal'; @@ -291,7 +291,6 @@ export type StreamMessages = { spec: PackedNote; }; }; -//#endregion // API event definitions // ストリームごとのEmitterの辞書を用意 From 2c494f10522024e25b748649cdc7de096459b131 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 04:41:07 +0900 Subject: [PATCH 35/91] edit comment --- src/server/api/stream/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 2d44154559..bf67ce90b2 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -299,7 +299,7 @@ type EventsDictionary = { [x in keyof StreamMessages]: Emitter = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; // Emitter辞書をストリームごとに共用体型にし、UnionToIntersectionで交差型にする export type StreamEventEmitter = UnionToIntersection; -// そうしないとユニオンが増大してts(2590)にひっかかる +// { [y in name]: (e: spec) => void }をまとめてその交差型をEmitterにかけるとts(2590)にひっかかる // provide stream channels union export type StreamChannels = StreamMessages[keyof StreamMessages]['name'] | 'notesStream'; From afb7d5d56b4c88e03164c0e17c61ac592e44fa48 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 09:32:33 +0900 Subject: [PATCH 36/91] Update src/prelude/types.ts MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Acid Chicken (硫酸鶏) --- src/prelude/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prelude/types.ts b/src/prelude/types.ts index d004d0ff31..b8c49f9292 100644 --- a/src/prelude/types.ts +++ b/src/prelude/types.ts @@ -1 +1 @@ -export type Resolved

> = P extends Promise ? R : never; +export type Resolved

= P extends PromiseLike ? Resolved : never; From 6a808ac5e3b770e620ab6b739398559904e4f125 Mon Sep 17 00:00:00 2001 From: tamaina Date: Tue, 7 Sep 2021 09:33:45 +0900 Subject: [PATCH 37/91] https://github.com/misskey-dev/misskey/pull/7769#discussion_r703058458 --- src/services/stream.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/services/stream.ts b/src/services/stream.ts index 3c5ef36399..c21ccb4a74 100644 --- a/src/services/stream.ts +++ b/src/services/stream.ts @@ -39,7 +39,7 @@ class Publisher { })); } - public publishInternalEvent = (type: K, value: InternalStreamTypes[K]): void => { + public publishInternalEvent = (type: K, value?: InternalStreamTypes[K]): void => { this.publish('internal', type, typeof value === 'undefined' ? null : value); } @@ -47,7 +47,7 @@ class Publisher { this.publish(`user:${userId}`, type, typeof value === 'undefined' ? null : value); } - public publishBroadcastStream = (type: K, value: BroadcastTypes[K]): void => { + public publishBroadcastStream = (type: K, value?: BroadcastTypes[K]): void => { this.publish('broadcast', type, typeof value === 'undefined' ? null : value); } @@ -59,7 +59,7 @@ class Publisher { this.publish(`driveStream:${userId}`, type, typeof value === 'undefined' ? null : value); } - public publishNoteStream = (noteId: Note['id'], type: K, value: NoteStreamTypes[K]): void => { + public publishNoteStream = (noteId: Note['id'], type: K, value?: NoteStreamTypes[K]): void => { this.publish(`noteStream:${noteId}`, type, { id: noteId, body: value From 59580e90937e35a56a7f6b608c09b21ad0dd52c8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 00:46:38 +0900 Subject: [PATCH 38/91] =?UTF-8?q?user=20pack=E3=81=A8note=20pack=E3=81=AE?= =?UTF-8?q?=E5=9E=8B=E4=B8=8D=E6=95=B4=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/models/repositories/note.ts | 23 ++++++++++++++++++----- src/models/repositories/user.ts | 30 +++++++++--------------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index 77fedd791f..376a09d0c6 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -447,11 +447,24 @@ export const packedNoteSchema = { channel: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'Channel' as const, + items: { + 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, + }, + name: { + type: 'string' as const, + optional: false as const, nullable: true as const, + }, + }, + }, }, localOnly: { type: 'boolean' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, emojis: { type: 'array' as const, @@ -466,7 +479,7 @@ export const packedNoteSchema = { }, url: { type: 'string' as const, - optional: false as const, nullable: false as const, + optional: false as const, nullable: true as const, }, }, }, @@ -485,11 +498,11 @@ export const packedNoteSchema = { }, uri: { type: 'string' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, url: { type: 'string' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, myReaction: { diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index 4a6534b557..39c90cf5ed 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -375,12 +375,12 @@ export const packedUserSchema = { }, isAdmin: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, isModerator: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, isBot: { @@ -402,23 +402,11 @@ export const packedUserSchema = { type: 'string' as const, nullable: false as const, optional: false as const }, - host: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, url: { type: 'string' as const, nullable: false as const, optional: false as const, format: 'url' }, - aliases: { - type: 'array' as const, - nullable: false as const, optional: false as const, - items: { - type: 'string' as const, - nullable: false as const, optional: false as const - } - } } } }, @@ -457,7 +445,7 @@ export const packedUserSchema = { }, isSuspended: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, example: false }, description: { @@ -476,7 +464,7 @@ export const packedUserSchema = { }, fields: { type: 'array' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, items: { type: 'object' as const, nullable: false as const, optional: false as const, @@ -525,26 +513,26 @@ export const packedUserSchema = { }, pinnedPageId: { type: 'string' as const, - nullable: true as const, optional: false as const + nullable: true as const, optional: true as const }, pinnedPage: { type: 'object' as const, - nullable: true as const, optional: false as const, + nullable: true as const, optional: true as const, ref: 'Page' as const, }, twoFactorEnabled: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, usePasswordLessLogin: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, securityKeys: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, avatarId: { From 36e86bbca7ea7881451f3dda24a7dbaf1e4b4168 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 00:47:34 +0900 Subject: [PATCH 39/91] revert https://github.com/misskey-dev/misskey/pull/7772#discussion_r706627736 --- test/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils.ts b/test/utils.ts index 253c410bf0..1a0c54463d 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -158,7 +158,7 @@ export async function initTestDb(justBorrow = false, initEntities?: any[]) { await conn.close(); } catch (e) {} - return createConnection({ + return await createConnection({ type: 'postgres', host: config.db.host, port: config.db.port, From 94ebf2ac5af89f01bdc3cc64764935e14bf379ce Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 00:47:34 +0900 Subject: [PATCH 40/91] revert https://github.com/misskey-dev/misskey/pull/7772#discussion_r706627736 --- test/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/utils.ts b/test/utils.ts index 253c410bf0..1a0c54463d 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -158,7 +158,7 @@ export async function initTestDb(justBorrow = false, initEntities?: any[]) { await conn.close(); } catch (e) {} - return createConnection({ + return await createConnection({ type: 'postgres', host: config.db.host, port: config.db.port, From a7f5ad78b47faaafdd634c450161f6821201f03d Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 00:46:38 +0900 Subject: [PATCH 41/91] =?UTF-8?q?user=20pack=E3=81=A8note=20pack=E3=81=AE?= =?UTF-8?q?=E5=9E=8B=E4=B8=8D=E6=95=B4=E5=90=88=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/models/repositories/note.ts | 23 ++++++++++++++++++----- src/models/repositories/user.ts | 30 +++++++++--------------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/models/repositories/note.ts b/src/models/repositories/note.ts index 77fedd791f..376a09d0c6 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -447,11 +447,24 @@ export const packedNoteSchema = { channel: { type: 'object' as const, optional: true as const, nullable: true as const, - ref: 'Channel' as const, + items: { + 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, + }, + name: { + type: 'string' as const, + optional: false as const, nullable: true as const, + }, + }, + }, }, localOnly: { type: 'boolean' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, emojis: { type: 'array' as const, @@ -466,7 +479,7 @@ export const packedNoteSchema = { }, url: { type: 'string' as const, - optional: false as const, nullable: false as const, + optional: false as const, nullable: true as const, }, }, }, @@ -485,11 +498,11 @@ export const packedNoteSchema = { }, uri: { type: 'string' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, url: { type: 'string' as const, - optional: false as const, nullable: true as const, + optional: true as const, nullable: false as const, }, myReaction: { diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index 4a6534b557..39c90cf5ed 100644 --- a/src/models/repositories/user.ts +++ b/src/models/repositories/user.ts @@ -375,12 +375,12 @@ export const packedUserSchema = { }, isAdmin: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, isModerator: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, isBot: { @@ -402,23 +402,11 @@ export const packedUserSchema = { type: 'string' as const, nullable: false as const, optional: false as const }, - host: { - type: 'string' as const, - nullable: true as const, optional: false as const - }, url: { type: 'string' as const, nullable: false as const, optional: false as const, format: 'url' }, - aliases: { - type: 'array' as const, - nullable: false as const, optional: false as const, - items: { - type: 'string' as const, - nullable: false as const, optional: false as const - } - } } } }, @@ -457,7 +445,7 @@ export const packedUserSchema = { }, isSuspended: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, example: false }, description: { @@ -476,7 +464,7 @@ export const packedUserSchema = { }, fields: { type: 'array' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, items: { type: 'object' as const, nullable: false as const, optional: false as const, @@ -525,26 +513,26 @@ export const packedUserSchema = { }, pinnedPageId: { type: 'string' as const, - nullable: true as const, optional: false as const + nullable: true as const, optional: true as const }, pinnedPage: { type: 'object' as const, - nullable: true as const, optional: false as const, + nullable: true as const, optional: true as const, ref: 'Page' as const, }, twoFactorEnabled: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, usePasswordLessLogin: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, securityKeys: { type: 'boolean' as const, - nullable: false as const, optional: false as const, + nullable: false as const, optional: true as const, default: false }, avatarId: { From beac5d2fb791b31a20910a6d9cc39919574489db Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:02:56 +0900 Subject: [PATCH 42/91] add prelude/types.ts --- src/prelude/types.ts | 1 + 1 file changed, 1 insertion(+) create mode 100644 src/prelude/types.ts diff --git a/src/prelude/types.ts b/src/prelude/types.ts new file mode 100644 index 0000000000..b8c49f9292 --- /dev/null +++ b/src/prelude/types.ts @@ -0,0 +1 @@ +export type Resolved

= P extends PromiseLike ? Resolved : never; From 866de46f6533d0bdd0beb0c20fafd65068319e6e Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:03:40 +0900 Subject: [PATCH 43/91] emoji --- src/models/repositories/emoji.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/models/repositories/emoji.ts b/src/models/repositories/emoji.ts index c3d7184ec9..2dc5f5282a 100644 --- a/src/models/repositories/emoji.ts +++ b/src/models/repositories/emoji.ts @@ -1,5 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Emoji } from '@/models/entities/emoji'; +import { Resolved } from '@/prelude/types'; + +export type PackedEmoji = Resolved>; @EntityRepository(Emoji) export class EmojiRepository extends Repository { From 6df0c45cba666ab59215d46f46a3d3591c603933 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:04:07 +0900 Subject: [PATCH 44/91] signin --- src/models/repositories/signin.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/models/repositories/signin.ts b/src/models/repositories/signin.ts index 9942d2d962..8038760742 100644 --- a/src/models/repositories/signin.ts +++ b/src/models/repositories/signin.ts @@ -1,5 +1,8 @@ import { EntityRepository, Repository } from 'typeorm'; import { Signin } from '@/models/entities/signin'; +import { Resolved } from '@/prelude/types'; + +export type PackedSignin = Resolved>; @EntityRepository(Signin) export class SigninRepository extends Repository { From 9ea98149573a8653a456fd5b1ed61e70a829ec12 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:04:30 +0900 Subject: [PATCH 45/91] game --- src/models/repositories/games/reversi/game.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/models/repositories/games/reversi/game.ts b/src/models/repositories/games/reversi/game.ts index dc91ad51b8..10433bf58f 100644 --- a/src/models/repositories/games/reversi/game.ts +++ b/src/models/repositories/games/reversi/game.ts @@ -2,6 +2,9 @@ import { User } from '@/models/entities/user'; import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../../../index'; import { ReversiGame } from '@/models/entities/games/reversi/game'; +import { Resolved } from '@/prelude/types'; + +export type PackedReversiGame = Resolved>; @EntityRepository(ReversiGame) export class ReversiGameRepository extends Repository { From ace6784b9d00cf06f8097d164d5efb496ac6a36d Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:04:55 +0900 Subject: [PATCH 46/91] matching --- src/models/repositories/games/reversi/matching.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts index 148221dee5..2696f1f8ea 100644 --- a/src/models/repositories/games/reversi/matching.ts +++ b/src/models/repositories/games/reversi/matching.ts @@ -3,6 +3,9 @@ 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 { Resolved } from '@/prelude/types'; + +export type PackedReversiMatching = Resolved>; @EntityRepository(ReversiMatching) export class ReversiMatchingRepository extends Repository { From 1cc72fdd73acbefb20e35c92139150fd179a89c8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:18:17 +0900 Subject: [PATCH 47/91] clean up --- src/server/api/stream/channels/channel.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/channels/channel.ts b/src/server/api/stream/channels/channel.ts index a5692563f3..e6a9a6c696 100644 --- a/src/server/api/stream/channels/channel.ts +++ b/src/server/api/stream/channels/channel.ts @@ -19,7 +19,7 @@ export default class extends Channel { this.channelId = params.channelId as string; // Subscribe stream - this.subscriber.on('notesStream', e => this.onNote(e)); + this.subscriber.on('notesStream', this.onNote); this.subscriber.on(`channelStream:${this.channelId}`, this.onEvent); this.emitTypersIntervalId = setInterval(this.emitTypers, 5000); } From 8cafc4ee5559664a1e4477e35260f65fcd199a2f Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:22:59 +0900 Subject: [PATCH 48/91] ev => data --- src/server/api/stream/index.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 89d9889220..7a980093f7 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -65,36 +65,36 @@ export default class Connection { } @autobind - private onUserEvent(ev: StreamMessages['user']['spec']) { // { type, body }と展開すると型も展開されてしまう - switch (ev.type) { + private onUserEvent(data: StreamMessages['user']['spec']) { // { type, body }と展開すると型も展開されてしまう + switch (data.type) { case 'follow': - this.following.add(ev.body.id); + this.following.add(data.body.id); break; case 'unfollow': - this.following.delete(ev.body.id); + this.following.delete(data.body.id); break; case 'mute': - this.muting.add(ev.body.id); + this.muting.add(data.body.id); break; case 'unmute': - this.muting.delete(ev.body.id); + this.muting.delete(data.body.id); break; // TODO: block events case 'followChannel': - this.followingChannels.add(ev.body.id); + this.followingChannels.add(data.body.id); break; case 'unfollowChannel': - this.followingChannels.delete(ev.body.id); + this.followingChannels.delete(data.body.id); break; case 'updateUserProfile': - this.userProfile = ev.body; + this.userProfile = data.body; break; case 'terminate': From 380d357a740b4b2d90158b57d1c496f0a5077aa6 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:27:20 +0900 Subject: [PATCH 49/91] refactor --- src/server/api/stream/index.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index 7a980093f7..ba0a8f6e25 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -47,8 +47,8 @@ export default class Connection { this.wsConnection.on('message', this.onWsConnectionMessage); - this.subscriber.on('broadcast', async ev => { - this.onBroadcastMessage(ev.type, ev.body); + this.subscriber.on('broadcast', data => { + this.onBroadcastMessage(data); }); if (this.user) { @@ -58,9 +58,7 @@ export default class Connection { this.updateFollowingChannels(); this.updateUserProfile(); - this.subscriber.on(`user:${this.user.id}`, ev => { - this.onUserEvent(ev); - }); + this.subscriber.on(`user:${this.user.id}`, this.onUserEvent); } } @@ -146,8 +144,8 @@ export default class Connection { } @autobind - private onBroadcastMessage(type: string, body: any) { - this.sendMessageToWs(type, body); + private onBroadcastMessage(data: StreamMessages['broadcast']['spec']) { + this.sendMessageToWs(data.type, data.body); } @autobind From 4ba33f24a5e62cc429d3782797ceac898cb58c5c Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:28:48 +0900 Subject: [PATCH 50/91] clean up --- src/server/api/stream/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index bf67ce90b2..7cb1213f21 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -302,4 +302,4 @@ export type StreamEventEmitter = UnionToIntersection void }をまとめてその交差型をEmitterにかけるとts(2590)にひっかかる // provide stream channels union -export type StreamChannels = StreamMessages[keyof StreamMessages]['name'] | 'notesStream'; +export type StreamChannels = StreamMessages[keyof StreamMessages]['name']; From 4bd42cf0710fe7669024c5a26c75112ab297935a Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:31:48 +0900 Subject: [PATCH 51/91] add type --- src/server/api/stream/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/index.ts b/src/server/api/stream/index.ts index ba0a8f6e25..5f1aaf0383 100644 --- a/src/server/api/stream/index.ts +++ b/src/server/api/stream/index.ts @@ -248,7 +248,7 @@ export default class Connection { } @autobind - private async onNoteStreamMessage(data: any) { + private async onNoteStreamMessage(data: StreamMessages['note']['spec']) { this.sendMessageToWs('noteUpdated', { id: data.body.id, type: data.type, From 217bf12aab11213e4c1a3891ff71db5c4cafc697 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:36:47 +0900 Subject: [PATCH 52/91] antenna --- src/server/api/stream/channels/antenna.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/server/api/stream/channels/antenna.ts b/src/server/api/stream/channels/antenna.ts index bf9c53c453..864e42dc66 100644 --- a/src/server/api/stream/channels/antenna.ts +++ b/src/server/api/stream/channels/antenna.ts @@ -3,6 +3,7 @@ import Channel from '../channel'; import { Notes } from '@/models/index'; import { isMutedUserRelated } from '@/misc/is-muted-user-related'; import { isBlockerUserRelated } from '@/misc/is-blocker-user-related'; +import { StreamMessages } from '../types'; export default class extends Channel { public readonly chName = 'antenna'; @@ -19,11 +20,9 @@ export default class extends Channel { } @autobind - private async onEvent(data: any) { - const { type, body } = data; - - if (type === 'note') { - const note = await Notes.pack(body.id, this.user, { detail: true }); + private async onEvent(data: StreamMessages['antenna']['spec']) { + if (data.type === 'note') { + const note = await Notes.pack(data.body.id, this.user, { detail: true }); // 流れてきたNoteがミュートしているユーザーが関わるものだったら無視する if (isMutedUserRelated(note, this.muting)) return; @@ -33,8 +32,6 @@ export default class extends Channel { this.connection.cacheNote(note); this.send('note', note); - } else { - this.send(type, body); } } From 0714c56c413b0849cd88c4637f9d279f603daf28 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 01:37:55 +0900 Subject: [PATCH 53/91] channel --- src/server/api/stream/channels/channel.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/api/stream/channels/channel.ts b/src/server/api/stream/channels/channel.ts index e6a9a6c696..e5c78bc695 100644 --- a/src/server/api/stream/channels/channel.ts +++ b/src/server/api/stream/channels/channel.ts @@ -5,6 +5,7 @@ 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 { StreamMessages } from '../types'; export default class extends Channel { public readonly chName = 'channel'; @@ -52,7 +53,7 @@ export default class extends Channel { } @autobind - private onEvent(data: any) { + private onEvent(data: StreamMessages['channel']['spec']) { if (data.type === 'typing') { const id = data.body; const begin = this.typers[id] == null; From c05e99b8f75171ba04b18706f8708aeaef29fc19 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 15:00:48 +0900 Subject: [PATCH 54/91] fix --- src/prelude/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/prelude/types.ts b/src/prelude/types.ts index b8c49f9292..0739402479 100644 --- a/src/prelude/types.ts +++ b/src/prelude/types.ts @@ -1 +1 @@ -export type Resolved

= P extends PromiseLike ? Resolved : never; +export type Resolved

= P extends PromiseLike ? R : never; From 04aa4a5e2c8c4b290e7e4bd5c5b89d17b6a8e007 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 15:35:59 +0900 Subject: [PATCH 55/91] add Packed type --- src/misc/schema.ts | 4 +++- src/models/repositories/note.ts | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index d27c9eff99..52fbbca43b 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -47,6 +47,8 @@ export const refs = { GalleryPost: packedGalleryPostSchema, }; +export type Packed = SchemaType + export interface Schema extends SimpleSchema { items?: Schema; properties?: Obj; @@ -92,7 +94,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/note.ts b/src/models/repositories/note.ts index 376a09d0c6..3a821e9d22 100644 --- a/src/models/repositories/note.ts +++ b/src/models/repositories/note.ts @@ -3,14 +3,14 @@ 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; +export type PackedNote = Packed<'Note'>; @EntityRepository(Note) export class NoteRepository extends Repository { From e2550e8dddaa9f5524733b962f85c93ea7598051 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 15:48:08 +0900 Subject: [PATCH 56/91] add PackedRef --- src/misc/schema.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index 52fbbca43b..f5e13d76d6 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -47,7 +47,9 @@ export const refs = { GalleryPost: packedGalleryPostSchema, }; -export type Packed = SchemaType +export type Packed = PackRef + +type PackRef = { [x in keyof s['properties']]: SchemaType }; export interface Schema extends SimpleSchema { items?: Schema; From e777feae9aba5e4c79afaa2a7d4e958da40084da Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 15:53:04 +0900 Subject: [PATCH 57/91] fix lint --- src/misc/schema.ts | 2 +- src/server/api/stream/channels/home-timeline.ts | 3 ++- src/server/api/stream/types.ts | 11 ++++++----- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index f5e13d76d6..fbcedbf2ff 100644 --- a/src/misc/schema.ts +++ b/src/misc/schema.ts @@ -47,7 +47,7 @@ export const refs = { GalleryPost: packedGalleryPostSchema, }; -export type Packed = PackRef +export type Packed = PackRef; type PackRef = { [x in keyof s['properties']]: SchemaType }; diff --git a/src/server/api/stream/channels/home-timeline.ts b/src/server/api/stream/channels/home-timeline.ts index 0e21ab552e..5482ccbfcf 100644 --- a/src/server/api/stream/channels/home-timeline.ts +++ b/src/server/api/stream/channels/home-timeline.ts @@ -5,6 +5,7 @@ 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 +19,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/types.ts b/src/server/api/stream/types.ts index 7cb1213f21..c4cba3d857 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -6,7 +6,7 @@ import { UserProfile } from '@/models/entities/user-profile'; import { PackedUser } from '@/models/repositories/user'; import { PackedNotification } from '@/models/repositories/notification'; import { Note } from '@/models/entities/note'; -import { PackedNote } from '@/models/repositories/note'; +// import { Packed<'Note'> } from '@/models/repositories/note'; import { Antenna } from '@/models/entities/antenna'; import { DriveFile } from '@/models/entities/drive-file'; import { PackedDriveFile } from '@/models/repositories/drive-file'; @@ -24,6 +24,7 @@ import { PackedReversiMatching } from '@/models/repositories/games/reversi/match import { AbuseUserReport } from '@/models/entities/abuse-user-report'; import { PackedSignin } from '@/models/repositories/signin'; import { Page } from '@/models/entities/page'; +import { Packed } from '@/misc/schema'; // 辞書(interface or type)から{ type, body }ユニオンを定義 // https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type @@ -59,9 +60,9 @@ export interface UserStreamTypes { export interface MainStreamTypes { notification: PackedNotification; - mention: PackedNote; - reply: PackedNote; - renote: PackedNote; + mention: Packed<'Note'>; + reply: Packed<'Note'>; + renote: Packed<'Note'>; follow: PackedUser; followed: PackedUser; unfollow: PackedUser; @@ -288,7 +289,7 @@ export type StreamMessages = { }; notes: { name: 'notesStream'; - spec: PackedNote; + spec: Packed<'Note'>; }; }; From 3afdfe848b1e5f442cd86985adce652ec3c98efb Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 21:11:06 +0900 Subject: [PATCH 58/91] add emoji schema --- src/models/repositories/emoji.ts | 44 +++++++++++++++++++++++++++++--- src/prelude/types.ts | 1 - 2 files changed, 41 insertions(+), 4 deletions(-) delete mode 100644 src/prelude/types.ts diff --git a/src/models/repositories/emoji.ts b/src/models/repositories/emoji.ts index 2dc5f5282a..24f03574fe 100644 --- a/src/models/repositories/emoji.ts +++ b/src/models/repositories/emoji.ts @@ -1,14 +1,14 @@ import { EntityRepository, Repository } from 'typeorm'; import { Emoji } from '@/models/entities/emoji'; -import { Resolved } from '@/prelude/types'; +import { SchemaType } from '@/misc/schema'; -export type PackedEmoji = Resolved>; +export type PackedEmoji = SchemaType; @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 { @@ -27,3 +27,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/prelude/types.ts b/src/prelude/types.ts deleted file mode 100644 index b8c49f9292..0000000000 --- a/src/prelude/types.ts +++ /dev/null @@ -1 +0,0 @@ -export type Resolved

= P extends PromiseLike ? Resolved : never; From ce0f3741b9eb7294d67a671b56d80a8ae266a474 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 21:39:02 +0900 Subject: [PATCH 59/91] add reversiGame --- src/models/repositories/games/reversi/game.ts | 153 +++++++++++++++++- 1 file changed, 147 insertions(+), 6 deletions(-) diff --git a/src/models/repositories/games/reversi/game.ts b/src/models/repositories/games/reversi/game.ts index 10433bf58f..121a3cad74 100644 --- a/src/models/repositories/games/reversi/game.ts +++ b/src/models/repositories/games/reversi/game.ts @@ -2,9 +2,9 @@ import { User } from '@/models/entities/user'; import { EntityRepository, Repository } from 'typeorm'; import { Users } from '../../../index'; import { ReversiGame } from '@/models/entities/games/reversi/game'; -import { Resolved } from '@/prelude/types'; +import { SchemaType } from '@/misc/schema'; -export type PackedReversiGame = Resolved>; +export type PackedReversiGame = SchemaType; @EntityRepository(ReversiGame) export class ReversiGameRepository extends Repository { @@ -14,7 +14,7 @@ export class ReversiGameRepository extends Repository { options?: { detail?: boolean } - ) { + ): Promise { const opts = Object.assign({ detail: true }, options); @@ -23,8 +23,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, @@ -44,9 +44,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, + } + } + } +}; From ef98e4ab4f1c14b51af139f97431b50ea55d953e Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 21:44:32 +0900 Subject: [PATCH 60/91] add reversiMatching --- .../repositories/games/reversi/matching.ts | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts index 2696f1f8ea..0cf3b9fd35 100644 --- a/src/models/repositories/games/reversi/matching.ts +++ b/src/models/repositories/games/reversi/matching.ts @@ -3,21 +3,21 @@ 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 { Resolved } from '@/prelude/types'; +import { SchemaType } from '@/misc/schema'; -export type PackedReversiMatching = Resolved>; +export type PackedReversiMatching = SchemaType; @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 @@ -29,3 +29,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, + }, + } +}; From ee3457cb094cbec4b43261bae9400b4461250856 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 21:46:26 +0900 Subject: [PATCH 61/91] remove signin schema (use Signin entity) --- src/models/repositories/signin.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/models/repositories/signin.ts b/src/models/repositories/signin.ts index 8038760742..9942d2d962 100644 --- a/src/models/repositories/signin.ts +++ b/src/models/repositories/signin.ts @@ -1,8 +1,5 @@ import { EntityRepository, Repository } from 'typeorm'; import { Signin } from '@/models/entities/signin'; -import { Resolved } from '@/prelude/types'; - -export type PackedSignin = Resolved>; @EntityRepository(Signin) export class SigninRepository extends Repository { From e749b756a0d54085d25f0b93fc4886f8f665c26f Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:12:48 +0900 Subject: [PATCH 62/91] add schemas refs, fix Packed type --- src/misc/schema.ts | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index fbcedbf2ff..4131875ef7 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,11 +48,12 @@ export const refs = { Clip: packedClipSchema, FederationInstance: packedFederationInstanceSchema, GalleryPost: packedGalleryPostSchema, + Emoji: packedEmojiSchema, + ReversiGame: packedReversiGameSchema, + ReversiMatching: packedReversiMatchingSchema, }; -export type Packed = PackRef; - -type PackRef = { [x in keyof s['properties']]: SchemaType }; +export type Packed = ObjType<(typeof refs[x])['properties']>; export interface Schema extends SimpleSchema { items?: Schema; From dee40b33d25008f2642f15e99f27b44534401dae Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:18:26 +0900 Subject: [PATCH 63/91] wip PackedHoge => Packed<'Hoge'> --- src/server/api/stream/types.ts | 71 +++++++++++++++------------------- 1 file changed, 31 insertions(+), 40 deletions(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index c4cba3d857..b3a2df0020 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -3,26 +3,17 @@ import Emitter from 'strict-event-emitter-types'; import { Channel } from '@/models/entities/channel'; import { User } from '@/models/entities/user'; import { UserProfile } from '@/models/entities/user-profile'; -import { PackedUser } from '@/models/repositories/user'; -import { PackedNotification } from '@/models/repositories/notification'; import { Note } from '@/models/entities/note'; -// import { Packed<'Note'> } from '@/models/repositories/note'; import { Antenna } from '@/models/entities/antenna'; import { DriveFile } from '@/models/entities/drive-file'; -import { PackedDriveFile } from '@/models/repositories/drive-file'; import { DriveFolder } from '@/models/entities/drive-folder'; -import { PackedDriveFolder } from '@/models/repositories/drive-folder'; import { Emoji } from '@/models/entities/emoji'; -import { PackedEmoji } from '@/models/repositories/emoji'; import { UserList } from '@/models/entities/user-list'; import { MessagingMessage } from '@/models/entities/messaging-message'; -import { PackedMessagingMessage } from '@/models/repositories/messaging-message'; import { UserGroup } from '@/models/entities/user-group'; import { ReversiGame } from '@/models/entities/games/reversi/game'; -import { PackedReversiGame } from '@/models/repositories/games/reversi/game'; -import { PackedReversiMatching } from '@/models/repositories/games/reversi/matching'; import { AbuseUserReport } from '@/models/entities/abuse-user-report'; -import { PackedSignin } from '@/models/repositories/signin'; +import { Signin } from '@/models/entities/signin'; import { Page } from '@/models/entities/page'; import { Packed } from '@/misc/schema'; @@ -42,7 +33,7 @@ export interface InternalStreamTypes { export interface BroadcastTypes { emojiAdded: { - emoji: PackedEmoji; + emoji: Packed<'Emoji'>; }; } @@ -53,40 +44,40 @@ export interface UserStreamTypes { updateUserProfile: UserProfile; mute: User; unmute: User; - follow: PackedUser; - unfollow: PackedUser; - userAdded: PackedUser; + follow: Packed<'User'>; + unfollow: Packed<'User'>; + userAdded: Packed<'User'>; } export interface MainStreamTypes { - notification: PackedNotification; + notification: Packed<'Notification'>; mention: Packed<'Note'>; reply: Packed<'Note'>; renote: Packed<'Note'>; - follow: PackedUser; - followed: PackedUser; - unfollow: PackedUser; - meUpdated: PackedUser; + follow: Packed<'User'>; + followed: Packed<'User'>; + unfollow: Packed<'User'>; + meUpdated: Packed<'User'>; pageEvent: { pageId: Page['id']; event: string; var: any; userId: User['id']; - user: PackedUser; + user: Packed<'User'>; }; urlUploadFinished: { marker?: string | null; - file: PackedDriveFile; + file: Packed<'DriveFile'>; }; readAllNotifications: undefined; - unreadNotification: PackedNotification; + unreadNotification: Packed<'Notification'>; unreadMention: Note['id']; readAllUnreadMentions: undefined; unreadSpecifiedNote: Note['id']; readAllUnreadSpecifiedNotes: undefined; readAllMessagingMessages: undefined; - messagingMessage: PackedMessagingMessage; - unreadMessagingMessage: PackedMessagingMessage; + messagingMessage: Packed<'MessagingMessage'>; + unreadMessagingMessage: Packed<'MessagingMessage'>; readAllAntennas: undefined; unreadAntenna: Antenna; readAllAnnouncements: undefined; @@ -94,24 +85,24 @@ export interface MainStreamTypes { unreadChannel: Note['id']; myTokenRegenerated: undefined; reversiNoInvites: undefined; - reversiInvited: PackedReversiMatching; - signin: PackedSignin; + reversiInvited: Packed<'ReversiMatching'>; + signin: Signin; registryUpdated: { scope?: string[]; key: string; value: any | null; }; - driveFileCreated: PackedDriveFile; + driveFileCreated: Packed<'DriveFile'>; readAntenna: Antenna; } export interface DriveStreamTypes { - fileCreated: PackedDriveFile; + fileCreated: Packed<'DriveFile'>; fileDeleted: DriveFile['id']; - fileUpdated: PackedDriveFile; - folderCreated: PackedDriveFolder; + fileUpdated: Packed<'DriveFile'>; + folderCreated: Packed<'DriveFolder'>; folderDeleted: DriveFolder['id']; - folderUpdated: PackedDriveFolder; + folderUpdated: Packed<'DriveFolder'>; } export interface NoteStreamTypes { @@ -144,8 +135,8 @@ export interface ChannelStreamTypes { } export interface UserListStreamTypes { - userAdded: PackedUser; - userRemoved: PackedUser; + userAdded: Packed<'User'>; + userRemoved: Packed<'User'>; } export interface AntennaStreamTypes { @@ -155,7 +146,7 @@ export interface AntennaStreamTypes { export interface MessagingStreamTypes { read: MessagingMessage['id'][]; typing: User['id']; - message: PackedMessagingMessage; + message: Packed<'MessagingMessage'>; deleted: MessagingMessage['id']; } @@ -165,25 +156,25 @@ export interface GroupMessagingStreamTypes { userId: User['id']; }; typing: User['id']; - message: PackedMessagingMessage; + message: Packed<'MessagingMessage'>; deleted: MessagingMessage['id']; } export interface MessagingIndexStreamTypes { read: MessagingMessage['id'][]; - message: PackedMessagingMessage; + message: Packed<'MessagingMessage'>; } export interface ReversiStreamTypes { - matched: PackedReversiGame; - invited: PackedReversiMatching; + matched: Packed<'ReversiGame'>; + invited: Packed<'ReversiMatching'>; } export interface ReversiGameStreamTypes { - started: PackedReversiGame; + started: Packed<'ReversiGame'>; ended: { winnerId?: User['id'] | null, - game: PackedReversiGame; + game: Packed<'ReversiGame'>; }; updateSettings: { key: string; From a97fb08af09fb91ee7a159c827ab6b60047860ed Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:20:21 +0900 Subject: [PATCH 64/91] add Packed type --- src/misc/schema.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/misc/schema.ts b/src/misc/schema.ts index d27c9eff99..4131875ef7 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 : From 1f82a983848108a9ce44e5280837886ed00e45c1 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:34:27 +0900 Subject: [PATCH 65/91] note-reaction --- src/models/repositories/note-reaction.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/note-reaction.ts b/src/models/repositories/note-reaction.ts index e73a832109..ba74076f6c 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 { From d7488715df4a956b52ee25a8350ea31a5e7978d8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:40:18 +0900 Subject: [PATCH 66/91] user --- src/models/repositories/user.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/user.ts b/src/models/repositories/user.ts index 39c90cf5ed..b6f27e32e2 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 From 3eb79b23bcc23742919f9ad88e7926b4a5a5f15a Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:40:51 +0900 Subject: [PATCH 67/91] user-group --- src/models/repositories/user-group.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/user-group.ts b/src/models/repositories/user-group.ts index a76ac7b9d3..b38a2fb50d 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({ From c9926414a0dcca06b7dc7c9deffdaedf52fc0c48 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:41:38 +0900 Subject: [PATCH 68/91] user-list --- src/models/repositories/user-list.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/user-list.ts b/src/models/repositories/user-list.ts index 809dbe0268..331c278e6f 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({ From 677a6aae2afe13417d26f4dc47b3f7078b4cfc52 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:47:03 +0900 Subject: [PATCH 69/91] note --- src/misc/check-hit-antenna.ts | 4 ++-- src/models/repositories/note.ts | 8 +++----- src/server/api/stream/channels/channel.ts | 4 ++-- src/server/api/stream/channels/global-timeline.ts | 4 ++-- src/server/api/stream/channels/hashtag.ts | 4 ++-- src/server/api/stream/channels/home-timeline.ts | 4 ++-- src/server/api/stream/channels/hybrid-timeline.ts | 4 ++-- src/server/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 | 14 +++++++------- 11 files changed, 30 insertions(+), 32 deletions(-) diff --git a/src/misc/check-hit-antenna.ts b/src/misc/check-hit-antenna.ts index 38965f4b0d..3789054b26 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/models/repositories/note.ts b/src/models/repositories/note.ts index 376a09d0c6..c0ac22b2db 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/server/api/stream/channels/channel.ts b/src/server/api/stream/channels/channel.ts index e6a9a6c696..72ddbf93b4 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 384ed61409..f5983ab472 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 997ab75f6d..281be4f2eb 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 0e21ab552e..52e9aec250 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 0b28ff616b..51f95fc0cd 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 20061410c4..a6166c2be2 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 0ca83cd658..63b254605b 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 f83bc9331e..ccd555e149 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 2e221d553a..f25f86da9c 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)) { @@ -52,7 +52,7 @@ export default async function( if (note.user != null) { // たぶんnullになることは無いはずだけど一応 for (const antenna of myAntennas) { - if (checkHitAntenna(antenna, note, note.user as any, undefined, Array.from(following))) { + if (await checkHitAntenna(antenna, note, note.user as any, undefined, Array.from(following))) { readAntennaNotes.push(note); } } From 02f6142d018dbce0b56dec15fd18d04cbce80365 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:52:16 +0900 Subject: [PATCH 70/91] app, messaging-message --- src/models/repositories/app.ts | 6 ++---- src/models/repositories/messaging-message.ts | 6 ++---- src/services/push-notification.ts | 4 ++-- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/models/repositories/app.ts b/src/models/repositories/app.ts index 2287bd4390..3bd7af05a0 100644 --- a/src/models/repositories/app.ts +++ b/src/models/repositories/app.ts @@ -1,9 +1,7 @@ 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'; @EntityRepository(App) export class AppRepository extends Repository { @@ -15,7 +13,7 @@ export class AppRepository extends Repository { includeSecret?: boolean, includeProfileImageIds?: boolean } - ): Promise { + ): Promise> { const opts = Object.assign({ detail: false, includeSecret: false, diff --git a/src/models/repositories/messaging-message.ts b/src/models/repositories/messaging-message.ts index f97905af2f..abdff63689 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/services/push-notification.ts b/src/services/push-notification.ts index 5bd7499692..23781acbe2 100644 --- a/src/services/push-notification.ts +++ b/src/services/push-notification.ts @@ -3,10 +3,10 @@ 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 = PackedNotification | Packed<'MessagingMessage'>; export default async function(userId: string, type: notificationType, body: notificationBody) { const meta = await fetchMeta(); From 295ad3521091617bfdc1146127bcfc5ad4aba275 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:53:06 +0900 Subject: [PATCH 71/91] notification --- src/models/repositories/notification.ts | 6 ++---- src/services/push-notification.ts | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/models/repositories/notification.ts b/src/models/repositories/notification.ts index b7f9e3643c..d1cf9b087e 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/services/push-notification.ts b/src/services/push-notification.ts index 23781acbe2..5949d11b3b 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 { Packed } from '@/misc/schema'; type notificationType = 'notification' | 'unreadMessagingMessage'; -type notificationBody = PackedNotification | Packed<'MessagingMessage'>; +type notificationBody = Packed<'Notification'> | Packed<'MessagingMessage'>; export default async function(userId: string, type: notificationType, body: notificationBody) { const meta = await fetchMeta(); From 59ac258272a02e27be8b5fb7a13d4b2b1e1ba8ea Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:54:15 +0900 Subject: [PATCH 72/91] drive-file --- src/models/repositories/drive-file.ts | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/models/repositories/drive-file.ts b/src/models/repositories/drive-file.ts index 63bd020cbe..ddf9a46afd 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 From 8f67adb8174255617666264fd931e7a7d9592cf4 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:54:51 +0900 Subject: [PATCH 73/91] drive-folder --- src/models/repositories/drive-folder.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/drive-folder.ts b/src/models/repositories/drive-folder.ts index bc73018f29..8ef6f01b5d 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); From fad785bebf966cdb560f4d482bf052fbc59981ec Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:55:21 +0900 Subject: [PATCH 74/91] following --- src/models/repositories/following.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/following.ts b/src/models/repositories/following.ts index 24ddd0d676..b1f716069f 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 = {}; From b98687244d67d595a73b374518a2264e37e71ff9 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:56:03 +0900 Subject: [PATCH 75/91] muting --- src/models/repositories/muting.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/muting.ts b/src/models/repositories/muting.ts index d957b1792d..869afd3c4e 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({ From 3d54fb24d5f776821ec2c65da6e13ead7296ee85 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:56:32 +0900 Subject: [PATCH 76/91] blocking --- src/models/repositories/blocking.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/blocking.ts b/src/models/repositories/blocking.ts index 515b3a6b16..ac60c9a4ce 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({ From 4dfebbd0fee3957c1f591703c158ed3860554556 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:56:55 +0900 Subject: [PATCH 77/91] hashtag --- src/models/repositories/hashtag.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/hashtag.ts b/src/models/repositories/hashtag.ts index ee42ad16b6..d52f6ba7c6 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, From 2c7daf8f0ee4d1807abbd4eecc1e29ed4bb99ae7 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 22:57:23 +0900 Subject: [PATCH 78/91] page --- src/models/repositories/page.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/page.ts b/src/models/repositories/page.ts index 1a61e2c99c..3a3642d7ec 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); From 8e9cfb8a90a88de90b3396d83f2fb7cfb1f2d60f Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:03:58 +0900 Subject: [PATCH 79/91] app (with modifying schema) --- src/models/repositories/app.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/models/repositories/app.ts b/src/models/repositories/app.ts index 3bd7af05a0..c48d069558 100644 --- a/src/models/repositories/app.ts +++ b/src/models/repositories/app.ts @@ -50,13 +50,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, From 5ed72999a9520e58e66823ba156a2bb54be2a7f6 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:04:48 +0900 Subject: [PATCH 80/91] import user? --- src/models/repositories/app.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/models/repositories/app.ts b/src/models/repositories/app.ts index c48d069558..0226edad11 100644 --- a/src/models/repositories/app.ts +++ b/src/models/repositories/app.ts @@ -2,6 +2,7 @@ import { EntityRepository, Repository } from 'typeorm'; import { App } from '@/models/entities/app'; import { AccessTokens } from '../index'; import { Packed } from '@/misc/schema'; +import { User } from '../entities/user'; @EntityRepository(App) export class AppRepository extends Repository { From df10aa40f4b2ff388423ad455f0c76dc598e6c07 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:05:28 +0900 Subject: [PATCH 81/91] channel --- src/models/repositories/channel.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/channel.ts b/src/models/repositories/channel.ts index 4bb829f570..5c7d095473 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; From 3bf7e4bf02993aedcb31af4c4ccabc3d04ea45a8 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:06:04 +0900 Subject: [PATCH 82/91] antenna --- src/models/repositories/antenna.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/antenna.ts b/src/models/repositories/antenna.ts index e61eed5e08..657de55581 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; From 3a4e3d78b2a7af8be8c47e1d991eddac5c8afa60 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:06:27 +0900 Subject: [PATCH 83/91] clip --- src/models/repositories/clip.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/clip.ts b/src/models/repositories/clip.ts index e3d718bef4..7892811d48 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({ From c71844c2921443120a6a9e62ac4feff157f101a9 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:07:45 +0900 Subject: [PATCH 84/91] gallery-post --- src/models/repositories/gallery-post.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/gallery-post.ts b/src/models/repositories/gallery-post.ts index afa22e9edf..4f666ff252 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); From 77ed1d7dc4f891c8356a61d6647d524c02e25dfd Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:08:10 +0900 Subject: [PATCH 85/91] emoji --- src/models/repositories/emoji.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/emoji.ts b/src/models/repositories/emoji.ts index 24f03574fe..7985c27aba 100644 --- a/src/models/repositories/emoji.ts +++ b/src/models/repositories/emoji.ts @@ -1,14 +1,12 @@ import { EntityRepository, Repository } from 'typeorm'; import { Emoji } from '@/models/entities/emoji'; -import { SchemaType } from '@/misc/schema'; - -export type PackedEmoji = SchemaType; +import { Packed } from '@/misc/schema'; @EntityRepository(Emoji) export class EmojiRepository extends Repository { public async pack( src: Emoji['id'] | Emoji, - ): Promise { + ): Promise> { const emoji = typeof src === 'object' ? src : await this.findOneOrFail(src); return { From 6b72d888f82063f2f0d56170b36f5ffa94f6e6a1 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:08:42 +0900 Subject: [PATCH 86/91] Packed --- src/models/repositories/games/reversi/game.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/games/reversi/game.ts b/src/models/repositories/games/reversi/game.ts index 121a3cad74..9adb386fa9 100644 --- a/src/models/repositories/games/reversi/game.ts +++ b/src/models/repositories/games/reversi/game.ts @@ -2,9 +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 { SchemaType } from '@/misc/schema'; - -export type PackedReversiGame = SchemaType; +import { Packed } from '@/misc/schema'; @EntityRepository(ReversiGame) export class ReversiGameRepository extends Repository { @@ -14,7 +12,7 @@ export class ReversiGameRepository extends Repository { options?: { detail?: boolean } - ): Promise { + ): Promise> { const opts = Object.assign({ detail: true }, options); From f8df218bbbdbbac76b548a362cebbb39b5c5cd3d Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:09:17 +0900 Subject: [PATCH 87/91] reversi-matching --- src/models/repositories/games/reversi/matching.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/models/repositories/games/reversi/matching.ts b/src/models/repositories/games/reversi/matching.ts index 0cf3b9fd35..b4515800df 100644 --- a/src/models/repositories/games/reversi/matching.ts +++ b/src/models/repositories/games/reversi/matching.ts @@ -3,16 +3,14 @@ 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 { SchemaType } from '@/misc/schema'; - -export type PackedReversiMatching = SchemaType; +import { Packed } from '@/misc/schema'; @EntityRepository(ReversiMatching) export class ReversiMatchingRepository extends Repository { public async pack( src: ReversiMatching['id'] | ReversiMatching, me: { id: User['id'] } - ): Promise { + ): Promise> { const matching = typeof src === 'object' ? src : await this.findOneOrFail(src); return await awaitAll({ From b2f27e9b4ec7bcac8bdd6e8c2a5b89811f4745b4 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:14:50 +0900 Subject: [PATCH 88/91] update stream.ts --- src/services/stream.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/stream.ts b/src/services/stream.ts index c21ccb4a74..2c308a1b54 100644 --- a/src/services/stream.ts +++ b/src/services/stream.ts @@ -25,7 +25,7 @@ import { UserListStreamTypes, UserStreamTypes } from '@/server/api/stream/types'; -import { PackedNote } from '@/models/repositories/note'; +import { Packed } from '@/misc/schema'; class Publisher { private publish = (channel: StreamChannels, type: string | null, value?: any): void => { @@ -98,7 +98,7 @@ class Publisher { this.publish(`reversiGameStream:${gameId}`, type, typeof value === 'undefined' ? null : value); } - public publishNotesStream = (note: PackedNote): void => { + public publishNotesStream = (note: Packed<'Note'>): void => { this.publish('notesStream', null, note); } From 7fd5152f73a5850d8148e96087f2ecf2d1a863f6 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:21:19 +0900 Subject: [PATCH 89/91] https://github.com/misskey-dev/misskey/pull/7769#issuecomment-917542339 --- src/server/api/stream/types.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index b3a2df0020..4508b4a371 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -19,9 +19,10 @@ import { Packed } from '@/misc/schema'; // 辞書(interface or type)から{ type, body }ユニオンを定義 // https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type +type EventUnions = { [K in keyof T]: { type: K; body: T[K]; } } type EventUnionFromDictionary< T extends object, - U = { [K in keyof T]: { type: K; body: T[K]; } } + U = EventUnions > = U[keyof U]; //#region Stream type-body definitions From 9f4ad3c8730bd8350321f63a2a5b494ac7ee7af2 Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:38:12 +0900 Subject: [PATCH 90/91] fix lint --- src/server/api/stream/types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 4508b4a371..72451628de 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -19,7 +19,7 @@ import { Packed } from '@/misc/schema'; // 辞書(interface or type)から{ type, body }ユニオンを定義 // https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type -type EventUnions = { [K in keyof T]: { type: K; body: T[K]; } } +type EventUnions = { [K in keyof T]: { type: K; body: T[K]; } }; type EventUnionFromDictionary< T extends object, U = EventUnions From 2a591861e7c9f55d716b9e90105bbce0b258ce7b Mon Sep 17 00:00:00 2001 From: tamaina Date: Sun, 12 Sep 2021 23:49:21 +0900 Subject: [PATCH 91/91] clean up? --- src/server/api/stream/types.ts | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/server/api/stream/types.ts b/src/server/api/stream/types.ts index 72451628de..c58a627eb3 100644 --- a/src/server/api/stream/types.ts +++ b/src/server/api/stream/types.ts @@ -17,14 +17,6 @@ import { Signin } from '@/models/entities/signin'; import { Page } from '@/models/entities/page'; import { Packed } from '@/misc/schema'; -// 辞書(interface or type)から{ type, body }ユニオンを定義 -// https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type -type EventUnions = { [K in keyof T]: { type: K; body: T[K]; } }; -type EventUnionFromDictionary< - T extends object, - U = EventUnions -> = U[keyof U]; - //#region Stream type-body definitions export interface InternalStreamTypes { antennaCreated: Antenna; @@ -217,6 +209,15 @@ export interface AdminStreamTypes { } //#endregion +// 辞書(interface or type)から{ type, body }ユニオンを定義 +// https://stackoverflow.com/questions/49311989/can-i-infer-the-type-of-a-value-using-extends-keyof-type +// VS Codeの展開を防止するためにEvents型を定義 +type Events = { [K in keyof T]: { type: K; body: T[K]; } }; +type EventUnionFromDictionary< + T extends object, + U = Events +> = U[keyof U]; + // name/messages(spec) pairs dictionary export type StreamMessages = { internal: { @@ -287,11 +288,11 @@ export type StreamMessages = { // API event definitions // ストリームごとのEmitterの辞書を用意 -type EventsDictionary = { [x in keyof StreamMessages]: Emitter void }> }; +type EventEmitterDictionary = { [x in keyof StreamMessages]: Emitter void }> }; // 共用体型を交差型にする型 https://stackoverflow.com/questions/54938141/typescript-convert-union-to-intersection type UnionToIntersection = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never; -// Emitter辞書をストリームごとに共用体型にし、UnionToIntersectionで交差型にする -export type StreamEventEmitter = UnionToIntersection; +// Emitter辞書から共用体型を作り、UnionToIntersectionで交差型にする +export type StreamEventEmitter = UnionToIntersection; // { [y in name]: (e: spec) => void }をまとめてその交差型をEmitterにかけるとts(2590)にひっかかる // provide stream channels union