diff --git a/app/__test__/api/MediaApi.spec.ts b/app/__test__/api/MediaApi.spec.ts index fffca386..95cac8e9 100644 --- a/app/__test__/api/MediaApi.spec.ts +++ b/app/__test__/api/MediaApi.spec.ts @@ -1,8 +1,8 @@ /// 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, filename: string) { diff --git a/app/src/Api.ts b/app/src/Api.ts index 1c26cbca..3b356f69 100644 --- a/app/src/Api.ts +++ b/app/src/Api.ts @@ -8,6 +8,11 @@ import { omitKeys } from "core/utils"; export type TApiUser = SafeUser; +export type ApiFetcher = ( + input: RequestInfo | URL, + init?: RequestInit, +) => Response | Promise; + 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; } & ( diff --git a/app/src/media/api/MediaApi.ts b/app/src/media/api/MediaApi.ts index 2b2eaea8..ceff6a4c 100644 --- a/app/src/media/api/MediaApi.ts +++ b/app/src/media/api/MediaApi.ts @@ -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 { protected override getDefaultOptions(): Partial { return { basepath: "/api/media", + upload_fetcher: fetch, }; } @@ -109,10 +113,12 @@ export class MediaApi extends ModuleApi { filename?: string; _init?: Omit; 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 { item: Request | Response | string | File | ReadableStream, opts?: { _init?: Omit; + fetcher?: typeof fetch; }, ) { return this.upload(item, { diff --git a/app/src/modules/ModuleApi.ts b/app/src/modules/ModuleApi.ts index b4c3eec0..ebb64036 100644 --- a/app/src/modules/ModuleApi.ts +++ b/app/src/modules/ModuleApi.ts @@ -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 = { export type TInput = string | (string | number | PrimaryFieldType)[]; export abstract class ModuleApi { - protected fetcher: typeof fetch; + protected fetcher: ApiFetcher; constructor( protected readonly _options: Partial = {}, - fetcher?: typeof fetch, + fetcher?: ApiFetcher, ) { this.fetcher = fetcher ?? fetch; } @@ -221,7 +222,7 @@ export class FetchPromise> implements Promise { constructor( public request: Request, protected options?: { - fetcher?: typeof fetch; + fetcher?: ApiFetcher; verbose?: boolean; }, // keep "any" here, it gets inferred correctly with the "refine" fn