バックエンドが生成するapi.jsonからmisskey-jsの型を作成する (#12434)

* ひとまず生成できるところまで

* ファイル構成整理

* 生成コマンド整理

* misskey-jsへの組み込み

* fix generator.ts

* wip

* fix generator.ts

* fix package.json

* 生成ロジックの調整

* 型レベルでのswitch-case機構をmisskey-jsからfrontendに持ち込めるようにした

* 型チェック用のtsconfig.jsonを作成

* 他のエンドポイントを呼ぶ関数にも適用

* 未使用エンティティなどを削除

* misskey-js側で手動定義されていた型を自動生成された型に移行(ただしapi.jsonがvalidでなくなってしまったので後で修正する)

* messagingは廃止されている(テストのビルドエラー解消)

* validなapi.jsonを出力できるように修正

* 修正漏れ対応

* Ajvに怒られて起動できなかったところを修正

* fix ci(途中)

* パラメータenumをやめる

* add command

* add api.json

* 都度自動生成をやめる

* 一気通貫スクリプト修正

* fix ci

* 生成ロジック修正

* フロントの型チェックは結局やらなかったので戻しておく

* fix pnpm-lock.yaml

* add README.md

---------

Co-authored-by: osamu <46447427+sam-osamu@users.noreply.github.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
おさむのひと 2023-12-02 21:00:05 +09:00 committed by GitHub
parent 92029ac325
commit 336416261a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
42 changed files with 27053 additions and 3964 deletions

View file

@ -1,4 +1,9 @@
import type { Endpoints } from './api.types.js';
import { SwitchCaseResponseType } from './api.types';
import type { Endpoints } from './api.types';
export {
SwitchCaseResponseType,
} from './api.types';
const MK_API_ERROR = Symbol();
@ -15,25 +20,15 @@ export function isAPIError(reason: any): reason is APIError {
}
export type FetchLike = (input: string, init?: {
method?: string;
body?: string;
credentials?: RequestCredentials;
cache?: RequestCache;
headers: {[key in string]: string}
}) => Promise<{
status: number;
json(): Promise<any>;
}>;
type IsNeverType<T> = [T] extends [never] ? true : false;
type StrictExtract<Union, Cond> = Cond extends Union ? Union : never;
type IsCaseMatched<E extends keyof Endpoints, P extends Endpoints[E]['req'], C extends number> =
IsNeverType<StrictExtract<Endpoints[E]['res']['$switch']['$cases'][C], [P, any]>> extends false ? true : false;
type GetCaseResult<E extends keyof Endpoints, P extends Endpoints[E]['req'], C extends number> =
StrictExtract<Endpoints[E]['res']['$switch']['$cases'][C], [P, any]>[1];
method?: string;
body?: string;
credentials?: RequestCredentials;
cache?: RequestCache;
headers: { [key in string]: string }
}) => Promise<{
status: number;
json(): Promise<any>;
}>;
export class APIClient {
public origin: string;
@ -53,22 +48,11 @@ export class APIClient {
}
public request<E extends keyof Endpoints, P extends Endpoints[E]['req']>(
endpoint: E, params: P = {} as P, credential?: string | null | undefined,
): Promise<Endpoints[E]['res'] extends { $switch: { $cases: [any, any][]; $default: any; }; }
?
IsCaseMatched<E, P, 0> extends true ? GetCaseResult<E, P, 0> :
IsCaseMatched<E, P, 1> extends true ? GetCaseResult<E, P, 1> :
IsCaseMatched<E, P, 2> extends true ? GetCaseResult<E, P, 2> :
IsCaseMatched<E, P, 3> extends true ? GetCaseResult<E, P, 3> :
IsCaseMatched<E, P, 4> extends true ? GetCaseResult<E, P, 4> :
IsCaseMatched<E, P, 5> extends true ? GetCaseResult<E, P, 5> :
IsCaseMatched<E, P, 6> extends true ? GetCaseResult<E, P, 6> :
IsCaseMatched<E, P, 7> extends true ? GetCaseResult<E, P, 7> :
IsCaseMatched<E, P, 8> extends true ? GetCaseResult<E, P, 8> :
IsCaseMatched<E, P, 9> extends true ? GetCaseResult<E, P, 9> :
Endpoints[E]['res']['$switch']['$default']
: Endpoints[E]['res']> {
const promise = new Promise((resolve, reject) => {
endpoint: E,
params: P = {} as P,
credential?: string | null,
): Promise<SwitchCaseResponseType<E, P>> {
return new Promise((resolve, reject) => {
this.fetch(`${this.origin}/api/${endpoint}`, {
method: 'POST',
body: JSON.stringify({
@ -83,10 +67,8 @@ export class APIClient {
}).then(async (res) => {
const body = res.status === 204 ? null : await res.json();
if (res.status === 200) {
if (res.status === 200 || res.status === 204) {
resolve(body);
} else if (res.status === 204) {
resolve(null);
} else {
reject({
[MK_API_ERROR]: true,
@ -95,7 +77,5 @@ export class APIClient {
}
}).catch(reject);
});
return promise as any;
}
}