pinia-plugin-subscription 0.1.4 → 0.1.6-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,25 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.1.6]
9
+
10
+ ### Added
11
+ - Added `execution` and `hydrationScheduler` support on `PluginSubscriber` / `PluginSubscriberInterface`.
12
+ - Added `createHydrationPlugin()` as the dedicated Nuxt / SSR hydration helper.
13
+ - Added `PluginSubscriptionOptions` for hydration-specific runtime overrides without changing the default `createPlugin()` API.
14
+
15
+ ### Changed
16
+ - The execution policy now defaults to the subscriber itself, with framework-specific overrides available only through the hydration helper.
17
+ - `PluginSubscription` resolves hydration timing from the subscriber before falling back to the global runtime scheduler.
18
+
19
+ ### Fixed
20
+ - Avoided SSR hydration crashes by allowing client-only Pinia plugins to be skipped on the server or deferred on the client.
21
+
22
+ ## [0.1.5]
23
+
24
+ Minor change
25
+
26
+
8
27
  ## [0.1.4]
9
28
 
10
29
  ### Added
@@ -14,9 +33,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
14
33
 
15
34
  ### Changed
16
35
  - `getDefineAStoreSetupContext()` now falls back to store ID lookup during plugin execution timing.
36
+ - `defineAStoreSetup()` now stores setup contexts only for stores with `storeOptions.enhancedStore = true`.
37
+ - `defineAStoreSetup()` now removes ID-indexed setup contexts after weak-map registration and on store disposal.
38
+ - `defineAStoreSetup()` now logs setup-context map size transitions when `storeOptions.debug = true`.
17
39
  - Public exports now include `defineAStoreCtx`, `getEnhancedStore`, and `setEnhancedStore`.
18
40
  - GitHub Actions now publishes GitHub pre-releases to npm with the `beta` dist-tag.
19
41
 
42
+ ### Added
43
+ - Added a Vitest performance-oriented test for setup-context tracking behavior with and without `enhancedStore`.
44
+
20
45
  ### Deprecated
21
46
  - `ctx.extensions.extending` is deprecated. Use `ctx.extensions.enhancedStore`.
22
47
  - `getExtendingStore()` is deprecated. Use `getEnhancedStore()`.
