modify MediaApi to support custom fetch implementation, defaults to native fetch (#158)

* modify MediaApi to support custom fetch implementation, defaults to native fetch

added an optional `fetcher` parameter to allow usage of a custom fetch function in both `upload` and `fetcher` methods. Defaults to the standard `fetch` if none is provided.

* fix tests and improve api fetcher types
This commit is contained in:
dswbx
2025-04-22 15:44:55 +02:00
committed by GitHub
parent 5763a6e150
commit a1be1b4bf4
4 changed files with 27 additions and 10 deletions
+8 -4
View File
@@ -1,8 +1,8 @@
/// <reference types="@types/bun" />
import { describe, expect, it } from "bun:test";
import { Hono } from "hono";
import { getFileFromContext, isFile, isReadableStream } from "../../src/core/utils";
import { MediaApi } from "../../src/media/api/MediaApi";
import { getFileFromContext, isFile, isReadableStream } from "core/utils";
import { MediaApi } from "media/api/MediaApi";
import { assetsPath, assetsTmpPath } from "../helper";
const mockedBackend = new Hono()
@@ -121,8 +121,12 @@ describe("MediaApi", () => {
});
it("should upload file in various ways", async () => {
// @ts-ignore tests
const api = new MediaApi({}, mockedBackend.request);
const api = new MediaApi(
{
upload_fetcher: mockedBackend.request,
},
mockedBackend.request,
);
const file = Bun.file(`${assetsPath}/image.png`);
async function matches(req: Promise<any>, filename: string) {
+6 -1
View File
@@ -8,6 +8,11 @@ import { omitKeys } from "core/utils";
export type TApiUser = SafeUser;
export type ApiFetcher = (
input: RequestInfo | URL,
init?: RequestInit,
) => Response | Promise<Response>;
declare global {
interface Window {
__BKND__: {
@@ -21,7 +26,7 @@ export type ApiOptions = {
headers?: Headers;
key?: string;
localStorage?: boolean;
fetcher?: typeof fetch;
fetcher?: ApiFetcher;
verbose?: boolean;
verified?: boolean;
} & (
+9 -2
View File
@@ -6,13 +6,17 @@ import {
type TInput,
} from "modules/ModuleApi";
import type { FileWithPath } from "ui/elements/media/file-selector";
import type { ApiFetcher } from "Api";
export type MediaApiOptions = BaseModuleApiOptions & {};
export type MediaApiOptions = BaseModuleApiOptions & {
upload_fetcher: ApiFetcher;
};
export class MediaApi extends ModuleApi<MediaApiOptions> {
protected override getDefaultOptions(): Partial<MediaApiOptions> {
return {
basepath: "/api/media",
upload_fetcher: fetch,
};
}
@@ -109,10 +113,12 @@ export class MediaApi extends ModuleApi<MediaApiOptions> {
filename?: string;
_init?: Omit<RequestInit, "body">;
path?: TInput;
fetcher?: ApiFetcher;
} = {},
) {
if (item instanceof Request || typeof item === "string") {
const res = await this.fetcher(item);
const fetcher = opts.fetcher ?? this.options.upload_fetcher;
const res = await fetcher(item);
if (!res.ok || !res.body) {
throw new Error("Failed to fetch file");
}
@@ -143,6 +149,7 @@ export class MediaApi extends ModuleApi<MediaApiOptions> {
item: Request | Response | string | File | ReadableStream,
opts?: {
_init?: Omit<RequestInit, "body">;
fetcher?: typeof fetch;
},
) {
return this.upload(item, {
+4 -3
View File
@@ -1,6 +1,7 @@
import { $console, type PrimaryFieldType } from "core";
import { isDebug } from "core/env";
import { encodeSearch } from "core/utils/reqres";
import type { ApiFetcher } from "Api";
export type { PrimaryFieldType };
export type BaseModuleApiOptions = {
@@ -24,11 +25,11 @@ export type ApiResponse<Data = any> = {
export type TInput = string | (string | number | PrimaryFieldType)[];
export abstract class ModuleApi<Options extends BaseModuleApiOptions = BaseModuleApiOptions> {
protected fetcher: typeof fetch;
protected fetcher: ApiFetcher;
constructor(
protected readonly _options: Partial<Options> = {},
fetcher?: typeof fetch,
fetcher?: ApiFetcher,
) {
this.fetcher = fetcher ?? fetch;
}
@@ -221,7 +222,7 @@ export class FetchPromise<T = ApiResponse<any>> implements Promise<T> {
constructor(
public request: Request,
protected options?: {
fetcher?: typeof fetch;
fetcher?: ApiFetcher;
verbose?: boolean;
},
// keep "any" here, it gets inferred correctly with the "refine" fn