pocketbase / js-sdk

PocketBase JavaScript SDK
https://www.npmjs.com/package/pocketbase
MIT License
2.06k stars 122 forks source link

How do I use the authStore asynchronously? Undefined `isValid` when using with Nuxt 3 #256

Closed fayazara closed 10 months ago

fayazara commented 10 months ago

I have written a middleware in Nuxt 3 as below.

import { usePocketBaseClient } from '@/composables/pocketBaseClient'
export default defineNuxtRouteMiddleware(() => {
  const pocketbase = usePocketBaseClient();
  const isUserLoggedIn = pocketbase?.authStore.isValid;
  console.log('isUserLoggedIn', isUserLoggedIn)
  if (!isUserLoggedIn) {
    return navigateTo('/auth/login')
  }
})

The pocketbase client is initiated correctly, but the isValid is always false, I can access the user data when I use it with a page. Is there a way to wait till I get the pocketbase user to check if they're valid in this middleware?

ganigeorgiev commented 10 months ago

I'm not sure that I understand what do you mean by asynchronously.

What is usePocketBaseClient()? Where and when the above code is being executed (eg. is it in the browser, server or both)?

If the above is for SSR, you can check some of the examples in https://github.com/pocketbase/js-sdk#ssr-integration.

I'll close the issue for now as I don't think there is an actionable item or something related to the JS SDK, but feel free to provide more details about your use case and I'll have a look.

fayazara commented 10 months ago

@ganigeorgiev Sorry about not being clear.

The usePocketbaseClient() is a nuxt composable running in the client

import PocketBase from 'pocketbase';
const pb = new PocketBase('http://127.0.0.1:8090');

export const usePocketBaseClient = () => {
  return pb as PocketBase;
}

Let me try to reproduce this and share a link.

ganigeorgiev commented 10 months ago

I don't think your issue is JS SDK related.

By default pb.authStore uses LocalStorage and all its operations are synchronous.

ganigeorgiev commented 10 months ago

I'm not very familiar with Nuxt, but are you even sure that the pocketbase variable in your example is being set to the JS SDK instance? If Yes, then why do you need the ? optional access?

fayazara commented 10 months ago

Yes, but I think i found out the issue, its running on the server, not on client Screenshot 04-11 at 17

fayazara commented 10 months ago

Basically I was trying to create a nuxt module for pocketbase similar to nuxt/supabase https://supabase.nuxtjs.org/

Let me see if there's any other way to do this.

ganigeorgiev commented 10 months ago

But I don't think you need a dedicated module, especially if your code is executed on the client-side (aka. browser).

Also why do the JS SDK instance actually needs to be composable in the first place?

In your example you can directly return export default pb, and then import it in your code without the need of usePocketBaseClient (eg. import pb from "/src/yourclient.js").

Having a single global PocketBase SDK instance is safe when executed in the browser. For an SSR example see https://github.com/pocketbase/js-sdk#ssr-integration.

fayazara commented 10 months ago

Yes, I just created a composable so I could reuse it in other pages and components etc.

I've updated my auth middleware, which seems to be working now.

import { usePocketBaseClient } from '@/composables/pocketBaseClient'
export default defineNuxtRouteMiddleware(async () => {
  if (process.server) return;
  const pocketbase = usePocketBaseClient();
  const isUserLoggedIn = await pocketbase?.authStore.isValid;
  if (!isUserLoggedIn) {
    return navigateTo('/auth/login')
  }
})

Might not be the correct way since the page is shown first then redirected back to the login page. Just testing what works best, will figure out a better way to handle this since, or just go the SSR way you mentioned in the docs link above.

Thank you for he help!

fayazara commented 10 months ago

Here's the test project I made to test out pocketbase with the composables I mentioned above.

https://github.com/fayazara/pocketbase-nuxt

ganigeorgiev commented 10 months ago

As mentioned earlier in https://github.com/pocketbase/js-sdk/issues/256#issuecomment-1793420266, returning a function in https://github.com/fayazara/pocketbase-nuxt/blob/main/composables/pocketBaseClient.ts#L5C4-L5C4 is not really necessary as it doesn't really do anything.

You can directly return export default pb and then you can directly import it in your client-side code like:

import pb from "/path/to/client.js"

...

const records = await pb.collection("example").getList(1, 20)