Skip to content

Commit f35433f

Browse files
committed
feat: enhance APIClient constructor to accept options for custom fetch implementation
chore: update biome configuration schema to 2.2.2 and remove deprecated settings test: add test for APIClient constructor with options
1 parent 3652905 commit f35433f

File tree

4 files changed

+30
-18
lines changed

4 files changed

+30
-18
lines changed

.vscode/settings.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"editor.defaultFormatter": "biomejs.biome"
1919
},
2020
"editor.codeActionsOnSave": {
21-
"source.organizeImports.biome": "explicit",
22-
"quickfix.biome": "explicit"
21+
"source.fixAll.biome": "explicit"
2322
}
2423
}

biome.json

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
{
2-
"$schema": "https://biomejs.dev/schemas/1.7.1/schema.json",
3-
"organizeImports": {
4-
"enabled": true
5-
},
2+
"$schema": "https://biomejs.dev/schemas/2.2.2/schema.json",
63
"linter": {
74
"enabled": true,
85
"rules": {
@@ -22,7 +19,6 @@
2219
"useImportType": "off"
2320
},
2421
"suspicious": {
25-
"noConsoleLog": "warn",
2622
"noEmptyBlockStatements": "warn",
2723
"noSkippedTests": "error"
2824
}
@@ -34,11 +30,5 @@
3430
"clientKind": "git",
3531
"defaultBranch": "main",
3632
"useIgnoreFile": true
37-
},
38-
"overrides": [
39-
{
40-
"include": ["**/*.md"],
41-
"formatter": { "indentStyle": "tab" }
42-
}
43-
]
33+
}
4434
}

src/index.test.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import {
44
beforeEach,
55
describe,
66
expect,
7+
mock,
78
test,
89
} from "bun:test";
9-
import { http, HttpResponse } from "msw";
10+
import { HttpResponse, http } from "msw";
1011
import { setupServer } from "msw/native";
1112

1213
import { APIClient } from ".";
@@ -31,6 +32,19 @@ describe(APIClient.name, () => {
3132
expect(client).toBeInstanceOf(APIClient);
3233
});
3334

35+
test("#constructor with options", async () => {
36+
let customFetch = mock<typeof fetch>().mockImplementation(globalThis.fetch);
37+
let client = new APIClient(new URL("https://example.com"), {
38+
fetch: customFetch as any as typeof fetch,
39+
});
40+
41+
expect(client).toBeInstanceOf(APIClient);
42+
await client.fetch("/path");
43+
expect(customFetch).toHaveBeenCalledWith(
44+
new Request("https://example.com/path"),
45+
);
46+
});
47+
3448
test("#fetch", async () => {
3549
let client = new APIClient(new URL("https://example.com"));
3650
let response = await client.fetch("/path");

src/index.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,14 @@
2323
export class APIClient implements APIClient.Type {
2424
/** The base URL for all API requests. Must be defined in subclasses. */
2525
protected readonly baseURL: URL;
26+
protected options: APIClient.Options;
2627

27-
constructor(baseURL: URL) {
28+
constructor(
29+
baseURL: URL,
30+
options: APIClient.Options = { fetch: globalThis.fetch },
31+
) {
2832
this.baseURL = baseURL;
33+
this.options = options;
2934
}
3035

3136
public interceptors = {
@@ -53,7 +58,7 @@ export class APIClient implements APIClient.Type {
5358
* @param response - The response object that was received.
5459
* @returns A promise that resolves to the (possibly processed) response.
5560
*/
56-
protected async after(request: Request, response: Response) {
61+
protected async after(_request: Request, response: Response) {
5762
return response;
5863
}
5964

@@ -74,7 +79,7 @@ export class APIClient implements APIClient.Type {
7479
request = await listener(request);
7580
}
7681

77-
let response = await fetch(request);
82+
let response = await this.options.fetch(request);
7883
response = await this.after(request, response);
7984
for (let listener of this.interceptors.after.listeners) {
8085
response = await listener(request, response);
@@ -179,4 +184,8 @@ export namespace APIClient {
179184
patch(path: string, init?: Omit<RequestInit, "method">): Promise<Response>;
180185
delete(path: string, init?: Omit<RequestInit, "method">): Promise<Response>;
181186
}
187+
188+
export interface Options {
189+
fetch: typeof globalThis.fetch;
190+
}
182191
}

0 commit comments

Comments
 (0)