Skip to content

Commit

Permalink
feat: allow providing custom fetch implementation (#24)
Browse files Browse the repository at this point in the history
  • Loading branch information
jacobwgillespie committed Nov 8, 2021
1 parent 72c8bf1 commit 6756b13
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 18 deletions.
7 changes: 4 additions & 3 deletions src/SupabaseStorageClient.ts
Original file line number Diff line number Diff line change
@@ -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)
}

/**
Expand All @@ -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)
}
}
26 changes: 20 additions & 6 deletions src/lib/StorageBucketApi.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
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
}

/**
* Retrieves the details of all Storage buckets within an existing product.
*/
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 }
Expand All @@ -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 }
Expand All @@ -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 }
Expand All @@ -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 }
Expand All @@ -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 }
Expand All @@ -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 }
Expand Down
17 changes: 14 additions & 3 deletions src/lib/StorageFileApi.ts
Original file line number Diff line number Diff line change
@@ -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'
Expand All @@ -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
}

/**
Expand Down Expand Up @@ -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 }
Expand Down Expand Up @@ -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 }
Expand All @@ -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,
})
Expand Down Expand Up @@ -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 }
Expand Down Expand Up @@ -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 },
Expand Down
19 changes: 13 additions & 6 deletions src/lib/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import fetch from 'cross-fetch'
import crossFetch from 'cross-fetch'

export type Fetch = typeof fetch

export interface FetchOptions {
headers?: {
Expand Down Expand Up @@ -46,14 +48,15 @@ const _getRequestParams = (
}

async function _handleRequest(
fetcher: Fetch = crossFetch,
method: RequestMethodType,
url: string,
options?: FetchOptions,
parameters?: FetchParameters,
body?: object
): Promise<any> {
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)
Expand All @@ -65,36 +68,40 @@ async function _handleRequest(
}

export async function get(
fetcher: Fetch | undefined,
url: string,
options?: FetchOptions,
parameters?: FetchParameters
): Promise<any> {
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<any> {
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<any> {
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<any> {
return _handleRequest('DELETE', url, options, parameters, body)
return _handleRequest(fetcher, 'DELETE', url, options, parameters, body)
}

0 comments on commit 6756b13

Please sign in to comment.