Skip to content

feat: allow providing custom fetch implementation #297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ Then you can use it from a global `supabase` variable:
</script>
```

### Custom `fetch` implementation

`supabase-js` uses the [`cross-fetch`](https://www.npmjs.com/package/cross-fetch) library to make HTTP requests, but an alternative `fetch` implementation can be provided as an option. This is most useful in environments where `cross-fetch` is not compatible, for instance Cloudflare Workers:

```js
import { createClient } from '@supabase/supabase-js'

// Provide a custom `fetch` implementation as an option
const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key', { fetch: fetch })
```

## Sponsors

We are building the features of Firebase using enterprise-grade, open source products. We support existing communities wherever possible, and if the products don’t exist we build them and open source them ourselves. Thanks to these sponsors who are making the OSS ecosystem better for everyone.
Expand Down
11 changes: 9 additions & 2 deletions src/SupabaseClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { DEFAULT_HEADERS } from './lib/constants'
import { stripTrailingSlash } from './lib/helpers'
import { SupabaseClientOptions } from './lib/types'
import { Fetch, SupabaseClientOptions } from './lib/types'
import { SupabaseAuthClient } from './lib/SupabaseAuthClient'
import { SupabaseQueryBuilder } from './lib/SupabaseQueryBuilder'
import { SupabaseStorageClient } from '@supabase/storage-js'
Expand Down Expand Up @@ -32,6 +32,7 @@ export default class SupabaseClient {
protected authUrl: string
protected storageUrl: string
protected realtime: RealtimeClient
protected fetch?: Fetch

/**
* Create a new client for use in the browser.
Expand All @@ -43,6 +44,7 @@ export default class SupabaseClient {
* @param options.detectSessionInUrl Set to "true" if you want to automatically detects OAuth grants in the URL and signs in the user.
* @param options.headers Any additional headers to send with each network request.
* @param options.realtime Options passed along to realtime-js constructor.
* @param options.fetch A custom fetch implementation.
*/
constructor(
protected supabaseUrl: string,
Expand All @@ -64,6 +66,8 @@ export default class SupabaseClient {
this.auth = this._initSupabaseAuthClient(settings)
this.realtime = this._initRealtimeClient(settings.realtime)

this.fetch = settings.fetch

// In the future we might allow the user to pass in a logger to receive these events.
// this.realtime.onOpen(() => console.log('OPEN'))
// this.realtime.onClose(() => console.log('CLOSED'))
Expand All @@ -74,7 +78,7 @@ export default class SupabaseClient {
* Supabase Storage allows you to manage user-generated content, such as photos or videos.
*/
get storage() {
return new SupabaseStorageClient(this.storageUrl, this._getAuthHeaders())
return new SupabaseStorageClient(this.storageUrl, this._getAuthHeaders(), this.fetch)
}

/**
Expand All @@ -89,6 +93,7 @@ export default class SupabaseClient {
schema: this.schema,
realtime: this.realtime,
table,
fetch: this.fetch,
})
}

Expand Down Expand Up @@ -166,6 +171,7 @@ export default class SupabaseClient {
persistSession,
detectSessionInUrl,
localStorage,
fetch: this.fetch,
})
}

Expand All @@ -180,6 +186,7 @@ export default class SupabaseClient {
return new PostgrestClient(this.restUrl, {
headers: this._getAuthHeaders(),
schema: this.schema,
fetch: this.fetch,
})
}

Expand Down
6 changes: 4 additions & 2 deletions src/lib/SupabaseQueryBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PostgrestQueryBuilder } from '@supabase/postgrest-js'
import { SupabaseRealtimeClient } from './SupabaseRealtimeClient'
import { RealtimeClient } from '@supabase/realtime-js'
import { SupabaseEventTypes, SupabaseRealtimePayload } from './types'
import { Fetch, SupabaseEventTypes, SupabaseRealtimePayload } from './types'

export class SupabaseQueryBuilder<T> extends PostgrestQueryBuilder<T> {
private _subscription: SupabaseRealtimeClient
Expand All @@ -14,14 +14,16 @@ export class SupabaseQueryBuilder<T> extends PostgrestQueryBuilder<T> {
schema,
realtime,
table,
fetch,
}: {
headers?: { [key: string]: string }
schema: string
realtime: RealtimeClient
table: string
fetch?: Fetch
}
) {
super(url, { headers, schema })
super(url, { headers, schema, fetch })

this._subscription = new SupabaseRealtimeClient(realtime, headers, schema, table)
this._realtime = realtime
Expand Down
7 changes: 7 additions & 0 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { GoTrueClient } from '@supabase/gotrue-js'
import { RealtimeClientOptions } from '@supabase/realtime-js'

export type Fetch = typeof fetch

type GoTrueClientOptions = ConstructorParameters<typeof GoTrueClient>[0]

export interface SupabaseAuthClientOptions extends GoTrueClientOptions {}
Expand Down Expand Up @@ -35,6 +37,11 @@ export type SupabaseClientOptions = {
* Options passed to the realtime-js instance
*/
realtime?: RealtimeClientOptions

/**
* A custom `fetch` implementation.
*/
fetch?: Fetch
}

export type SupabaseRealtimePayload<T> = {
Expand Down