package/README.md CHANGED
@@ -83,13 +83,58 @@ export const myStoreSubscriber: PluginSubscriberInterface = {
83
83
 
84
84
  - **Debug mode:** Specifies the name of the plugin(s) to debug as the second argument to `createPlugin` to enable detailed logging.
85
85
  - **Reset callbacks:** Define `resetStoreCallback` to run custom logic when a store is reset.
86
+ - **SSR and hydration control:** Configure whether each subscribed plugin runs on the server, the client, or only after client hydration.
86
87
 
87
88
  ## API Reference
88
89
 
89
- ### `createPlugin(subscribers: PluginSubscriber[], debug?: boolean): PiniaPlugin`
90
+ ### `createPlugin(subscribers: PluginSubscriber[], debug?: string[]): PiniaPlugin`
90
91
 
91
92
  Creates and returns a Pinia plugin from the provided `subscribers`. Each subscriber is invoked when a store is registered.
92
93
 
94
+ ### `createHydrationPlugin(subscribers: PluginSubscriber[], options?: PluginSubscriptionOptions): PiniaPlugin`
95
+
96
+ Creates a Pinia plugin dedicated to SSR / Nuxt hydration orchestration. This helper is useful when a store plugin needs a runtime-specific scheduler or environment override without forcing every app to re-declare the plugin’s execution policy.
97
+
98
+ ```typescript
99
+ import { createHydrationPlugin, PLUGIN_NAME as PPS } from 'pinia-plugin-subscription'
100
+
101
+ pinia.use(createHydrationPlugin([
102
+ persistedStateSubscriber
103
+ ], {
104
+ debug: [PPS],
105
+ hydrationScheduler: (run) => {
106
+ nextTick(() => run())
107
+ }
108
+ }))
109
+ ```
110
+
111
+ ### SSR / Nuxt hydration control
112
+
113
+ The source of truth for hydration policy stays on the subscriber itself. For example, a client-only plugin should declare its execution directly:
114
+
115
+ ```typescript
116
+ export const persistedStateSubscriber: PluginSubscriberInterface = {
117
+ name: 'persisted-state',
118
+ execution: {
119
+ environment: 'client',
120
+ hydration: 'defer',
121
+ },
122
+ hydrationScheduler: (run) => {
123
+ nextTick(() => run())
124
+ },
125
+ invoke: (context, debug) => {
126
+ // ...
127
+ return true
128
+ }
129
+ }
130
+ ```
131
+
132
+ Available execution options:
133
+
134
+ - `environment: 'both' | 'client' | 'server'` — controls where the subscriber is allowed to run.
135
+ - `hydration: 'immediate' | 'defer'` — on the client, `defer` schedules execution after hydration.
136
+ - `hydrationScheduler` can be provided either on a subscriber or via `createHydrationPlugin()` to override the execution timing when needed.
137
+
93
138
  ### `defineAStoreCtx(id, setup, options?)`
94
139
 
95
140
  Use actions or access the state, added by one or more plugins, when defining the store.
@@ -111,10 +156,15 @@ export const useMyStore = defineAStoreCtx('myStore', (ctx) => {
111
156
  `ctx.extensions` now supports:
112
157
  - `enhancedStore`
113
158
 
159
+ The setup context is indexed internally only when `storeOptions.enhancedStore` is set to `true` (this is enabled automatically by `defineAStoreCtx`).
160
+ The temporary lookup by store id is now cleaned as soon as the weak-map association is established (and on store dispose), which limits map growth over time.
161
+ When `storeOptions.debug` is `true`, setup-context map size transitions are logged for observability.
162
+
114
163
  ### `PluginSubscriberInterface`
115
164
 
116
165
  An object with at least an `invoke(context: PiniaPluginContext, debug?: boolean)` method, plus optional properties:
117
166
 
167
+ - `execution?: { environment?: 'both' | 'client' | 'server'; hydration?: 'immediate' | 'defer' }`
118
168
  - `resetStoreCallback?: (store?: any) => void`
119
169
  - `storeOnActionSubscription?: { store, callback }` (getter)
120
170
  - `storeMutationSubscription?: { store, callback }` (getter)
@@ -143,6 +193,18 @@ import { addStore } from './src/extending-pinia-store/plugins/stores'
143
193
  class ExtendingStoreSubscriber extends PluginSubscriber<StoreExtension> {
144
194
  constructor() {
145
195
  super('extendsPiniaStore', StoreExtension.customizeStore.bind(StoreExtension))
196
+
197
+ // Controls when this subscriber may run and whether it should wait for hydration on the client.
198
+ this.execution = {
199
+ environment: 'client',
200
+ hydration: 'defer',
201
+ }
202
+
203
+ // Optional framework-specific scheduler for deferred execution.
204
+ this.hydrationScheduler = (run) => {
205
+ nextTick(() => run())
206
+ }
207
+
146
208
  this.pluginCreated = addStore
147
209
  }
148
210
  }
@@ -150,6 +212,12 @@ class ExtendingStoreSubscriber extends PluginSubscriber<StoreExtension> {
150
212
  export const extendingStoreSubscriber = new ExtendingStoreSubscriber()
151
213
  ```
152
214
 
215
+ This example shows the recommended pattern for SSR / Nuxt-safe plugins:
216
+
217
+ - `execution.environment` restricts the subscriber to `'both'`, `'client'`, or `'server'`
218
+ - `execution.hydration` is `'immediate'` by default and can be set to `'defer'` when the plugin must wait for client hydration
219
+ - `hydrationScheduler` lets you override the runtime scheduling behavior, for example with Nuxt/Vue `nextTick()`
220
+
153
221
  ## The `Store` Class — Summary
154
222
 
155
223
  The `Store` class (see [src/core/Store.ts](src/core/Store.ts)) is a wrapper around a `PiniaStore` providing: