diff --git a/packages/docs/ssr/nuxt.md b/packages/docs/ssr/nuxt.md index 592ab0fca3..a4174a318c 100644 --- a/packages/docs/ssr/nuxt.md +++ b/packages/docs/ssr/nuxt.md @@ -87,7 +87,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 @@ -100,8 +100,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/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/nuxt.config.ts b/packages/nuxt/playground/nuxt.config.ts index b2c0a251be..52966fbd2f 100644 --- a/packages/nuxt/playground/nuxt.config.ts +++ b/packages/nuxt/playground/nuxt.config.ts @@ -13,6 +13,7 @@ export default defineNuxtConfig({ telemetry: { enabled: false, }, + extends: ['../example-layer'], pinia: { storesDirs: ['./stores/**', './domain/*/stores'], diff --git a/packages/nuxt/playground/pages/index.vue b/packages/nuxt/playground/pages/index.vue index 450e65a2d3..8696d72401 100644 --- a/packages/nuxt/playground/pages/index.vue +++ b/packages/nuxt/playground/pages/index.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/src/module.ts b/packages/nuxt/src/module.ts index f81f9779ef..b904a988a0 100644 --- a/packages/nuxt/src/module.ts +++ b/packages/nuxt/src/module.ts @@ -67,8 +67,12 @@ const module: NuxtModule = defineNuxtModule({ ]) if (!options.storesDirs) { - // resolve it against the src dir which is the root by default - options.storesDirs = [resolve(nuxt.options.srcDir, 'stores')] + // Add stores directory for each layer, including the main src dir + options.storesDirs = [] + for (const layer of nuxt.options._layers) { + console.log(layer) + options.storesDirs.push(resolve(layer.config.srcDir, 'stores')) + } } if (options.storesDirs) { diff --git a/packages/nuxt/test/nuxt.spec.ts b/packages/nuxt/test/nuxt.spec.ts index 8bcbfccc05..91a49c1f23 100644 --- a/packages/nuxt/test/nuxt.spec.ts +++ b/packages/nuxt/test/nuxt.spec.ts @@ -26,6 +26,7 @@ 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') }) it('drops state that is marked with skipHydrate', async () => {