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

Auto Register stores dir in all layers #2757

Open
wants to merge 2 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
33 changes: 32 additions & 1 deletion packages/docs/ssr/nuxt.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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`:
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt/__tests__/nuxt.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
})
11 changes: 11 additions & 0 deletions packages/nuxt/example-layer/nuxt.config.ts
Original file line number Diff line number Diff line change
@@ -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/**')],
},
})
9 changes: 9 additions & 0 deletions packages/nuxt/example-layer/stores/layerStore.ts
Original file line number Diff line number Diff line change
@@ -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,
}
})
3 changes: 3 additions & 0 deletions packages/nuxt/playground/app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const counter = useCounter()
useTestStore()
useSomeStoreStore()

const layerStore = useLayerStore()

Choose a reason for hiding this comment

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

I think we don't need to change the playground code. We can treat the current playground as a layer. Refer to #2828.
What do you think ?@posva

Copy link
Member

Choose a reason for hiding this comment

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

Why not. I will need to take a proper look next time

// await useAsyncData('counter', () => counter.asyncIncrement().then(() => true))

if (import.meta.server) {
Expand All @@ -17,5 +18,7 @@ if (import.meta.server) {
<div>
<p>Count: {{ counter.$state.count }}</p>
<button @click="counter.increment()">+</button>

<p>Layer: {{ layerStore.state }}</p>
</div>
</template>
2 changes: 2 additions & 0 deletions packages/nuxt/playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ export default defineNuxtConfig({
},
modules: [piniaModule],

extends: ['../example-layer'],

pinia: {
storesDirs: ['./stores/**', './domain/*/stores'],
},
Expand Down
9 changes: 6 additions & 3 deletions packages/nuxt/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,12 @@ const module: NuxtModule<ModuleOptions> = defineNuxtModule<ModuleOptions>({
{ 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) {
Copy link
Member

Choose a reason for hiding this comment

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

Let's use a public API for layers. I don't know what it is but surely there must be a way to resolve the layers from the options, maybe with a nuxt hook?

Copy link

@wzc520pyfm wzc520pyfm Nov 30, 2024

Choose a reason for hiding this comment

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

nuxt.options._layers seems to be the currently recommended solution for nuxt at present. There are two reasons:

options.storesDirs.push(resolver.resolve(layer.config.srcDir, 'stores'))
}
}

if (options.storesDirs) {
Expand Down