feat(misskey-js): multipart/form-dataのリクエストに対応 (#14147)
* feat(misskey-js): multipart/form-dataのリクエストに対応 * lint * add test * Update Changelog * テストを厳しくする * lint * multipart/form-dataではnullのプロパティを弾くように
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import './autogen/apiClientJSDoc.js';
|
||||
|
||||
import { SwitchCaseResponseType } from './api.types.js';
|
||||
import type { Endpoints } from './api.types.js';
|
||||
import { endpointReqTypes } from './autogen/endpoint.js';
|
||||
import type { SwitchCaseResponseType, Endpoints } from './api.types.js';
|
||||
|
||||
export type {
|
||||
SwitchCaseResponseType,
|
||||
@@ -23,7 +23,7 @@ export function isAPIError(reason: Record<PropertyKey, unknown>): reason is APIE
|
||||
|
||||
export type FetchLike = (input: string, init?: {
|
||||
method?: string;
|
||||
body?: string;
|
||||
body?: Blob | FormData | string;
|
||||
credentials?: RequestCredentials;
|
||||
cache?: RequestCache;
|
||||
headers: { [key in string]: string }
|
||||
@@ -49,20 +49,55 @@ export class APIClient {
|
||||
this.fetch = opts.fetch ?? ((...args) => fetch(...args));
|
||||
}
|
||||
|
||||
private assertIsRecord<T>(obj: T): obj is T & Record<string, any> {
|
||||
return obj !== null && typeof obj === 'object' && !Array.isArray(obj);
|
||||
}
|
||||
|
||||
public request<E extends keyof Endpoints, P extends Endpoints[E]['req']>(
|
||||
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({
|
||||
let mediaType = 'application/json';
|
||||
if (endpoint in endpointReqTypes) {
|
||||
mediaType = endpointReqTypes[endpoint];
|
||||
}
|
||||
let payload: FormData | string = '{}';
|
||||
|
||||
if (mediaType === 'application/json') {
|
||||
payload = JSON.stringify({
|
||||
...params,
|
||||
i: credential !== undefined ? credential : this.credential,
|
||||
}),
|
||||
});
|
||||
} else if (mediaType === 'multipart/form-data') {
|
||||
payload = new FormData();
|
||||
const i = credential !== undefined ? credential : this.credential;
|
||||
if (i != null) {
|
||||
payload.append('i', i);
|
||||
}
|
||||
if (this.assertIsRecord(params)) {
|
||||
for (const key in params) {
|
||||
const value = params[key];
|
||||
|
||||
if (value == null) continue;
|
||||
|
||||
if (value instanceof File || value instanceof Blob) {
|
||||
payload.append(key, value);
|
||||
} else if (typeof value === 'object') {
|
||||
payload.append(key, JSON.stringify(value));
|
||||
} else {
|
||||
payload.append(key, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.fetch(`${this.origin}/api/${endpoint}`, {
|
||||
method: 'POST',
|
||||
body: payload,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Content-Type': endpointReqTypes[endpoint],
|
||||
},
|
||||
credentials: 'omit',
|
||||
cache: 'no-cache',
|
||||
|
Reference in New Issue
Block a user