supabase / supabase-js

An isomorphic Javascript client for Supabase. Query your Supabase database, subscribe to realtime events, upload and download files, browse typescript examples, invoke postgres functions via rpc, invoke supabase edge functions, query pgvector.
https://supabase.com
MIT License
2.86k stars 220 forks source link

SVELTEKIT: Streaming queries causes error. #1028

Closed themixednuts closed 2 weeks ago

themixednuts commented 3 weeks ago

Bug report

Describe the bug

When trying to navigate after the initial load (which works just fine), you get an Error thing.catch is not a function on preload-data links.

To Reproduce

Steps to reproduce the behavior, please provide code snippets or a repository:

export const load: PageServerLoad = async ({ locals: { safeGetSession, supabase }, params: { id } }) => {
    const { session } = await safeGetSession()

    if (!session?.user.id) {
        throw redirect(303, '/login')
    }

       const profile = supabase.from('profiles').select().eq('id', id)

      // this is not part of the issue but show cases how SvelteKit wants you to handle errors on streams, but can't do this since there is no catch method. throwOnError() doesn't provide it with a catch() method either. 

       profile.catch(e => console.log(e))

    return {
        profile
    }
}

Expected behavior

There should be a catch method

System information

encima commented 3 weeks ago

Hi @themixednuts I am not super familiar with Sveltekit so you might need to educate me a bit!

By stream, you mean streamed promise? What stops you from streaming the promise and catching on Svelte's side with {:catch}? I might be wrong but I thought that was the recommended practice

themixednuts commented 3 weeks ago

Hi @themixednuts I am not super familiar with Sveltekit so you might need to educate me a bit!

By stream, you mean streamed promise? What stops you from streaming the promise and catching on Svelte's side with {:catch}? I might be wrong but I thought that was the recommended practice

All good! I think the docs will explain the best here https://kit.svelte.dev/docs/load#streaming-with-promises.

In the code side, sveltekit checks for a .catch() on the promise, and since there is none it throws an error. So {:catch} wouldn't even be possible even so.

encima commented 3 weeks ago

Thanks for the pointer, so it looks like the call you make returns a PromiseLike from the PostgrestBuilder object that does not implement catch (see here)

What you could do is map the throwOnError to catch for Svelte to pick up but possibly others have different ideas?

soedirgo commented 2 weeks ago

Hey @themixednuts, you can also do this by wrapping the call in an async function:

export const load: PageServerLoad = async ({ locals: { safeGetSession, supabase }, params: { id } }) => {
    const { session } = await safeGetSession()

    if (!session?.user.id) {
        throw redirect(303, '/login')
    }

       const profile = (async () => await supabase.from('profiles').select().eq('id', id))()

      // this is not part of the issue but show cases how SvelteKit wants you to handle errors on streams, but can't do this since there is no catch method. throwOnError() doesn't provide it with a catch() method either. 

       profile.catch(e => console.log(e))

    return {
        profile
    }
}