pinia-plugin-subscription 0.0.0-alpha.4 → 0.0.0-beta.2
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/README.md +139 -60
- package/dist/pinia-plugin-subscription.js +534 -440
- package/dist/pinia-plugin-subscription.umd.cjs +4 -4
- package/dist/types/index.d.ts +24 -5
- package/dist/types/plugin.d.ts +23 -6
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -1,102 +1,181 @@
|
|
|
1
|
-
#
|
|
1
|
+
# pinia-plugin-subscription
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
   
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Pinia plugin for Vue.js that helps building Pinia plugins by centralizing subscriber registration and providing a `Store` base class for store helpers.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
This project provides:
|
|
8
|
+
- a lightweight mechanism to declare "subscribers" that are invoked when stores are registered or updated by Pinia;
|
|
9
|
+
- a `Store` base class (helper wrapper) to ease interacting with Pinia stores from subscribers or other plugin code;
|
|
10
|
+
- an API to create a Pinia plugin from a list of subscribers.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
The main goal is to offer a clear API for writing reusable Pinia plugins and to make it easy to extend stores from plugin code.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
+
### Basic usage
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
npm install pinia-plugin-subscription
|
|
17
|
-
```
|
|
16
|
+
1. Import the plugin factory and register your subscribers with Pinia:
|
|
18
17
|
|
|
19
|
-
|
|
18
|
+
```typescript
|
|
19
|
+
// main.ts
|
|
20
|
+
import { createApp } from 'vue'
|
|
21
|
+
import { createPinia } from 'pinia'
|
|
22
|
+
import { createPlugin } from 'pinia-plugin-subscription'
|
|
23
|
+
import myStoreSubscriber from './src/core/my-store'
|
|
24
|
+
import App from './App.vue'
|
|
20
25
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
```
|
|
26
|
+
const app = createApp(App)
|
|
27
|
+
const pinia = createPinia()
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
// Register plugin (subscribers array, debug flag)
|
|
30
|
+
pinia.use(createPlugin([myStoreSubscriber]))
|
|
26
31
|
|
|
27
|
-
|
|
32
|
+
app.use(pinia)
|
|
33
|
+
app.mount('#app')
|
|
34
|
+
```
|
|
28
35
|
|
|
29
|
-
|
|
36
|
+
2. A subscriber example using a `Store` subclass:
|
|
30
37
|
|
|
31
38
|
```typescript
|
|
32
|
-
|
|
33
|
-
|
|
39
|
+
// src/core/my-store.ts
|
|
40
|
+
import { Store } from 'pinia-plugin-subscription'
|
|
34
41
|
|
|
35
|
-
|
|
42
|
+
class MyStore extends Store {
|
|
43
|
+
constructor(store, options, debug = false) {
|
|
44
|
+
super(store, options, debug)
|
|
45
|
+
this.doSomething()
|
|
46
|
+
}
|
|
36
47
|
|
|
37
|
-
|
|
38
|
-
|
|
48
|
+
private doSomething() {
|
|
49
|
+
try {
|
|
50
|
+
console.log('store', this.store)
|
|
51
|
+
console.log('state', this.state)
|
|
52
|
+
console.log('store options', this.options)
|
|
53
|
+
|
|
54
|
+
// conditionaly property added
|
|
55
|
+
if(
|
|
56
|
+
(!this.stateHas('myProperty') || this.getStatePropertyValue('myProperty') === 'old-value')
|
|
57
|
+
&& this.storeHas('myAction')
|
|
58
|
+
){
|
|
59
|
+
this.addToState('myProperty', 'new-value')
|
|
60
|
+
}
|
|
61
|
+
} catch(e) {
|
|
62
|
+
this.debugLog(e)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export const myStoreSubscriber = {
|
|
39
68
|
invoke: (context, debug) => {
|
|
40
|
-
|
|
69
|
+
// create an instance of the Store subclass when options.storeOptions is present
|
|
70
|
+
const myStore = MyStore.customizeStore(context.store, context.options, debug)
|
|
71
|
+
if (!myStore) return
|
|
72
|
+
|
|
73
|
+
//Execute logic if store is augmented by plugin
|
|
74
|
+
doAnotherthing(myStore)
|
|
75
|
+
},
|
|
76
|
+
resetStoreCallback: (store) => {
|
|
77
|
+
console.log('[subscriber] store reset:', store?.$id)
|
|
41
78
|
}
|
|
42
|
-
}
|
|
79
|
+
}
|
|
43
80
|
```
|
|
44
81
|
|
|
45
|
-
|
|
82
|
+
### Advanced usage
|
|
46
83
|
|
|
47
|
-
|
|
48
|
-
import { createApp } from 'vue';
|
|
49
|
-
import { createPinia } from 'pinia';
|
|
50
|
-
import App from './App.vue';
|
|
84
|
+
#### Debug mode
|
|
51
85
|
|
|
52
|
-
|
|
53
|
-
const pinia = createPinia();
|
|
86
|
+
Enable debug mode to log store changes and internal actions:
|
|
54
87
|
|
|
55
|
-
|
|
88
|
+
```typescript
|
|
89
|
+
pinia.use(createPlugin([subscriber], true))
|
|
90
|
+
```
|
|
56
91
|
|
|
57
|
-
|
|
58
|
-
app.mount('#app');
|
|
59
|
-
```
|
|
92
|
+
#### Reset store callbacks
|
|
60
93
|
|
|
61
|
-
|
|
94
|
+
Subscribers may define `resetStoreCallback` to run custom logic when a store reset is handled by the plugin.
|
|
62
95
|
|
|
63
|
-
|
|
96
|
+
```typescript
|
|
97
|
+
const subscriber = {
|
|
98
|
+
invoke: (context, debug) => {
|
|
99
|
+
console.log('Store changed:', context.store.$state)
|
|
100
|
+
},
|
|
101
|
+
resetStoreCallback: (store) => {
|
|
102
|
+
console.log('Store reset:', store.$id)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
64
106
|
|
|
65
|
-
|
|
107
|
+
## API
|
|
66
108
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
109
|
+
### `createPlugin(subscribers: PluginSubscriber[], debug?: boolean): PiniaPlugin`
|
|
110
|
+
|
|
111
|
+
Creates a Pinia plugin from the provided `subscribers` and optional `debug` flag. Each subscriber will be invoked with the Pinia plugin context when a store is registered.
|
|
112
|
+
|
|
113
|
+
### `PluginSubscriber`
|
|
114
|
+
|
|
115
|
+
The `PluginSubscriber` interface has been extended: it's still an object with at least an `invoke(context: PiniaPluginContext, debug?: boolean)` method, but it can now expose several useful properties for plugins:
|
|
116
|
+
|
|
117
|
+
- **`resetStoreCallback?: (store?: Store) => void`**: callback invoked when the store is reset.
|
|
118
|
+
- **`storeOnActionSubscription?: StoreOnActionSubscription`**: provides a native Pinia `onAction` subscription via a getter returning `{ store, callback }`.
|
|
119
|
+
- **`storeMutationSubscription?: StoreMutationSubscription`**: provides a native mutation subscription (`store.$subscribe`) via a getter returning `{ store, callback }`.
|
|
120
|
+
- **`subscriptions: PluginSubscriptions | undefined`**: an object listing plugin-specific subscription functions (see `Store.addSubscription`).
|
|
121
|
+
|
|
122
|
+
These additions make it easier for subscribers to integrate with Pinia's native event cycle and to expose reusable extension points.
|
|
70
123
|
|
|
71
|
-
|
|
124
|
+
## The `PluginSubscriber` class (abstract)
|
|
125
|
+
|
|
126
|
+
The project provides an abstract `PluginSubscriber` implementation ([src/plugins/pluginSubscriber.ts](src/plugins/pluginSubscriber.ts)) that makes it easy to create reusable subscribers:
|
|
127
|
+
|
|
128
|
+
- Constructor: `new PluginSubscriber(pluginName: string, createInstanceFunction: CreateInstance)`
|
|
129
|
+
- Main behavior: in `invoke(context, debug)` the class creates a helper instance (`Store` or subclass) via the `createInstanceFunction` (typically `MyStore.customizeStore`) and exposes on the instance:
|
|
130
|
+
- `subscriptions` (from `store.getSubscriptions()`)
|
|
131
|
+
- `storeMutationSubscription` (from `store.storeSubscribe`)
|
|
132
|
+
- `storeOnActionSubscription` (from `store.onAction`)
|
|
133
|
+
- optionally a `pluginCreated(store)` hook called after initialization
|
|
72
134
|
|
|
73
|
-
Add custom callbacks to be executed when the store is reset.
|
|
74
135
|
|
|
75
136
|
```typescript
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
137
|
+
import PluginSubscriber from './src/plugins/pluginSubscriber'
|
|
138
|
+
import StoreExtension from './src/extending-pinia-store/core/StoreExtension'
|
|
139
|
+
import { addStore } from './src/extending-pinia-store/plugins/stores'
|
|
140
|
+
|
|
141
|
+
class ExtendingStoreSubscriber extends PluginSubscriber<StoreExtension> {
|
|
142
|
+
constructor() {
|
|
143
|
+
super('extendsPiniaStore', StoreExtension.customizeStore.bind(StoreExtension))
|
|
144
|
+
this.pluginCreated = addStore
|
|
82
145
|
}
|
|
83
|
-
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export const extendingStoreSubscriber = new ExtendingStoreSubscriber()
|
|
84
149
|
```
|
|
85
150
|
|
|
86
|
-
|
|
151
|
+
Here `ExtendingStoreSubscriber` provides a `createInstanceFunction` that returns a `StoreExtension` instance if `options.storeOptions` is present, and sets a `pluginCreated` hook (here `addStore`) to run plugin-specific logic once the instance is ready.
|
|
87
152
|
|
|
88
|
-
|
|
153
|
+
## The `Store` class (summary)
|
|
89
154
|
|
|
90
|
-
|
|
155
|
+
The `Store` class (in [src/core/Store.ts](src/core/Store.ts)) is a base wrapper around a `PiniaStore` exposing helpers:
|
|
91
156
|
|
|
92
|
-
-
|
|
93
|
-
-
|
|
157
|
+
- Properties: `debug`, `options`, `state`, `store`.
|
|
158
|
+
- Useful methods:
|
|
159
|
+
- `addToState(name, value?)`: adds a property to the store state and exposes it as a `Ref` on the store when appropriate.
|
|
160
|
+
- `addSubscription(pluginName, subscription)`: registers a plugin-specific subscription function (accessible via `getSubscriptions`).
|
|
161
|
+
- `getSubscriptions()`: returns subscriptions registered with `addSubscription` (or `undefined`).
|
|
162
|
+
- `storeSubscribe` (getter/setter): exposes a mutation subscription callback (`store.$subscribe`) as a factory returning `{ store, callback }`.
|
|
163
|
+
- `onAction` (getter/setter): exposes a Pinia `onAction` callback in the same form.
|
|
164
|
+
- `static customizeStore(store, options, debug?)`: instantiate the class (or subclass) when `options.storeOptions` is present.
|
|
165
|
+
- `debugLog(message, args)`: conditional logging when `debug` is true.
|
|
166
|
+
- `hasDeniedFirstChar(property)`, `getOption(...)`, `getValue(value)`, `getStatePropertyValue(...)`.
|
|
167
|
+
- `isOptionApi()`: true when the store uses Pinia Options API.
|
|
94
168
|
|
|
95
|
-
|
|
169
|
+
Other small helpers exposed: `stateHas(property)`, `storeHas(property)` and `getValue` to retrieve the real value of a `Ref` or a raw value.
|
|
96
170
|
|
|
97
|
-
|
|
171
|
+
`Store.customizeStore(...)` is the recommended entry point used by subscribers to create store helper instances.
|
|
98
172
|
|
|
99
|
-
|
|
100
|
-
|
|
173
|
+
|
|
174
|
+
## Testing
|
|
101
175
|
|
|
176
|
+
This plugin is tested with Vitest. Coverage (from the included coverage report at [coverage/index.html](coverage/index.html)):
|
|
102
177
|
|
|
178
|
+
- Statements: **97.64%** (83/85)
|
|
179
|
+
- Branches: **86.53%** (45/52)
|
|
180
|
+
- Functions: **100%** (38/38)
|
|
181
|
+
- Lines: **97.59%** (81/83)
|