import { packedUserLiteSchema, packedUserDetailedNotMeOnlySchema, packedMeDetailedOnlySchema, packedUserDetailedNotMeSchema, packedMeDetailedSchema, packedUserDetailedSchema, packedUserSchema, } from '@/models/schema/user'; import { packedNoteSchema } from '@/models/schema/note'; import { packedUserListSchema } from '@/models/schema/user-list'; import { packedAppSchema } from '@/models/schema/app'; import { packedMessagingMessageSchema } from '@/models/schema/messaging-message'; import { packedNotificationSchema } from '@/models/schema/notification'; import { packedDriveFileSchema } from '@/models/schema/drive-file'; import { packedDriveFolderSchema } from '@/models/schema/drive-folder'; import { packedFollowingSchema } from '@/models/schema/following'; import { packedMutingSchema } from '@/models/schema/muting'; import { packedBlockingSchema } from '@/models/schema/blocking'; import { packedNoteReactionSchema } from '@/models/schema/note-reaction'; import { packedHashtagSchema } from '@/models/schema/hashtag'; import { packedPageSchema } from '@/models/schema/page'; import { packedUserGroupSchema } from '@/models/schema/user-group'; import { packedNoteFavoriteSchema } from '@/models/schema/note-favorite'; import { packedChannelSchema } from '@/models/schema/channel'; import { packedAntennaSchema } from '@/models/schema/antenna'; import { packedClipSchema } from '@/models/schema/clip'; import { packedFederationInstanceSchema } from '@/models/schema/federation-instance'; import { packedQueueCountSchema } from '@/models/schema/queue'; import { packedGalleryPostSchema } from '@/models/schema/gallery-post'; import { packedEmojiSchema } from '@/models/schema/emoji'; export const refs = { UserLite: packedUserLiteSchema, UserDetailedNotMeOnly: packedUserDetailedNotMeOnlySchema, MeDetailedOnly: packedMeDetailedOnlySchema, UserDetailedNotMe: packedUserDetailedNotMeSchema, MeDetailed: packedMeDetailedSchema, UserDetailed: packedUserDetailedSchema, 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, Emoji: packedEmojiSchema, }; // Packed = SchemaTypeDef; とすると展開されてマウスホバー時に型表示が使い物にならなくなる // ObjTypeを指定すると(なぜか)展開されずにPacked<'Hoge'>と表示される type PackedDef; allOf?: ReadonlyArray }> = r['allOf'] extends ReadonlyArray ? UnionToIntersection> : r['oneOf'] extends ReadonlyArray ? UnionSchemaType : r['properties'] extends Obj ? ObjType : never; export type Packed = PackedDef; type TypeStringef = 'boolean' | 'number' | 'string' | 'array' | 'object' | 'any'; type StringDefToType = T extends 'boolean' ? boolean : T extends 'number' ? number : T extends 'string' ? string | Date : T extends 'array' ? ReadonlyArray : T extends 'object' ? Record : any; // https://swagger.io/specification/?sbsearch=optional#schema-object type OfSchema = { readonly anyOf?: ReadonlyArray; readonly oneOf?: ReadonlyArray; readonly allOf?: ReadonlyArray; } export interface MinimumSchema extends OfSchema { readonly type?: TypeStringef; readonly nullable?: boolean; readonly optional?: boolean; readonly items?: MinimumSchema; readonly properties?: Obj; readonly description?: string; readonly example?: any; readonly format?: string; readonly ref?: keyof typeof refs; readonly enum?: ReadonlyArray; readonly default?: (this['type'] extends TypeStringef ? StringDefToType : any) | null; readonly maxLength?: number; readonly minLength?: number; } export interface Schema extends MinimumSchema { readonly nullable: boolean; readonly optional: boolean; } type NonUndefinedPropertyNames = { [K in keyof T]: T[K]['optional'] extends true ? never : K }[keyof T]; type UndefinedPropertyNames = { [K in keyof T]: T[K]['optional'] extends true ? K : never }[keyof T]; export interface Obj { [key: string]: Schema; } export type ObjType = { -readonly [P in UndefinedPropertyNames]?: SchemaType } & { -readonly [P in NonUndefinedPropertyNames]: SchemaType }; type NullOrUndefined

= p['nullable'] extends true ? p['optional'] extends true ? (T | null | undefined) : (T | null) : p['optional'] extends true ? (T | undefined) : T; // 共用体型を交差型にする型 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; // https://github.com/misskey-dev/misskey/pull/8144#discussion_r785287552 // 単純にSchemaTypeDefで判定するだけではダメ type UnionSchemaType = X extends any ? SchemaType : never; type ArrayUnion = T extends any ? Array : never; export type SchemaTypeDef

= p['type'] extends 'number' ? number : p['type'] extends 'string' ? ( p['enum'] extends readonly string[] ? p['enum'][number] : p['format'] extends 'date-time' ? string : // Dateにする?? string ) : p['type'] extends 'boolean' ? boolean : p['type'] extends 'object' ? ( p['ref'] extends keyof typeof refs ? Packed : p['properties'] extends NonNullable ? ObjType : p['anyOf'] extends ReadonlyArray ? UnionSchemaType & Partial>> : p['allOf'] extends ReadonlyArray ? UnionToIntersection> : any ) : p['type'] extends 'array' ? ( p['items'] extends OfSchema ? ( p['items']['anyOf'] extends ReadonlyArray ? UnionSchemaType>[] : p['items']['oneOf'] extends ReadonlyArray ? ArrayUnion>> : p['items']['allOf'] extends ReadonlyArray ? UnionToIntersection>>[] : never ) : p['items'] extends NonNullable ? SchemaTypeDef[] : any[] ) : p['oneOf'] extends ReadonlyArray ? UnionSchemaType : any; export type SchemaType

= NullOrUndefined>;