Skip to content
Snippets Groups Projects
Commit bdb59253 authored by syuilo's avatar syuilo
Browse files

update api api

parent 3557741f
No related branches found
No related tags found
No related merge requests found
...@@ -18,21 +18,13 @@ coming soon ...@@ -18,21 +18,13 @@ coming soon
todo todo
## API request ## API request
都度インスタンスやトークンを指定する場合
``` ts
import * as Misskey from 'misskey-js';
const meta = await Misskey.api.request('https://misskey.test', 'meta', { detail: true }, 'TOKEN');
```
最初にインスタンスやトークンを指定し、以後のリクエストでその情報を使いまわす場合
``` ts ``` ts
import * as Misskey from 'misskey-js'; import * as Misskey from 'misskey-js';
const cli = new Misskey.api.APIClient({ const cli = new Misskey.api.APIClient({
origin: 'https://misskey.test' origin: 'https://misskey.test',
credential: 'TOKEN',
}); });
cli.i = { token: 'TOKEN' };
const meta = await cli.request('meta', { detail: true }); const meta = await cli.request('meta', { detail: true });
``` ```
......
...@@ -14,54 +14,51 @@ export function isAPIError(reason: any): reason is APIError { ...@@ -14,54 +14,51 @@ export function isAPIError(reason: any): reason is APIError {
return reason[MK_API_ERROR] === true; return reason[MK_API_ERROR] === true;
} }
export function request<E extends keyof Endpoints>(
origin: string,
endpoint: E,
data: Endpoints[E]['req'] = {},
credential: string | null | undefined,
): Promise<Endpoints[E]['res']> {
const promise = new Promise<Endpoints[E]['res']>((resolve, reject) => {
// Append a credential
if (credential !== undefined) (data as Record<string, any>).i = credential;
// Send request
fetch(`${origin}/api/${endpoint}`, {
method: 'POST',
body: JSON.stringify(data),
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;
}
export class APIClient { export class APIClient {
public i: { token: string; } | null = null; public origin: string;
private origin: string; public credential: string | null | undefined;
public fetch: (typeof fetch);
constructor(opts: { constructor(opts: {
origin: APIClient['origin']; origin: APIClient['origin'];
credential?: APIClient['credential'];
fetch?: APIClient['fetch'] | null | undefined;
}) { }) {
this.origin = opts.origin; this.origin = opts.origin;
this.credential = opts.credential;
this.fetch = opts.fetch || fetch;
} }
public request<E extends keyof Endpoints>( public request<E extends keyof Endpoints>(
endpoint: E, data: Endpoints[E]['req'] = {}, credential?: string | null | undefined, endpoint: E, data: Endpoints[E]['req'] = {}, credential?: string | null | undefined,
): Promise<Endpoints[E]['res']> { ): Promise<Endpoints[E]['res']> {
return request(this.origin, endpoint, data, credential === undefined ? this.i?.token : credential); const promise = new Promise<Endpoints[E]['res']>((resolve, reject) => {
// Append a credential
if (this.credential) (data as Record<string, any>).i = this.credential;
if (credential) (data as Record<string, any>).i = credential;
// Send request
this.fetch(`${this.origin}/api/${endpoint}`, {
method: 'POST',
body: JSON.stringify(data),
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;
} }
} }
import { request } from '../src/api'; import { APIClient } from '../src/api';
import { enableFetchMocks } from 'jest-fetch-mock'; import { enableFetchMocks } from 'jest-fetch-mock';
enableFetchMocks(); enableFetchMocks();
...@@ -21,16 +21,22 @@ describe('API', () => { ...@@ -21,16 +21,22 @@ describe('API', () => {
fetchMock.mockResponse(async (req) => { fetchMock.mockResponse(async (req) => {
const body = await req.json(); const body = await req.json();
if (req.method == 'POST' && req.url == 'https://misskey.test/api/i') { if (req.method == 'POST' && req.url == 'https://misskey.test/api/i') {
if (typeof body.i != 'string') { if (body.i === 'TOKEN') {
return JSON.stringify({ id: 'foo' });
} else {
return { status: 400 }; return { status: 400 };
} }
return JSON.stringify({ id: 'foo' });
} else { } else {
return { status: 404 }; return { status: 404 };
} }
}); });
const res = await request('https://misskey.test', 'i', {}, 'TOKEN'); const cli = new APIClient({
origin: 'https://misskey.test',
credential: 'TOKEN',
});
const res = await cli.request('i');
// validate response // validate response
expect(res).toEqual({ expect(res).toEqual({
...@@ -60,11 +66,18 @@ describe('API', () => { ...@@ -60,11 +66,18 @@ describe('API', () => {
}); });
try { try {
await request('https://misskey.test', 'i', {}, 'TOKEN'); const cli = new APIClient({
origin: 'https://misskey.test',
credential: 'TOKEN',
});
await cli.request('i');
} catch (e) { } catch (e) {
expect(e.id).toEqual('5d37dbcb-891e-41ca-a3d6-e690c97775ac'); expect(e.id).toEqual('5d37dbcb-891e-41ca-a3d6-e690c97775ac');
} }
}); });
// TODO: ネットワークエラーのテスト // TODO: ネットワークエラーのテスト
// TODO: JSON以外が返ってきた場合のハンドリング
}); });
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment