Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: throw when a store is used outside of a Nuxt-aware context. #2857

Open
wants to merge 3 commits into
base: v2
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions packages/nuxt/playground/pages/usage-after-await.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<script lang="ts" setup>
const useFancyCounter = async () => {
await new Promise((resolve) => setTimeout(resolve, 0))

// ❌ bad usage: the use of a store after an await could lead to using the wrong pinia instance.
return useCounter()
}

const event = useRequestEvent()
useNuxtApp().hook('vue:error', (error) => {
if (event) {
setResponseStatus(event, 500, String(error))
}
})

const counter = await useFancyCounter()
</script>

<template>
<div>
<p>Count: {{ counter.$state.count }}</p>
<button @click="counter.increment()">+</button>
</div>
</template>
25 changes: 24 additions & 1 deletion packages/nuxt/src/runtime/composables.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,27 @@
import { useNuxtApp } from '#app'
import {
defineStore as _defineStore,
type Pinia,
type StoreGeneric,
} from 'pinia'
export * from 'pinia'

export const usePinia = () => useNuxtApp().$pinia
export const usePinia = () => useNuxtApp().$pinia as Pinia | undefined

export const defineStore: typeof _defineStore = (
...args: [idOrOptions: any, setup?: any, setupOptions?: any]
) => {
if (!import.meta.server) {
return _defineStore(...args)
}

const originalUseStore = _defineStore(...args)
function useStore(pinia?: Pinia | null, hot?: StoreGeneric): StoreGeneric {
return originalUseStore(pinia || usePinia(), hot)
}

useStore.$id = originalUseStore.$id
useStore._pinia = originalUseStore._pinia

return useStore
}
6 changes: 6 additions & 0 deletions packages/nuxt/test/nuxt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,10 @@ describe('works with nuxt', async () => {
expect(html).not.toContain('I should not be serialized or hydrated')
expect(html).toContain('skipHydrate-wrapped state is correct')
})

it('throws an error server-side when the nuxt context is not available', async () => {
await expect($fetch('/usage-after-await')).rejects.toThrowError(
'[nuxt] instance unavailable'
)
})
})