/* * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ import * as Misskey from 'misskey-js'; import { ref } from 'vue'; import { apiUrl } from '@@/js/config.js'; import { $i } from '@/account.js'; export const pendingApiRequestsCount = ref(0); export type Endpoint = keyof Misskey.Endpoints; export type Request = Misskey.Endpoints[E]['req']; export type AnyRequest = (E extends Endpoint ? Request : never) | object; export type Response> = E extends Endpoint ? P extends Request ? Misskey.api.SwitchCaseResponseType : never : object; // Implements Misskey.api.ApiClient.request export function misskeyApi< ResT = void, E extends Endpoint | NonNullable = Endpoint, P extends AnyRequest = E extends Endpoint ? Request : never, _ResT = ResT extends void ? Response : ResT, >( endpoint: E, data: P & { i?: string | null; } = {} as any, token?: string | null | undefined, signal?: AbortSignal, ): Promise<_ResT> { if (endpoint.includes('://')) throw new Error('invalid endpoint'); pendingApiRequestsCount.value++; const onFinally = () => { pendingApiRequestsCount.value--; }; const promise = new Promise<_ResT>((resolve, reject) => { // Append a credential if ($i) data.i = $i.token; if (token !== undefined) data.i = token; // Send request window.fetch(`${apiUrl}/${endpoint}`, { method: 'POST', body: JSON.stringify(data), credentials: 'omit', cache: 'no-cache', headers: { 'Content-Type': 'application/json', }, signal, }).then(async (res) => { const body = res.status === 204 ? null : await res.json(); if (res.status === 200) { resolve(body); } else if (res.status === 204) { resolve(undefined as _ResT); // void -> undefined } else { reject(body.error); } }).catch(reject); }); promise.then(onFinally, onFinally); return promise; } // Implements Misskey.api.ApiClient.request export function misskeyApiGet< ResT = void, E extends keyof Misskey.Endpoints = keyof Misskey.Endpoints, P extends Misskey.Endpoints[E]['req'] = Misskey.Endpoints[E]['req'], _ResT = ResT extends void ? Misskey.api.SwitchCaseResponseType : ResT, >( endpoint: E, data: P = {} as any, ): Promise<_ResT> { pendingApiRequestsCount.value++; const onFinally = () => { pendingApiRequestsCount.value--; }; const query = new URLSearchParams(data as any); const promise = new Promise<_ResT>((resolve, reject) => { // Send request window.fetch(`${apiUrl}/${endpoint}?${query}`, { method: 'GET', credentials: 'omit', cache: 'default', }).then(async (res) => { const body = res.status === 204 ? null : await res.json(); if (res.status === 200) { resolve(body); } else if (res.status === 204) { resolve(undefined as _ResT); // void -> undefined } else { reject(body.error); } }).catch(reject); }); promise.then(onFinally, onFinally); return promise; }