diff --git a/packages/docs/ssr/nuxt.md b/packages/docs/ssr/nuxt.md index 12c5454e74..58a47f9aea 100644 --- a/packages/docs/ssr/nuxt.md +++ b/packages/docs/ssr/nuxt.md @@ -85,7 +85,7 @@ By default `@pinia/nuxt` exposes a few auto imports: - `storeToRefs()` when you need to extract individual refs from a store - `acceptHMRUpdate()` for [hot module replacement](../cookbook/hot-module-replacement.md) -It also automatically imports **all stores** defined within your `stores` folder. It doesn't lookup for nested stores though. You can customize this behavior by setting the `storesDirs` option: +It also automatically imports **all stores** defined within your `stores` folder in the main `srcDir` and all layers. It doesn't lookup nested stores though. You can customize this behavior by setting the `storesDirs` option: ```ts // nuxt.config.ts @@ -98,8 +98,39 @@ export default defineNuxtConfig({ }) ``` +**Note**: The folders are relative to the root of your project. If you change the `srcDir` option, you need to adjust the paths accordingly. + +#### Merging Pinia Options Across Layers + +Nuxt merges Pinia options from all layers, but defining the `storesDirs` option, such as `['./stores/**', './custom-folder/**']`, in your main `nuxt.config.ts` will only be resolved relative to the main `srcDir`. To ensure that your stores are correctly auto imported in layers, you need to define the `storesDirs` option for each layer individually. + +#### Example: Defining Stores in a Custom Layer + +To define store directories for a specific layer, use the following approach: + +```ts +import { fileURLToPath } from 'node:url' +import { defineNuxtConfig } from 'nuxt/config' +import { dirname, join } from 'path' + +const currentDir = dirname(fileURLToPath(import.meta.url)) + +export default defineNuxtConfig({ + pinia: { + storesDirs: [join(currentDir, './stores/**')], + }, +}) +``` + +In this example: + +- `currentDir` represents the directory of the current layer. +- `storesDirs` is set to point to the `stores` folder relative to the current layer's directory. + Note the folders are relative to the root of your project. If you change the `srcDir` option, you need to adapt the paths accordingly. +For more detailed information on working with layers and relative paths in Nuxt, refer to the [Nuxt Documentation on Layers](https://nuxt.com/docs/guide/going-further/layers#relative-paths-and-aliases). + ## Nuxt 2 without bridge Pinia supports Nuxt 2 until `@pinia/nuxt` v0.2.1. Make sure to also install [`@nuxtjs/composition-api`](https://composition-api.nuxtjs.org/) alongside `pinia`: diff --git a/packages/nuxt/__tests__/nuxt.spec.ts b/packages/nuxt/__tests__/nuxt.spec.ts index 51f7cf5a83..fcd398cc25 100644 --- a/packages/nuxt/__tests__/nuxt.spec.ts +++ b/packages/nuxt/__tests__/nuxt.spec.ts @@ -32,5 +32,6 @@ describe('works with nuxt', async () => { it('works on ssr', async () => { const html = await $fetch('/') expect(html).toContain('Count: 101') + expect(html).toContain('Layer: store state') }) }) diff --git a/packages/nuxt/example-layer/nuxt.config.ts b/packages/nuxt/example-layer/nuxt.config.ts new file mode 100644 index 0000000000..aa124e7bd1 --- /dev/null +++ b/packages/nuxt/example-layer/nuxt.config.ts @@ -0,0 +1,11 @@ +import { fileURLToPath } from 'node:url' +import { defineNuxtConfig } from 'nuxt/config' +import { dirname, join } from 'path' + +const currentDir = dirname(fileURLToPath(import.meta.url)) + +export default defineNuxtConfig({ + pinia: { + storesDirs: [join(currentDir, './stores/**')], + }, +}) diff --git a/packages/nuxt/example-layer/stores/layerStore.ts b/packages/nuxt/example-layer/stores/layerStore.ts new file mode 100644 index 0000000000..b621a217fd --- /dev/null +++ b/packages/nuxt/example-layer/stores/layerStore.ts @@ -0,0 +1,9 @@ +import { ref } from 'vue' + +export const useLayerStore = defineStore('layerStore', () => { + console.log('I was defined within a stores directory in example-layer') + const state = ref('store state') + return { + state, + } +}) diff --git a/packages/nuxt/playground/app.vue b/packages/nuxt/playground/app.vue index 450e65a2d3..8696d72401 100644 --- a/packages/nuxt/playground/app.vue +++ b/packages/nuxt/playground/app.vue @@ -6,6 +6,7 @@ const counter = useCounter() useTestStore() useSomeStoreStore() +const layerStore = useLayerStore() // await useAsyncData('counter', () => counter.asyncIncrement().then(() => true)) if (import.meta.server) { @@ -17,5 +18,7 @@ if (import.meta.server) {

Count: {{ counter.$state.count }}

+ +

Layer: {{ layerStore.state }}

diff --git a/packages/nuxt/playground/nuxt.config.ts b/packages/nuxt/playground/nuxt.config.ts index 973b5d95a3..069179ddcb 100644 --- a/packages/nuxt/playground/nuxt.config.ts +++ b/packages/nuxt/playground/nuxt.config.ts @@ -8,6 +8,8 @@ export default defineNuxtConfig({ }, modules: [piniaModule], + extends: ['../example-layer'], + pinia: { storesDirs: ['./stores/**', './domain/*/stores'], }, diff --git a/packages/nuxt/src/module.ts b/packages/nuxt/src/module.ts index b528bad4f6..356f663754 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -91,9 +91,12 @@ const module: NuxtModule = defineNuxtModule({ { from: composables, name: 'storeToRefs' }, ]) - if (!options.storesDirs) { - // resolve it against the src dir which is the root by default - options.storesDirs = [resolver.resolve(nuxt.options.srcDir, 'stores')] + if (options.storesDirs == null) { + // Add stores directory for each layer, including the main src dir + options.storesDirs = [] + for (const layer of nuxt.options._layers) { + options.storesDirs.push(resolver.resolve(layer.config.srcDir, 'stores')) + } } if (options.storesDirs) {