From cee1d5e2d01359e6d762a10fc67d4e7c1cc830eb Mon Sep 17 00:00:00 2001 From: Kagami Sascha Rosylight Date: Thu, 30 Mar 2023 02:33:19 +0200 Subject: chore: integrate misskey-js as a workspace item (git subtree) (#10409) * Additional changes for the merge * api-misskey-js --- packages/misskey-js/src/api.ts | 102 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 packages/misskey-js/src/api.ts (limited to 'packages/misskey-js/src/api.ts') diff --git a/packages/misskey-js/src/api.ts b/packages/misskey-js/src/api.ts new file mode 100644 index 0000000000..fcc9884465 --- /dev/null +++ b/packages/misskey-js/src/api.ts @@ -0,0 +1,102 @@ +import type { Endpoints } from './api.types'; + +const MK_API_ERROR = Symbol(); + +export type APIError = { + id: string; + code: string; + message: string; + kind: 'client' | 'server'; + info: Record; +}; + +export function isAPIError(reason: any): reason is APIError { + return reason[MK_API_ERROR] === true; +} + +export type FetchLike = (input: string, init?: { + method?: string; + body?: string; + credentials?: RequestCredentials; + cache?: RequestCache; + headers: {[key in string]: string} + }) => Promise<{ + status: number; + json(): Promise; + }>; + +type IsNeverType = [T] extends [never] ? true : false; + +type StrictExtract = Cond extends Union ? Union : never; + +type IsCaseMatched = + IsNeverType> extends false ? true : false; + +type GetCaseResult = + StrictExtract[1]; + +export class APIClient { + public origin: string; + public credential: string | null | undefined; + public fetch: FetchLike; + + constructor(opts: { + origin: APIClient['origin']; + credential?: APIClient['credential']; + fetch?: APIClient['fetch'] | null | undefined; + }) { + this.origin = opts.origin; + this.credential = opts.credential; + // ネイティブ関数をそのまま変数に代入して使おうとするとChromiumではIllegal invocationエラーが発生するため、 + // 環境で実装されているfetchを使う場合は無名関数でラップして使用する + this.fetch = opts.fetch || ((...args) => fetch(...args)); + } + + public request( + endpoint: E, params: P = {} as P, credential?: string | null | undefined, + ): Promise extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + IsCaseMatched extends true ? GetCaseResult : + Endpoints[E]['res']['$switch']['$default'] + : Endpoints[E]['res']> + { + const promise = new Promise((resolve, reject) => { + this.fetch(`${this.origin}/api/${endpoint}`, { + method: 'POST', + body: JSON.stringify({ + ...params, + i: credential !== undefined ? credential : this.credential, + }), + headers: { + 'Content-Type': 'application/json', + }, + credentials: 'omit', + cache: 'no-cache', + }).then(async (res) => { + const body = res.status === 204 ? null : await res.json(); + + if (res.status === 200) { + resolve(body); + } else if (res.status === 204) { + resolve(null); + } else { + reject({ + [MK_API_ERROR]: true, + ...body.error, + }); + } + }).catch(reject); + }); + + return promise as any; + } +} -- cgit v1.2.3-freya