From 6756b138f3afabcab9bceacea231419d920d8048 Mon Sep 17 00:00:00 2001 From: Jacob Gillespie Date: Mon, 8 Nov 2021 09:51:21 +0000 Subject: [PATCH] feat: allow providing custom fetch implementation (#24) --- src/SupabaseStorageClient.ts | 7 ++++--- src/lib/StorageBucketApi.ts | 26 ++++++++++++++++++++------ src/lib/StorageFileApi.ts | 17 ++++++++++++++--- src/lib/fetch.ts | 19 +++++++++++++------ 4 files changed, 51 insertions(+), 18 deletions(-) diff --git a/src/SupabaseStorageClient.ts b/src/SupabaseStorageClient.ts index a2e32b3..05ee5f4 100644 --- a/src/SupabaseStorageClient.ts +++ b/src/SupabaseStorageClient.ts @@ -1,8 +1,9 @@ import { StorageBucketApi, StorageFileApi } from './lib' +import { Fetch } from './lib/fetch' export class SupabaseStorageClient extends StorageBucketApi { - constructor(url: string, headers: { [key: string]: string } = {}) { - super(url, headers) + constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) { + super(url, headers, fetch) } /** @@ -11,6 +12,6 @@ export class SupabaseStorageClient extends StorageBucketApi { * @param id The bucket id to operate on. */ from(id: string): StorageFileApi { - return new StorageFileApi(this.url, this.headers, id) + return new StorageFileApi(this.url, this.headers, id, this.fetch) } } diff --git a/src/lib/StorageBucketApi.ts b/src/lib/StorageBucketApi.ts index 9663a01..e2d7308 100644 --- a/src/lib/StorageBucketApi.ts +++ b/src/lib/StorageBucketApi.ts @@ -1,14 +1,16 @@ -import { get, post, put, remove } from './fetch' +import { Fetch, get, post, put, remove } from './fetch' import { Bucket } from './types' import { DEFAULT_HEADERS } from './constants' export class StorageBucketApi { protected url: string protected headers: { [key: string]: string } + protected fetch?: Fetch - constructor(url: string, headers: { [key: string]: string } = {}) { + constructor(url: string, headers: { [key: string]: string } = {}, fetch?: Fetch) { this.url = url this.headers = { ...DEFAULT_HEADERS, ...headers } + this.fetch = fetch } /** @@ -16,7 +18,7 @@ export class StorageBucketApi { */ async listBuckets(): Promise<{ data: Bucket[] | null; error: Error | null }> { try { - const data = await get(`${this.url}/bucket`, { headers: this.headers }) + const data = await get(this.fetch, `${this.url}/bucket`, { headers: this.headers }) return { data, error: null } } catch (error) { return { data: null, error } @@ -30,7 +32,7 @@ export class StorageBucketApi { */ async getBucket(id: string): Promise<{ data: Bucket | null; error: Error | null }> { try { - const data = await get(`${this.url}/bucket/${id}`, { headers: this.headers }) + const data = await get(this.fetch, `${this.url}/bucket/${id}`, { headers: this.headers }) return { data, error: null } } catch (error) { return { data: null, error } @@ -49,6 +51,7 @@ export class StorageBucketApi { ): Promise<{ data: string | null; error: Error | null }> { try { const data = await post( + this.fetch, `${this.url}/bucket`, { id, name: id, public: options.public }, { headers: this.headers } @@ -70,6 +73,7 @@ export class StorageBucketApi { ): Promise<{ data: { message: string } | null; error: Error | null }> { try { const data = await put( + this.fetch, `${this.url}/bucket/${id}`, { id, name: id, public: options.public }, { headers: this.headers } @@ -89,7 +93,12 @@ export class StorageBucketApi { id: string ): Promise<{ data: { message: string } | null; error: Error | null }> { try { - const data = await post(`${this.url}/bucket/${id}/empty`, {}, { headers: this.headers }) + const data = await post( + this.fetch, + `${this.url}/bucket/${id}/empty`, + {}, + { headers: this.headers } + ) return { data, error: null } } catch (error) { return { data: null, error } @@ -106,7 +115,12 @@ export class StorageBucketApi { id: string ): Promise<{ data: { message: string } | null; error: Error | null }> { try { - const data = await remove(`${this.url}/bucket/${id}`, {}, { headers: this.headers }) + const data = await remove( + this.fetch, + `${this.url}/bucket/${id}`, + {}, + { headers: this.headers } + ) return { data, error: null } } catch (error) { return { data: null, error } diff --git a/src/lib/StorageFileApi.ts b/src/lib/StorageFileApi.ts index 9452cce..7efb2f5 100644 --- a/src/lib/StorageFileApi.ts +++ b/src/lib/StorageFileApi.ts @@ -1,4 +1,4 @@ -import { FetchParameters, get, post, remove } from './fetch' +import { Fetch, FetchParameters, get, post, remove } from './fetch' import { isBrowser } from './helpers' import { FileObject, FileOptions, SearchOptions } from './types' import fetch from 'cross-fetch' @@ -22,11 +22,18 @@ export class StorageFileApi { protected url: string protected headers: { [key: string]: string } protected bucketId?: string + protected fetch?: Fetch - constructor(url: string, headers: { [key: string]: string } = {}, bucketId?: string) { + constructor( + url: string, + headers: { [key: string]: string } = {}, + bucketId?: string, + fetch?: Fetch + ) { this.url = url this.headers = headers this.bucketId = bucketId + this.fetch = fetch } /** @@ -165,6 +172,7 @@ export class StorageFileApi { ): Promise<{ data: { message: string } | null; error: Error | null }> { try { const data = await post( + this.fetch, `${this.url}/object/move`, { bucketId: this.bucketId, sourceKey: fromPath, destinationKey: toPath }, { headers: this.headers } @@ -192,6 +200,7 @@ export class StorageFileApi { try { const _path = this._getFinalPath(path) let data = await post( + this.fetch, `${this.url}/object/sign/${_path}`, { expiresIn }, { headers: this.headers } @@ -212,7 +221,7 @@ export class StorageFileApi { async download(path: string): Promise<{ data: Blob | null; error: Error | null }> { try { const _path = this._getFinalPath(path) - const res = await get(`${this.url}/object/${_path}`, { + const res = await get(this.fetch, `${this.url}/object/${_path}`, { headers: this.headers, noResolveJson: true, }) @@ -253,6 +262,7 @@ export class StorageFileApi { async remove(paths: string[]): Promise<{ data: FileObject[] | null; error: Error | null }> { try { const data = await remove( + this.fetch, `${this.url}/object/${this.bucketId}`, { prefixes: paths }, { headers: this.headers } @@ -307,6 +317,7 @@ export class StorageFileApi { try { const body = { ...DEFAULT_SEARCH_OPTIONS, ...options, prefix: path || '' } const data = await post( + this.fetch, `${this.url}/object/list/${this.bucketId}`, body, { headers: this.headers }, diff --git a/src/lib/fetch.ts b/src/lib/fetch.ts index 9a16348..50ea076 100644 --- a/src/lib/fetch.ts +++ b/src/lib/fetch.ts @@ -1,4 +1,6 @@ -import fetch from 'cross-fetch' +import crossFetch from 'cross-fetch' + +export type Fetch = typeof fetch export interface FetchOptions { headers?: { @@ -46,6 +48,7 @@ const _getRequestParams = ( } async function _handleRequest( + fetcher: Fetch = crossFetch, method: RequestMethodType, url: string, options?: FetchOptions, @@ -53,7 +56,7 @@ async function _handleRequest( body?: object ): Promise { return new Promise((resolve, reject) => { - fetch(url, _getRequestParams(method, options, parameters, body)) + fetcher(url, _getRequestParams(method, options, parameters, body)) .then((result) => { if (!result.ok) throw result if (options?.noResolveJson) return resolve(result) @@ -65,36 +68,40 @@ async function _handleRequest( } export async function get( + fetcher: Fetch | undefined, url: string, options?: FetchOptions, parameters?: FetchParameters ): Promise { - return _handleRequest('GET', url, options, parameters) + return _handleRequest(fetcher, 'GET', url, options, parameters) } export async function post( + fetcher: Fetch | undefined, url: string, body: object, options?: FetchOptions, parameters?: FetchParameters ): Promise { - return _handleRequest('POST', url, options, parameters, body) + return _handleRequest(fetcher, 'POST', url, options, parameters, body) } export async function put( + fetcher: Fetch | undefined, url: string, body: object, options?: FetchOptions, parameters?: FetchParameters ): Promise { - return _handleRequest('PUT', url, options, parameters, body) + return _handleRequest(fetcher, 'PUT', url, options, parameters, body) } export async function remove( + fetcher: Fetch | undefined, url: string, body: object, options?: FetchOptions, parameters?: FetchParameters ): Promise { - return _handleRequest('DELETE', url, options, parameters, body) + return _handleRequest(fetcher, 'DELETE', url, options, parameters, body) }