Skip to content

Issue with Route middleware : vue-query hooks can only be used inside setup() function #72

Open
@armenr

Description

@armenr

Environment

❯ node -v
v20.11.1

"@hebilicious/vue-query-nuxt": "^0.3.0",

Reproduction

composables/useQueryWrapper.ts

import { experimental_createPersister } from '@tanstack/query-persist-client-core'
import type { GetUserQuery } from '~/API'

export default async function useQueryWrapper() {
  const queryClient = useQueryClient()

  const { isLoading, isError, data, error } = useQuery({
    queryKey: ['getUser'],
    queryFn: async () => {
      const { data } = await useLeanGraphql({
        variables: { id: '9e98ae52-1f4b-47ad-9661-afb2c7efc653' },
        graphqlAction: getUser,
        fields: {
          name: 'getUser',
          fields: getUserSharedFields(true) as Field<GetUserQuery>['fields'],
        },
      })
      return data
      // console.log({ data })
    },
    persister: process.client ? experimental_createPersister({ storage: window.localStorage }) : undefined,
  })

  console.log({
    queryClient,
    isLoading,
    isError,
    data,
    error,
  })

  return { queryClient, isLoading, isError, data, error }
}

plugins/03.auth-redirect.ts

import { Amplify } from 'aws-amplify'
import config from '~/amplifyconfiguration.json'

const unprotectedRoutes = [
  'index',
  'signin',
  'signup',
  'recovery',
  'cause-areas',
  'demo-amplify',
  'cookie-policy',
  'privacy-policy',
  'recovery-confirm',
  'terms-of-service',
]

export default defineNuxtPlugin({
  name: 'AmplifyAuthRedirect',
  enforce: 'pre',
  setup() {
    addRouteMiddleware(
      'AmplifyAuthMiddleware',
      defineNuxtRouteMiddleware(async (to) => {
        try {
          // if we're running on the client, initialize Amplify
          if (process.client)
            Amplify.configure(config, { ssr: useRuntimeConfig().public.ssrEnabled })

          // does the user have a valid session?
          // !! deleted users still possess valid tokens for 1 hour (Cognito "feature")
          const { userId } = await useAuth().getCurrentUser()

          // if the user has a valid session, fetch their user data
          if (userId) {

            // !! testing simple getUser with Id query via vue-query
            try {
              const TESTINGTHIS = await useQueryWrapper()          // 👈 Doesn't work!
              useLogger().info('useQueryWrapper', TESTINGTHIS)
            }
            catch (e) {
              useLogger().error('useQueryWrapper error', e)
            }

            // existing pinia-based implementation
            if (useAuthStore().isLoggedIn === false) {
              // if not, fetch it from the API
              await useAuthStore().fetchCurrentUser(userId)
            }

            if (to.name === 'signin')
              return navigateTo('/feed')
          }
        }
        catch (e) {
          if (e instanceof Error && 'code' in e) {
            if (e.code === 'NotAuthorizedException') {
              useLogger().error('NotAuthorizedException')
              return
            }
          }

          if (!unprotectedRoutes.includes(to.name))
            return navigateTo('/signin')
        }
      }),
      { global: true },
    )
  },
})

Describe the bug

Hi! Thanks for all your great work on this plugin :)

I'm struggling with just one specific implementation.

  • I'm able to call useQueryWrapper in the setup block of one of my pages.
  • I'm able to call useQueryWrapper in my Pinia store (I <3 Pinia, but I'm tryna replace it with vue-query, so I'm really only calling useQueryWrapper from inside pinia as a test...)

In my my authStore.ts (pinia), I can successfully do this:

  useQueryWrapper().then((data) => {
    console.log("Hai antfu, posva, and herbilicious! ", data)
  })
  • I'm unable to call useQueryWrapper from inside the global middleware I create in the plugin I've shared above.

If I could, I'd implement that whole plugin differently, but this is the specific way that the AWS Amplify documentation insists that we implement a routeGuard with SSR + Nuxt3 + Amplify.

I did do lots of digging and searching, and I found this: TanStack/query#5533

I don't understand how we're not getting any context from inside a plugin...I'm just confused (and probably a bit of a newb).

Based on that discussion, I even tried to do useNuxtApp().runWithContext(async () => await useQueryWrapper()) from inside the 03.auth-redirect.ts plugin.

I'm totally stuck. Would you happen to have any suggestion or idea as to how I can get this working. I'm sure that I'm missing something stupid/ovious, but it's 4AM here and I'm already starting to lose it 😂

Thank you for any help or direction you may be able to provide! 🙌🏼

Additional context

No response

Logs

03.auth-redirect.ts:45 [ERROR] 24:03.34 DEV - useQueryWrapper error Error: vue-query hooks can only be used inside setup() function or functions that support injection context.
    at useQueryClient (useQueryClient.ts:9:11)
    at useQueryWrapper (useQueryWrapper.ts:5:23)
    at wrappred (function-metrics-helpers.mjs:42:17)
    at 03.auth-redirect.ts:41:62
    at executeAsync (index.mjs:111:19)
    at 03.auth-redirect.ts:41:51
    at async router.js:138:39

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions