qwik icon indicating copy to clipboard operation
qwik copied to clipboard

[📖] Supabase Integration does not work.

Open y471n opened this issue 2 years ago • 5 comments

Suggestion

When trying to incorporate the Supabase authentication using the code suggested in the docs:

export const useDBTest = routeLoader$(async (requestEv) => {
  const supabaseClient = createServerClient(
    import.meta.env.PUBLIC_SUPABASE_URL,
    import.meta.env.PUBLIC_SUPABASE_ANON_KEY,
    requestEv
  );
  const { data } = await supabaseClient.from('test').select('*')
  return { data };
});

I get the following TS error:

Argument of type 'RequestEventLoader<QwikCityPlatform>' is not assignable to parameter of type 'RequestEvent<QwikCityPlatform>'.
  Type 'RequestEventLoader<QwikCityPlatform>' is missing the following properties from type 'RequestEvent<QwikCityPlatform>': headersSent, exited, getWritableStream, nextts(2345)

The requestEv does not have all the attributes needed for the supabase server-client.

y471n avatar Apr 29 '23 00:04 y471n

where is createServerClient coming from?

manucorporat avatar Apr 29 '23 09:04 manucorporat

This is from qwik supabase auth lib. import { createServerClient } from 'supabase-auth-helpers-qwik';

https://qwik.builder.io/docs/integrations/supabase/

y471n avatar Apr 29 '23 10:04 y471n

@y471n Please note that if you are using routeLoader$ outside of the layout.tsx or index.tsx files located in the routes folder, it may not function as intended. Have you checked whether you are using routeLoader$ in any of these files?

diecodev avatar May 09 '23 16:05 diecodev

I'm using it inside index.tsx itself. The issue was with createServerClient. I used createClient from Supabase lib itself as a workaround to make it work.

y471n avatar May 10 '23 03:05 y471n

@y471n then, clear the vite cache for dev mode. Go to package.json file and find the start script. Then add --force before the --open flag.

diecodev avatar May 10 '23 05:05 diecodev

Hi @y471n 👋 did @diecodev 's reply helped with this issue? thanks for helping out @diecodev 🙏

zanettin avatar May 18 '23 20:05 zanettin

Have you figured how to set it up ? I am trying to use supabase-cli but I kinda get stuck because we don't have the same auth-helpers as other framework... Is this because Qwik uses serverClient only ?

paveilleux avatar May 22 '23 15:05 paveilleux

@PaVeilleux Can you please show any repository where you have problems with the package?

diecodev avatar May 22 '23 16:05 diecodev

Well I am quite confused on the process to authenticate user server-side. From what I understand, the flow would be somewhat similar to this :

  1. Create client from "@supabase/supabase-js"
  2. Wrap the app with a context provider (root layout)
  3. Use createServerClient from "supabase-auth-helpers-qwik" to store cookies
  4. Use createBrowserClient from "supabase-auth-helpers-qwik" for components

Does wraping the app in the layout acts as createMiddlewareSupabaseClient from @supabase/auth-helpers-nextjs ? Am I supposed to use the createServerClient or the client from @supabase/supabase-js for the context?

paveilleux avatar May 22 '23 17:05 paveilleux

To use supabase with qwik you don't need to create a context provider or start the supabase client from the @supabase/supabase-js package, you just need to follow the example in the qwik documentation. Previously there was a problem with supabase.auth but it has been fixed recently. In case you don't understand how to start or create the supabase client, here is a step by step guide:

Guide to use Supabase with Qwik:

  1. First, install the packages:

I recommend you to install the packages as devDependencies and the exact version (to avoid versioning problems in the future).

npm install --exact --save-dev @supabase/supabase-js supabase-auth-helpers-qwik
  1. Create a routeLoader$ (this utility is provided by qwik-city) or if you want to use the supabaseClient from a Form (qwik-city component) you can use a routeAction$ or globalAction$ (both utilities are also provided by qwik-city).

In this example, I'm using a globalAction$ to handle a login form, so I can use the globalAction$ from the loginForm.tsx file.

//loginForm.tsx

import { Form, globalAction$, zod$, z } from "@builder.io/qwik-city";

export const useLoginForm = globalAction$(
  async (user, event) => {
    const supabaseUrl = event.env.get("SUPABASE_URL")!;
    const supabaseKey = event.env.get("SUPABASE_KEY")!;

    const supabase = createServerClient(supabaseUrl, supabaseKey, event);

    const { data, error } = await supabase.auth.signInWithPassword({
      email: user.email,
      password: user.password,
    });

    return {
      success: true,
      data: data,
    };
  },
  zod$({
    email: z.string().email("Please enter a valid email."),
    password: z
      .string()
      .min(8, "Password must be at least 8 characters long.")
      .max(20, "The password must be less than 20 characters long."),
  })
);
  1. Now, use the globalAction$ (or the routeLoader$/routeAction$) in whatever file you need to use it in.
// loginForm.tsx

export const LoginForm = component$(() => {
  const action = useLoginForm();

  if (action.value?.success) {
      location.reload();
   }

  return (
    <>
      <h1 class="my-10 text-center text-2xl font-bold">
        Please Sign in to continue
      </h1>
      <Form
        action={action}
        class="mx-auto mt-20 flex max-w-md flex-col items-stretch gap-6 p-4"
      >
        <input
          type="email"
          placeholder="[email protected]"
          name="email"
          class="rounded-md border border-gray-300 px-3 py-1 outline-none transition-colors focus-within:border-black"
        />
        <input
          type="password"
          placeholder="********"
          name="password"
          minLength={8}
          maxLength={20}
          class="rounded-md border border-gray-300 px-3 py-1 outline-none transition-colors focus-within:border-black"
        />
        <button
          type="submit"
          class="rounded-md bg-black px-3 py-1 font-medium text-white"
        >
          Ingresar
        </button>
      </Form>
    </>
  );
});

diecodev avatar May 22 '23 18:05 diecodev

@zanettin I think we can close this issue in order to do not have a backlog of issues that may already be resolved.

diecodev avatar Jun 26 '23 13:06 diecodev

hi @diecodev 👋 sure. feel free to reopen when needed 🙏

zanettin avatar Jun 26 '23 17:06 zanettin