diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 2e9bc76059..ef4409e7d9 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -41,6 +41,7 @@ "@swc/cli": "0.1.62", "@swc/core": "1.3.56", "eventemitter3": "5.0.1", + "json-schema-to-ts": "^2.8.0", "reconnecting-websocket": "4.4.0" } } diff --git a/packages/misskey-js/src/endpoints.ts b/packages/misskey-js/src/endpoints.ts index bbeaaf8646..3a5325d22c 100644 --- a/packages/misskey-js/src/endpoints.ts +++ b/packages/misskey-js/src/endpoints.ts @@ -1,4 +1,5 @@ import { localUsernameSchema, passwordSchema } from "./schemas/user"; +import type { JSONSchema7 } from 'json-schema-to-ts'; export type RolePolicies = { gtlAvailable: boolean; @@ -33,7 +34,7 @@ export interface IEndpointMeta { }; }; - readonly defines: { req: Schema | undefined; res: Schema | undefined; }[]; + readonly defines: ReadonlyArray<{ req: JSONSchema7 | undefined; res: JSONSchema7 | undefined; }>; /** * このエンドポイントにリクエストするのにユーザー情報が必須か否か @@ -132,14 +133,13 @@ export const endpoints = { required: ['username', 'password'], }, res: { - type: 'object', - ref: 'User', + $ref: '/schemas/User', properties: { token: { type: 'string', }, - required: ['token'], }, + required: ['token'], }, }], }, @@ -159,4 +159,4 @@ export const endpoints = { res: undefined, }], }, -} as const; +} as const satisfies { [x: string]: IEndpointMeta; }; diff --git a/packages/misskey-js/src/schemas.ts b/packages/misskey-js/src/schemas.ts new file mode 100644 index 0000000000..506627a8d9 --- /dev/null +++ b/packages/misskey-js/src/schemas.ts @@ -0,0 +1,78 @@ +import type { FromSchema, JSONSchema7Reference } from 'json-schema-to-ts'; + +import { IdSchema } from './schemas/id.js'; +import { + packedUserLiteSchema, + packedUserDetailedNotMeOnlySchema, + packedMeDetailedOnlySchema, + packedUserDetailedNotMeSchema, + packedMeDetailedSchema, + packedUserDetailedSchema, + packedUserSchema, +} from './schemas/user.js'; +import { packedNoteSchema } from './schemas/note.js'; +import { packedUserListSchema } from './schemas/user-list.js'; +import { packedAppSchema } from './schemas/app.js'; +import { packedNotificationSchema } from './schemas/notification.js'; +import { packedDriveFileSchema } from './schemas/drive-file.js'; +import { packedDriveFolderSchema } from './schemas/drive-folder.js'; +import { packedFollowingSchema } from './schemas/following.js'; +import { packedMutingSchema } from './schemas/muting.js'; +import { packedRenoteMutingSchema } from './schemas/renote-muting.js'; +import { packedBlockingSchema } from './schemas/blocking.js'; +import { packedNoteReactionSchema } from './schemas/note-reaction.js'; +import { packedHashtagSchema } from './schemas/hashtag.js'; +import { packedPageSchema } from './schemas/page.js'; +import { packedNoteFavoriteSchema } from './schemas/note-favorite.js'; +import { packedChannelSchema } from './schemas/channel.js'; +import { packedAntennaSchema } from './schemas/antenna.js'; +import { packedClipSchema } from './schemas/clip.js'; +import { packedFederationInstanceSchema } from './schemas/federation-instance.js'; +import { packedQueueCountSchema } from './schemas/queue.js'; +import { packedGalleryPostSchema } from './schemas/gallery-post.js'; +import { packedEmojiDetailedSchema, packedEmojiSimpleSchema } from './schemas/emoji.js'; +import { packedFlashSchema } from './schemas/flash.js'; + +export const refs = { + UserLite: packedUserLiteSchema, + UserDetailedNotMeOnly: packedUserDetailedNotMeOnlySchema, + MeDetailedOnly: packedMeDetailedOnlySchema, + UserDetailedNotMe: packedUserDetailedNotMeSchema, + MeDetailed: packedMeDetailedSchema, + UserDetailed: packedUserDetailedSchema, + User: packedUserSchema, + + UserList: packedUserListSchema, + App: packedAppSchema, + Note: packedNoteSchema, + NoteReaction: packedNoteReactionSchema, + NoteFavorite: packedNoteFavoriteSchema, + Notification: packedNotificationSchema, + DriveFile: packedDriveFileSchema, + DriveFolder: packedDriveFolderSchema, + Following: packedFollowingSchema, + Muting: packedMutingSchema, + RenoteMuting: packedRenoteMutingSchema, + Blocking: packedBlockingSchema, + Hashtag: packedHashtagSchema, + Page: packedPageSchema, + Channel: packedChannelSchema, + QueueCount: packedQueueCountSchema, + Antenna: packedAntennaSchema, + Clip: packedClipSchema, + FederationInstance: packedFederationInstanceSchema, + GalleryPost: packedGalleryPostSchema, + EmojiSimple: packedEmojiSimpleSchema, + EmojiDetailed: packedEmojiDetailedSchema, + Flash: packedFlashSchema, +} as const satisfies { [x: string]: JSONSchema7Reference }; + +type Refs = typeof packedAntennaSchema | typeof packedNoteSchema; // TODO: typeof refs[keyof typeof refs]; +type UnionToArray = T extends any ? [T, ...A] : never; + +export type References = [ + typeof IdSchema, + ...UnionToArray +]; + +export type Packed = FromSchema diff --git a/packages/misskey-js/src/schemas/antenna.ts b/packages/misskey-js/src/schemas/antenna.ts index ac7ea65b35..04e34c8b5c 100644 --- a/packages/misskey-js/src/schemas/antenna.ts +++ b/packages/misskey-js/src/schemas/antenna.ts @@ -1,3 +1,5 @@ +import type { JSONSchema7Reference } from 'json-schema-to-ts'; + export const packedAntennaSchema = { $id: '/schemas/Antenna', @@ -88,4 +90,4 @@ export const packedAntennaSchema = { 'isActive', 'hasUnreadNote', ], -} as const; +} as const satisfies JSONSchema7Reference; diff --git a/packages/misskey-js/src/schemas/note.ts b/packages/misskey-js/src/schemas/note.ts index 82c8b36cd5..79e93602f9 100644 --- a/packages/misskey-js/src/schemas/note.ts +++ b/packages/misskey-js/src/schemas/note.ts @@ -1,3 +1,5 @@ +import type { JSONSchema7Reference } from 'json-schema-to-ts'; + export const packedNoteSchema = { $id: '/schemas/Note', @@ -156,4 +158,4 @@ export const packedNoteSchema = { 'renoteCount', 'repliesCount', ], -} as const; +} as const satisfies JSONSchema7Reference; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0010581416..8c449f16de 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -973,6 +973,9 @@ importers: eventemitter3: specifier: 5.0.1 version: 5.0.1 + json-schema-to-ts: + specifier: ^2.8.0 + version: 2.8.0 reconnecting-websocket: specifier: 4.4.0 version: 4.4.0 @@ -6590,7 +6593,6 @@ packages: /@types/json-schema@7.0.11: resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==} - dev: true /@types/json5@0.0.29: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} @@ -13800,6 +13802,15 @@ packages: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} dev: true + /json-schema-to-ts@2.8.0: + resolution: {integrity: sha512-fNAnQ6N0a/0rJlqkzKBdb+5EnMgcKTlrAwMLg3adlKRTT1uNNT4ziqwBzMhj4vp768pO9PoQzZcUyv3QWmD0pQ==} + engines: {node: '>=16'} + dependencies: + '@babel/runtime': 7.21.0 + '@types/json-schema': 7.0.11 + ts-algebra: 1.2.0 + dev: false + /json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -18762,6 +18773,10 @@ packages: escape-string-regexp: 5.0.0 dev: false + /ts-algebra@1.2.0: + resolution: {integrity: sha512-kMuJJd8B2N/swCvIvn1hIFcIOrLGbWl9m/J6O3kHx9VRaevh00nvgjPiEGaRee7DRaAczMYR2uwWvXU22VFltw==} + dev: false + /ts-dedent@2.2.0: resolution: {integrity: sha512-q5W7tVM71e2xjHZTlgfTDoPF/SmqKG5hddq9SzR49CH2hayqRKJtQ4mtRlSxKaJlR/+9rEM+mnBHf7I2/BQcpQ==} engines: {node: '>=6.10'}