Skip to content

Request to dynamic import @supabase/node-fetch #1303

@liyachun01

Description

@liyachun01

Chore

Describe the chore

Request update the static import of @supabase/node-fetch in src/lib/fetch.ts:

import nodeFetch, { Headers as NodeFetchHeaders } from '@supabase/node-fetch'
type Fetch = typeof fetch
export const resolveFetch = (customFetch?: Fetch): Fetch => {
let _fetch: Fetch
if (customFetch) {
_fetch = customFetch
} else if (typeof fetch === 'undefined') {
_fetch = nodeFetch as unknown as Fetch
} else {
_fetch = fetch
}
return (...args: Parameters<Fetch>) => _fetch(...args)
}

export const resolveHeadersConstructor = () => {
if (typeof Headers === 'undefined') {
return NodeFetchHeaders
}
return Headers
}

Use dynamic import('@supabase/node-fetch') to avoid possible Cannot read property 'bind' of undefined error.

Additional context

Related to this issue supabase/postgrest-js#574.

Using @supabase/supabase-js, a user is able to provide custom fetch by providing a global.fetch option. However, with @supabase/node-fetch statically imported, a Cannot read property 'bind' of undefined error may throw at runtime.

TypeError: Cannot read property 'bind' of undefined
    at path/to/node_modules/@supabase/node-fetch/browser.js

The error is thrown when the runtime environment does not have native fetch on globalObject at all.

https://github.com/supabase/node-fetch/blob/bd8f50a4ae647e56cda296b8301d7dff01d4a87b/browser.js#L18.

/* @supabase/node-fetch/browser.js#L18 */
export default globalObject.fetch.bind(globalObject);

In some other @supabase/ packages like @supabase/auth-js, the fetch is resolved using a resolveFetch function:

https://github.com/supabase/auth-js/blob/8af88b6f4e41872b73e84c40f71793dab6c62126/src/lib/helpers.ts#L93-L104.

/* @supabase/auth-js/src/lib/helpers.ts#L93-L104. */
export const resolveFetch = (customFetch?: Fetch): Fetch => {
  let _fetch: Fetch
  if (customFetch) {
    _fetch = customFetch
  } else if (typeof fetch === 'undefined') {
    _fetch = (...args) =>
      import('@supabase/node-fetch' as any).then(({ default: fetch }) => fetch(...args))
  } else {
    _fetch = fetch
  }
  return (...args) => _fetch(...args)
}

This way, the node-fetch import is safe. We could also implement this for nodeFetch and Headers imported here.

Activity

self-assigned this
on Jul 24, 2025
mandarini

mandarini commented on Jul 25, 2025

@mandarini
Contributor

Hi @liyachun01 ! Thank you very much for your detailed report, and enhancement request. As I have replied in detail in your PR, please bear with us until we officially drop support for Node 18. After that, @supabase/node-fetch dependency will be removed, and all the issues are going to be fixed! :D

I do hope my decision makes sense to everyone.

Again, thanks for being part of our community!

added theissue type on Jul 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or requestjavascriptPull requests that update javascript codeplanned

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    Participants

    @mandarini@liyachun01

    Issue actions

      Request to dynamic import `@supabase/node-fetch` · Issue #1303 · supabase/supabase-js