Skip to content
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
2 changes: 2 additions & 0 deletions packages/nuxt/global.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Global compile-time constants
declare var __TEST__: boolean
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any way to get rid of this? I don't think we should need this

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>
async function useFancyCounter() {
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>
32 changes: 30 additions & 2 deletions packages/nuxt/src/runtime/composables.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,33 @@
import { useNuxtApp } from '#app'
import type { Pinia } from 'pinia'
import {
defineStore as _defineStore,
type Pinia,
type StoreGeneric,
} from 'pinia'
export * from 'pinia'

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

export const defineStore: typeof _defineStore =
process.env.NODE_ENV === 'production' && !__TEST__
? _defineStore
: (((
...args: Parameters<typeof _defineStore>
): ReturnType<typeof _defineStore> => {
if (!import.meta.server) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition can be probably be moved up so we simply return _defineStore too

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
}) as typeof _defineStore)
6 changes: 6 additions & 0 deletions packages/nuxt/test/nuxt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,10 @@ describe('Nuxt', async () => {
it('can auto import from layers', async () => {
expect(await $fetch('/')).toContain('Layer store: 0')
})

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'
)
})
})
1 change: 1 addition & 0 deletions packages/nuxt/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"extends": "./playground/.nuxt/tsconfig.json",
"include": [
"./shims.d.ts",
"./global.d.ts",
// missing in the playground
"./src"
]
Expand Down