pinia-plugin-subscription 0.1.8 → 0.2.0-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 +11 -0
- package/README.md +53 -1
- package/dist/chunks/{index-B-zO0yrr.js → index-D-rnwSJk.js} +27 -22
- package/dist/core/PluginSubscriber.d.ts +1 -1
- package/dist/core/PluginSubscription.d.ts +39 -4
- package/dist/core/RollbackStateSnapshotsHandler.d.ts +64 -0
- package/dist/core/Store.d.ts +4 -4
- package/dist/factories/state-snapshot.d.ts +3 -0
- package/dist/helpers.js +1 -1
- package/dist/lib/main.d.ts +1 -0
- package/dist/pinia-plugin-subscription.js +409 -199
- package/dist/plugins/createPlugin.d.ts +6 -1
- package/dist/types/plugin.d.ts +5 -2
- package/dist/types/store.d.ts +12 -1
- package/dist/utils/deep-clone.d.ts +1 -0
- package/dist/utils/store.d.ts +8 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ 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
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Added automatic state rollback on action failure via the `rollbackAfterFailure` store option: the declared state keys are snapshotted before the action runs and restored through `$patch` when the action throws (sync or async).
|
|
12
|
+
- Added `$rollbackAfterFailure(params, ...args)` to `PiniaCustomProperties`, available on every store registered by the plugin, to run an action with an explicit snapshot/rollback wrapper.
|
|
13
|
+
- Added `RollbackActionParams` and `RollbackAfterFailureParams` types to the public API.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
- Action names starting with `_` or `$` are rejected by the rollback wrapper to protect internal store methods.
|
|
17
|
+
- Rollback tracking data (`rollbackAfterFailure` params and pending snapshots) is now cleaned up when a store is disposed, preventing memory leaks with dynamically created stores.
|
|
18
|
+
|
|
8
19
|
## [0.1.8]
|
|
9
20
|
|
|
10
21
|
### Added
|
package/README.md
CHANGED
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
- a lightweight mechanism to declare "subscribers" that are invoked when stores are registered or updated by Pinia;
|
|
7
7
|
- a `Store` base class (helper wrapper) to ease interacting with Pinia stores from subscribers or other plugin code;
|
|
8
8
|
- an API to create a Pinia plugin from a list of subscribers;
|
|
9
|
-
- the $reset method to all stores modified by the plugin
|
|
9
|
+
- the $reset method to all stores modified by the plugin;
|
|
10
|
+
- automatic state rollback on action failure via the `rollbackAfterFailure` store option and the `$rollbackAfterFailure` method.
|
|
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
|
|
|
@@ -205,6 +206,57 @@ const mySubscriber: PluginSubscriberInterface = {
|
|
|
205
206
|
|
|
206
207
|
This keeps the server render deterministic and prevents browser-only initialization from crashing Nuxt or SSR builds.
|
|
207
208
|
|
|
209
|
+
### State rollback on action failure
|
|
210
|
+
|
|
211
|
+
The plugin can automatically restore the previous state when an action throws. Declare the state keys to snapshot per action via the `rollbackAfterFailure` store option:
|
|
212
|
+
|
|
213
|
+
```typescript
|
|
214
|
+
import { defineAStore } from 'pinia-plugin-subscription'
|
|
215
|
+
|
|
216
|
+
export const useMyStore = defineAStore('myStore', () => {
|
|
217
|
+
const count = ref(0)
|
|
218
|
+
|
|
219
|
+
function riskyAction() {
|
|
220
|
+
count.value += 1
|
|
221
|
+
throw new Error('Something went wrong')
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return { count, riskyAction }
|
|
225
|
+
}, {
|
|
226
|
+
rollbackAfterFailure: {
|
|
227
|
+
// only the listed keys are snapshotted / restored (deep-cloned)
|
|
228
|
+
riskyAction: ['count']
|
|
229
|
+
}
|
|
230
|
+
})
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
Before a configured action runs, the declared state keys are snapshotted. If the action throws (synchronously or by rejecting its returned promise), the snapshot is restored through `$patch`, so partial mutations are rolled back. The snapshot is always discarded once the action completes or fails.
|
|
234
|
+
|
|
235
|
+
Only the actions listed in `rollbackAfterFailure` are snapshotted, so unrelated actions pay no cloning cost. Use `'all'` instead of a key list to snapshot the full state — prefer explicit keys for large states.
|
|
236
|
+
|
|
237
|
+
Action names starting with `_` or `$` are rejected to protect internal store methods.
|
|
238
|
+
|
|
239
|
+
#### Manual rollback with `$rollbackAfterFailure`
|
|
240
|
+
|
|
241
|
+
Every store registered by the plugin also exposes a `$rollbackAfterFailure` method to run any action with an explicit snapshot/rollback wrapper, without declaring it in the store options:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
const store = useMyStore()
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
await store.$rollbackAfterFailure(
|
|
248
|
+
{ action: 'riskyAction', stateKeys: ['count'] },
|
|
249
|
+
// ...args forwarded to the action
|
|
250
|
+
)
|
|
251
|
+
} catch (error) {
|
|
252
|
+
// the action failed and the state was restored
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
- `params.action` — the name of the action to execute.
|
|
257
|
+
- `params.stateKeys` — optional; the state keys to snapshot, or `'all'` (default when omitted or empty).
|
|
258
|
+
- The original error is rethrown after the state is restored.
|
|
259
|
+
|
|
208
260
|
### `defineAStoreCtx(id, setup, options?)`
|
|
209
261
|
|
|
210
262
|
Use actions or access the state, added by one or more plugins, when defining the store.
|
|
@@ -49,10 +49,10 @@ class L {
|
|
|
49
49
|
set subscriptions(t) {
|
|
50
50
|
this._subscriptions = t;
|
|
51
51
|
}
|
|
52
|
-
hydrate(t, e) {
|
|
53
|
-
}
|
|
54
52
|
afterHydration(t, e) {
|
|
55
53
|
}
|
|
54
|
+
hydrate(t, e) {
|
|
55
|
+
}
|
|
56
56
|
invoke({ store: t, options: e }, r) {
|
|
57
57
|
return this._storeInstance = this._createInstance(t, { ...e, ...this.pluginOptions }, r, this.console), this._storeInstance ? (this._subscriptions = this._storeInstance.getSubscriptions(), this._storeMutationSubscription = this._storeInstance.storeSubscribe, this._storeOnActionSubscription = this._storeInstance.onAction, this.pluginCreated && this.pluginCreated(t), !0) : !1;
|
|
58
58
|
}
|
|
@@ -104,7 +104,7 @@ function N(s, t, e) {
|
|
|
104
104
|
s,
|
|
105
105
|
t,
|
|
106
106
|
r
|
|
107
|
-
) :
|
|
107
|
+
) : $(
|
|
108
108
|
s,
|
|
109
109
|
t,
|
|
110
110
|
r
|
|
@@ -129,12 +129,12 @@ function d(s, t, e) {
|
|
|
129
129
|
return o && (p.set(a, r), c.delete(s), h(s, e, "moved context to weak map"), x(a, s, e)), a;
|
|
130
130
|
}), i);
|
|
131
131
|
}
|
|
132
|
-
function
|
|
132
|
+
function $(s, t, e) {
|
|
133
133
|
return e && (t = { ...t, ...e ?? {} }), g(s, t);
|
|
134
134
|
}
|
|
135
|
-
const
|
|
135
|
+
const m = /* @__PURE__ */ new Set(["_", "$"]);
|
|
136
136
|
function I(s) {
|
|
137
|
-
return
|
|
137
|
+
return m.has(s[0]);
|
|
138
138
|
}
|
|
139
139
|
function w(s) {
|
|
140
140
|
return p.get(s) ?? (typeof s?.$id == "string" ? c.get(s.$id) : void 0);
|
|
@@ -151,6 +151,9 @@ function M(s, t) {
|
|
|
151
151
|
function T(s) {
|
|
152
152
|
return k(s);
|
|
153
153
|
}
|
|
154
|
+
function W(s, t) {
|
|
155
|
+
return `${s}-${t.$id}`;
|
|
156
|
+
}
|
|
154
157
|
function E(s) {
|
|
155
158
|
return s ? Array.isArray(s) ? s.length === 0 : typeof s == "object" ? Object.keys(s).length === 0 : typeof s == "string" ? s.trim() === "" : !1 : !(typeof s == "boolean" || typeof s == "number");
|
|
156
159
|
}
|
|
@@ -190,10 +193,6 @@ class P extends C {
|
|
|
190
193
|
get store() {
|
|
191
194
|
return this._store;
|
|
192
195
|
}
|
|
193
|
-
hydrate() {
|
|
194
|
-
}
|
|
195
|
-
afterHydration() {
|
|
196
|
-
}
|
|
197
196
|
get storeSubscribe() {
|
|
198
197
|
if (this._storeSubscribe)
|
|
199
198
|
return () => ({
|
|
@@ -215,6 +214,8 @@ class P extends C {
|
|
|
215
214
|
addSubscription(e, r, o) {
|
|
216
215
|
this._subscriptions[e] = { subscription: r, ...o ?? {} };
|
|
217
216
|
}
|
|
217
|
+
afterHydration() {
|
|
218
|
+
}
|
|
218
219
|
/**
|
|
219
220
|
* Create and return a class instance
|
|
220
221
|
* @param store
|
|
@@ -226,12 +227,6 @@ class P extends C {
|
|
|
226
227
|
if (r.storeOptions && this.hasRequiredKeys(r.storeOptions))
|
|
227
228
|
return new this(e, r, o, i);
|
|
228
229
|
}
|
|
229
|
-
hasDeniedFirstChar(e) {
|
|
230
|
-
return I(e);
|
|
231
|
-
}
|
|
232
|
-
static hasRequiredKeys(e) {
|
|
233
|
-
return this._requiredKeys !== void 0 && this._requiredKeys?.every((r) => !!e[r]);
|
|
234
|
-
}
|
|
235
230
|
getOption(e) {
|
|
236
231
|
return this.options && this.options[e];
|
|
237
232
|
}
|
|
@@ -245,6 +240,14 @@ class P extends C {
|
|
|
245
240
|
getValue(e) {
|
|
246
241
|
return e?.__v_isRef ? e.value : e;
|
|
247
242
|
}
|
|
243
|
+
hasDeniedFirstChar(e) {
|
|
244
|
+
return I(e);
|
|
245
|
+
}
|
|
246
|
+
static hasRequiredKeys(e) {
|
|
247
|
+
return this._requiredKeys !== void 0 && this._requiredKeys?.every((r) => !!e[r]);
|
|
248
|
+
}
|
|
249
|
+
hydrate() {
|
|
250
|
+
}
|
|
248
251
|
isOptionApi() {
|
|
249
252
|
return this.store._isOptionsAPI;
|
|
250
253
|
}
|
|
@@ -314,24 +317,26 @@ class D {
|
|
|
314
317
|
);
|
|
315
318
|
}
|
|
316
319
|
}
|
|
317
|
-
class
|
|
320
|
+
class K extends D {
|
|
318
321
|
constructor() {
|
|
319
322
|
super(...arguments);
|
|
320
323
|
n(this, "_pluginName", _);
|
|
321
324
|
}
|
|
322
325
|
}
|
|
323
|
-
const
|
|
326
|
+
const F = new K();
|
|
324
327
|
export {
|
|
325
328
|
D as C,
|
|
326
329
|
C as D,
|
|
327
|
-
|
|
330
|
+
F as P,
|
|
328
331
|
P as S,
|
|
329
332
|
L as a,
|
|
330
333
|
R as b,
|
|
331
|
-
|
|
334
|
+
w as c,
|
|
332
335
|
N as d,
|
|
333
|
-
|
|
334
|
-
|
|
336
|
+
k as e,
|
|
337
|
+
T as f,
|
|
338
|
+
W as g,
|
|
339
|
+
I as h,
|
|
335
340
|
E as i,
|
|
336
341
|
_ as p,
|
|
337
342
|
M as s
|
|
@@ -28,8 +28,8 @@ export default abstract class PluginSubscriber<Instance extends Store> implement
|
|
|
28
28
|
get subscriptions(): PluginSubscriptions | undefined;
|
|
29
29
|
set subscriptions(subscriptions: PluginSubscriptions);
|
|
30
30
|
constructor(pluginName: string, createInstanceFunction: CreateInstance, pluginConsole?: Console);
|
|
31
|
-
hydrate(context: PiniaPluginContext, debug: boolean): void | Promise<void>;
|
|
32
31
|
afterHydration(context: PiniaPluginContext, debug: boolean): void | Promise<void>;
|
|
32
|
+
hydrate(context: PiniaPluginContext, debug: boolean): void | Promise<void>;
|
|
33
33
|
invoke({ store, options }: PiniaPluginContext, debug: boolean): boolean;
|
|
34
34
|
}
|
|
35
35
|
export {};
|
|
@@ -4,9 +4,13 @@ import type { PluginSubscriber, PluginSubscriptionOptions, PluginSubscriptions }
|
|
|
4
4
|
export default class PluginSubscription extends Debug {
|
|
5
5
|
protected _className: string;
|
|
6
6
|
private _hydrationScheduler;
|
|
7
|
+
private _onActionSubscriptions;
|
|
8
|
+
private _onActionAfterSubscriptions;
|
|
9
|
+
private _onActionOnErrorSubscriptions;
|
|
7
10
|
private _options?;
|
|
8
11
|
private _pluginDebug?;
|
|
9
12
|
private _resetStoreCallback;
|
|
13
|
+
private _storeRollbackSnapshotsHandler;
|
|
10
14
|
private _subscribers;
|
|
11
15
|
private _subscribersDelivered;
|
|
12
16
|
private _subscribersScheduled;
|
|
@@ -16,7 +20,32 @@ export default class PluginSubscription extends Debug {
|
|
|
16
20
|
set subscribers(subscribers: PluginSubscriber[]);
|
|
17
21
|
get subscriptions(): PluginSubscriptions[] | undefined;
|
|
18
22
|
constructor(subscribers: PluginSubscriber[], debugOrOptions?: PluginSubscriptionOptions | string[], pluginOptions?: PluginSubscriptionOptions);
|
|
23
|
+
private addOnActionAfterCallback;
|
|
24
|
+
private addOnActionOnErrorCallback;
|
|
19
25
|
private addResetStoreCallback;
|
|
26
|
+
private clearOnActionCallbacksSubscriptions;
|
|
27
|
+
private clearStoreTracking;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a callback collector for the specified action and store.
|
|
30
|
+
* @param actionName The name of the action to collect callbacks for.
|
|
31
|
+
* @param store The store instance associated with the action.
|
|
32
|
+
* @returns A function that collects callbacks for the specified action and store.
|
|
33
|
+
*/
|
|
34
|
+
private createOnActionAfterCallbackCollector;
|
|
35
|
+
/**
|
|
36
|
+
* Creates a callback collector for the specified action and store that handles errors.
|
|
37
|
+
* @param actionName The name of the action to collect error callbacks for.
|
|
38
|
+
* @param store The store instance associated with the action.
|
|
39
|
+
* @returns A function that collects error callbacks for the specified action and store.
|
|
40
|
+
*/
|
|
41
|
+
private createOnActionOnErrorCallbackCollector;
|
|
42
|
+
/**
|
|
43
|
+
* Rolls back the state snapshot for a given action if an error occurs, and removes the snapshot after the action completes or fails.
|
|
44
|
+
* @param actionName The name of the action being executed.
|
|
45
|
+
* @param store The Pinia store instance.
|
|
46
|
+
* @returns void
|
|
47
|
+
*/
|
|
48
|
+
private createRollbackSnapshot;
|
|
20
49
|
private defineCurrentEnvironment;
|
|
21
50
|
private definePluginDebug;
|
|
22
51
|
private definePluginExecution;
|
|
@@ -24,15 +53,21 @@ export default class PluginSubscription extends Debug {
|
|
|
24
53
|
private defineSubscriberKey;
|
|
25
54
|
private defineSubscriptionKey;
|
|
26
55
|
private executeResetStoreCallbacks;
|
|
56
|
+
/**
|
|
57
|
+
* Executes the store's onAction subscription for the given plugin subscriber.
|
|
58
|
+
* @param store The Pinia store instance.
|
|
59
|
+
* @param subscriber The plugin subscriber.
|
|
60
|
+
* @returns void
|
|
61
|
+
*/
|
|
62
|
+
private executeStoreOnActionSubscription;
|
|
27
63
|
private executeSubscriber;
|
|
28
64
|
private executeSubscriberSafely;
|
|
65
|
+
plugin({ store, options }: PiniaPluginContext): void;
|
|
29
66
|
private queueSubscriberExecution;
|
|
67
|
+
private registerStoreCleanup;
|
|
68
|
+
private rewriteResetStore;
|
|
30
69
|
private shouldInvokePlugin;
|
|
31
70
|
private shouldScheduleAfterHydration;
|
|
32
|
-
plugin({ store, options }: PiniaPluginContext): void;
|
|
33
|
-
private rewriteResetStore;
|
|
34
|
-
private registerStoreCleanup;
|
|
35
|
-
private clearStoreTracking;
|
|
36
71
|
private storeOnActionSubscription;
|
|
37
72
|
private storeMutationSubscription;
|
|
38
73
|
private subscriptionDelivery;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { PiniaPluginContext, Store } from 'pinia';
|
|
2
|
+
/**
|
|
3
|
+
* Handles rollback state snapshots for Pinia stores.
|
|
4
|
+
* This class provides methods to add rollback actions to stores,
|
|
5
|
+
* create rollback snapshots, and manage the state snapshots internally.
|
|
6
|
+
*/
|
|
7
|
+
export default class RollbackStateSnapshotsHandler {
|
|
8
|
+
private _stateSnapshots;
|
|
9
|
+
private _storeHasRollbackSnapshots;
|
|
10
|
+
private _storeRollbackSnapshotsParams;
|
|
11
|
+
/**
|
|
12
|
+
* Adds a rollback action to the given store.
|
|
13
|
+
* This method extends the store with a $rollbackAfterFailure function that handles rollback logic for actions.
|
|
14
|
+
* @param {Store} store The store to which the rollback action will be added.
|
|
15
|
+
* @returns void
|
|
16
|
+
*/
|
|
17
|
+
addRollbackAction(store: Store): void;
|
|
18
|
+
/**
|
|
19
|
+
* Creates a rollback snapshot for the specified action and store.
|
|
20
|
+
* This snapshot can be used to restore the store's state in case of an error during the action execution.
|
|
21
|
+
* @param {string} actionName The name of the action for which the rollback snapshot is created.
|
|
22
|
+
* @param {Store} store The Pinia store instance.
|
|
23
|
+
* @returns An object containing `after` and `onError` callbacks for handling the rollback, or `undefined` if no snapshot is created.
|
|
24
|
+
*/
|
|
25
|
+
createOnActionCallbacks(actionName: string, store: Store): {
|
|
26
|
+
after: () => void;
|
|
27
|
+
onError: () => void;
|
|
28
|
+
} | undefined;
|
|
29
|
+
/**
|
|
30
|
+
* Initializes the rollback state snapshots handler from the given Pinia plugin context.
|
|
31
|
+
* This method extracts the rollback snapshot parameters from the store options and stores them internally.
|
|
32
|
+
* @param {PiniaPluginContext} param0 The Pinia plugin context containing the store and its options.
|
|
33
|
+
* @returns void
|
|
34
|
+
*/
|
|
35
|
+
initFromPluginContext({ options, store }: PiniaPluginContext): void;
|
|
36
|
+
/**
|
|
37
|
+
* Clears all rollback tracking data for the given store.
|
|
38
|
+
* Must be called when the store is disposed to avoid memory leaks with dynamically created stores.
|
|
39
|
+
* @param {Store} store The disposed Pinia store instance.
|
|
40
|
+
* @returns void
|
|
41
|
+
*/
|
|
42
|
+
clearStoreTracking(store: Store): void;
|
|
43
|
+
private patchStore;
|
|
44
|
+
/**
|
|
45
|
+
* Removes a state snapshot identified by the given snapshot key from the internal state snapshot tracking.
|
|
46
|
+
* @param snapshotKey The key of the state snapshot to be removed.
|
|
47
|
+
* @returns void
|
|
48
|
+
*/
|
|
49
|
+
private removeStateSnapshot;
|
|
50
|
+
/**
|
|
51
|
+
* Saves the current state snapshot for a given store and action.
|
|
52
|
+
* @param store The Pinia store instance.
|
|
53
|
+
* @param actionName The name of the action being executed.
|
|
54
|
+
* @param stateKeys The state keys to include in the snapshot, or 'all' for the full state.
|
|
55
|
+
* @returns A unique symbol key representing the saved snapshot.
|
|
56
|
+
*/
|
|
57
|
+
private saveStateSnapshot;
|
|
58
|
+
/**
|
|
59
|
+
* Checks if the given store has rollback snapshots.
|
|
60
|
+
* @param store The Pinia store instance.
|
|
61
|
+
* @returns True if the store has rollback snapshots, false otherwise.
|
|
62
|
+
*/
|
|
63
|
+
storeHasRollbackSnapshots(store: Store): boolean;
|
|
64
|
+
}
|
package/dist/core/Store.d.ts
CHANGED
|
@@ -18,8 +18,6 @@ export default class Store extends Debug {
|
|
|
18
18
|
get state(): StateTree;
|
|
19
19
|
set state(state: StateTree);
|
|
20
20
|
get store(): AnyObject;
|
|
21
|
-
hydrate(): void | Promise<void>;
|
|
22
|
-
afterHydration(): void | Promise<void>;
|
|
23
21
|
get storeSubscribe(): StoreMutationSubscription | undefined;
|
|
24
22
|
set storeSubscribe(storeSubscribe: StoreMutationSubscriptionCallback);
|
|
25
23
|
constructor(store: PiniaStore, options: AnyObject, debug?: boolean, customConsole?: Console);
|
|
@@ -33,6 +31,7 @@ export default class Store extends Debug {
|
|
|
33
31
|
subscriptionOptions?: StoreOptions;
|
|
34
32
|
stores?: PiniaStore[];
|
|
35
33
|
}): void;
|
|
34
|
+
afterHydration(): void | Promise<void>;
|
|
36
35
|
/**
|
|
37
36
|
* Create and return a class instance
|
|
38
37
|
* @param store
|
|
@@ -41,12 +40,13 @@ export default class Store extends Debug {
|
|
|
41
40
|
* @returns
|
|
42
41
|
*/
|
|
43
42
|
static customizeStore<Instance extends Store>(store: PiniaStore, options: AnyObject, debug?: boolean, customConsole?: Console): Instance | undefined;
|
|
44
|
-
hasDeniedFirstChar(property: string): boolean;
|
|
45
|
-
protected static hasRequiredKeys(options: AnyObject): boolean;
|
|
46
43
|
getOption(optionName: keyof StoreOptions): import("../types").StoreOptionsPropertyValue;
|
|
47
44
|
getStatePropertyValue(propertyName: string): any;
|
|
48
45
|
getSubscriptions(): PluginSubscriptions | undefined;
|
|
49
46
|
getValue(value: any): any;
|
|
47
|
+
protected hasDeniedFirstChar(property: string): boolean;
|
|
48
|
+
protected static hasRequiredKeys(options: AnyObject): boolean;
|
|
49
|
+
hydrate(): void | Promise<void>;
|
|
50
50
|
isOptionApi(): boolean;
|
|
51
51
|
stateHas(property: string): boolean;
|
|
52
52
|
storeHas(property: string): boolean;
|
package/dist/helpers.js
CHANGED
package/dist/lib/main.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export { createPlugin } from "../plugins/createPlugin";
|
|
|
5
5
|
export { createHydrationPlugin } from "../plugins/createHydrationPlugin";
|
|
6
6
|
export type { AnyObject, Console, CustomStore, DefineAStoreSetupContext, DefineAStoreSetupExtensions, EmptyExtensions, PluginExecutionEnvironment, PluginExecutionOptions, PluginHydrationScheduler, PluginHydrationTiming, PluginRuntimeEnvironment, PluginStoreOptions, PluginSubscriptionOptions, PluginSubscriberInterface, PluginSubscriptionDefinition, PluginSubscriptions, StatePropertyValue, StoreOptions, StoreOptionsPropertyValue, StoreMutationSubscription, StoreMutationSubscriptionCallback, StoreOnActionCallbackParameters, StoreOnActionSubscription, StoreOnActionSubscriptionCallback, NativePiniaSubscription, NativePiniaSubscriptionReturn, SearchCollectionCriteria, LogType, StyleDefinition, StyleDefinitionKeys, StyleDefinitions, ConsoleStyleDefinition, ConsoleStyleDefinitionKeys, ConsoleStyleDefinitions, PartialList, ListTypes, ListTypesMap, List } from "../types";
|
|
7
7
|
export type { StoreMutationSubscriptionReturn, StoreOnActionSubscriptionReturn } from "../types/plugin";
|
|
8
|
+
export type { RollbackActionParams, RollbackAfterFailureParams } from "../types/store";
|
|
8
9
|
export { defineAStore, defineAStoreCtx, getDefineAStoreSetupContext, getEnhancedStore, getExtendingStore, setEnhancedStore } from "../utils/store";
|
|
9
10
|
export { CustomConsole } from "../system/log";
|
|
10
11
|
export { isEmpty } from "../utils/validation";
|
|
@@ -1,288 +1,498 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import {
|
|
5
|
-
import { C as
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
hydration: "immediate"
|
|
9
|
-
};
|
|
10
|
-
function E(r) {
|
|
11
|
-
if (typeof window < "u" && typeof window.requestAnimationFrame == "function") {
|
|
12
|
-
window.requestAnimationFrame(() => globalThis.setTimeout(r, 0));
|
|
13
|
-
return;
|
|
14
|
-
}
|
|
15
|
-
globalThis.setTimeout(r, 0);
|
|
16
|
-
}
|
|
17
|
-
function h(r) {
|
|
1
|
+
var g = Object.defineProperty;
|
|
2
|
+
var E = (n, s, t) => s in n ? g(n, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : n[s] = t;
|
|
3
|
+
var a = (n, s, t) => E(n, typeof s != "symbol" ? s + "" : s, t);
|
|
4
|
+
import { h as O, g as f, D as m, i as y, P as C } from "./chunks/index-D-rnwSJk.js";
|
|
5
|
+
import { C as T, p as W, a as L, S as I, d as q, b as G, c as U, e as z, f as B, s as J } from "./chunks/index-D-rnwSJk.js";
|
|
6
|
+
import { toRaw as _ } from "vue";
|
|
7
|
+
function u(n) {
|
|
18
8
|
if (typeof structuredClone == "function")
|
|
19
9
|
try {
|
|
20
|
-
return structuredClone(
|
|
10
|
+
return structuredClone(n);
|
|
21
11
|
} catch {
|
|
22
12
|
}
|
|
23
|
-
if (
|
|
24
|
-
return
|
|
25
|
-
if (
|
|
13
|
+
if (n === null || typeof n != "object")
|
|
14
|
+
return n;
|
|
15
|
+
if (n instanceof Map)
|
|
26
16
|
return new Map(
|
|
27
|
-
Array.from(
|
|
17
|
+
Array.from(n.entries(), ([t, e]) => [u(t), u(e)])
|
|
28
18
|
);
|
|
29
|
-
if (
|
|
30
|
-
return new Set(Array.from(
|
|
31
|
-
if (Array.isArray(
|
|
32
|
-
return
|
|
33
|
-
if (Object.getPrototypeOf(
|
|
19
|
+
if (n instanceof Set)
|
|
20
|
+
return new Set(Array.from(n.values(), (t) => u(t)));
|
|
21
|
+
if (Array.isArray(n))
|
|
22
|
+
return n.map((t) => u(t));
|
|
23
|
+
if (Object.getPrototypeOf(n) === Object.prototype || Object.getPrototypeOf(n) === null)
|
|
34
24
|
return Object.fromEntries(
|
|
35
|
-
Object.entries(
|
|
25
|
+
Object.entries(n).map(([t, e]) => [t, u(e)])
|
|
26
|
+
);
|
|
27
|
+
const s = Object.create(Object.getPrototypeOf(n));
|
|
28
|
+
for (const [t, e] of Object.entries(n))
|
|
29
|
+
s[t] = u(e);
|
|
30
|
+
return s;
|
|
31
|
+
}
|
|
32
|
+
function $(n, s = "all") {
|
|
33
|
+
if (Array.isArray(s)) {
|
|
34
|
+
const t = {};
|
|
35
|
+
for (const e of s)
|
|
36
|
+
e in n && (t[e] = u(_(n[e])));
|
|
37
|
+
return t;
|
|
38
|
+
}
|
|
39
|
+
if (s !== "all")
|
|
40
|
+
throw new Error(`Invalid keys parameter: ${s}`);
|
|
41
|
+
return u(_(n));
|
|
42
|
+
}
|
|
43
|
+
class v {
|
|
44
|
+
constructor() {
|
|
45
|
+
a(this, "_stateSnapshots", /* @__PURE__ */ new Map());
|
|
46
|
+
a(this, "_storeHasRollbackSnapshots", /* @__PURE__ */ new Set());
|
|
47
|
+
a(this, "_storeRollbackSnapshotsParams", /* @__PURE__ */ new Map());
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Adds a rollback action to the given store.
|
|
51
|
+
* This method extends the store with a $rollbackAfterFailure function that handles rollback logic for actions.
|
|
52
|
+
* @param {Store} store The store to which the rollback action will be added.
|
|
53
|
+
* @returns void
|
|
54
|
+
*/
|
|
55
|
+
addRollbackAction(s) {
|
|
56
|
+
typeof s.$rollbackAfterFailure != "function" && (s.$rollbackAfterFailure = async ({ action: t, stateKeys: e }, ...i) => {
|
|
57
|
+
const r = s[t];
|
|
58
|
+
if (typeof r != "function" || O(t))
|
|
59
|
+
return;
|
|
60
|
+
const o = !e || e.length === 0 ? "all" : e, h = this.saveStateSnapshot(s, t, o);
|
|
61
|
+
try {
|
|
62
|
+
await r.apply(s, i);
|
|
63
|
+
} catch (c) {
|
|
64
|
+
throw this.patchStore(h, s), c;
|
|
65
|
+
} finally {
|
|
66
|
+
this.removeStateSnapshot(h);
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Creates a rollback snapshot for the specified action and store.
|
|
72
|
+
* This snapshot can be used to restore the store's state in case of an error during the action execution.
|
|
73
|
+
* @param {string} actionName The name of the action for which the rollback snapshot is created.
|
|
74
|
+
* @param {Store} store The Pinia store instance.
|
|
75
|
+
* @returns An object containing `after` and `onError` callbacks for handling the rollback, or `undefined` if no snapshot is created.
|
|
76
|
+
*/
|
|
77
|
+
createOnActionCallbacks(s, t) {
|
|
78
|
+
const e = this._storeRollbackSnapshotsParams.get(
|
|
79
|
+
f(s, t)
|
|
36
80
|
);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
81
|
+
if (!e || e.length === 0)
|
|
82
|
+
return;
|
|
83
|
+
const i = this.saveStateSnapshot(t, s, e);
|
|
84
|
+
return {
|
|
85
|
+
after: () => {
|
|
86
|
+
this.removeStateSnapshot(i);
|
|
87
|
+
},
|
|
88
|
+
onError: () => {
|
|
89
|
+
this.patchStore(i, t), this.removeStateSnapshot(i);
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Initializes the rollback state snapshots handler from the given Pinia plugin context.
|
|
95
|
+
* This method extracts the rollback snapshot parameters from the store options and stores them internally.
|
|
96
|
+
* @param {PiniaPluginContext} param0 The Pinia plugin context containing the store and its options.
|
|
97
|
+
* @returns void
|
|
98
|
+
*/
|
|
99
|
+
initFromPluginContext({ options: s, store: t }) {
|
|
100
|
+
const e = s?.storeOptions?.rollbackAfterFailure;
|
|
101
|
+
e && !this._storeHasRollbackSnapshots.has(t.$id) && (Object.keys(e).forEach((i) => {
|
|
102
|
+
this._storeRollbackSnapshotsParams.set(
|
|
103
|
+
f(i, t),
|
|
104
|
+
e[i]
|
|
105
|
+
);
|
|
106
|
+
}), this._storeHasRollbackSnapshots.add(t.$id)), this.addRollbackAction(t);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Clears all rollback tracking data for the given store.
|
|
110
|
+
* Must be called when the store is disposed to avoid memory leaks with dynamically created stores.
|
|
111
|
+
* @param {Store} store The disposed Pinia store instance.
|
|
112
|
+
* @returns void
|
|
113
|
+
*/
|
|
114
|
+
clearStoreTracking(s) {
|
|
115
|
+
const t = `-${s.$id}`;
|
|
116
|
+
for (const e of Array.from(this._storeRollbackSnapshotsParams.keys()))
|
|
117
|
+
e.endsWith(t) && this._storeRollbackSnapshotsParams.delete(e);
|
|
118
|
+
this._storeHasRollbackSnapshots.delete(s.$id);
|
|
119
|
+
for (const e of Array.from(this._stateSnapshots.keys()))
|
|
120
|
+
e.description?.startsWith(`${s.$id}:`) && this._stateSnapshots.delete(e);
|
|
121
|
+
}
|
|
122
|
+
patchStore(s, t) {
|
|
123
|
+
const e = this._stateSnapshots.get(s);
|
|
124
|
+
if (e)
|
|
125
|
+
try {
|
|
126
|
+
t.$patch(e);
|
|
127
|
+
} catch (i) {
|
|
128
|
+
console.error(`Failed to patch store with snapshot ${String(s)}`, i);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Removes a state snapshot identified by the given snapshot key from the internal state snapshot tracking.
|
|
133
|
+
* @param snapshotKey The key of the state snapshot to be removed.
|
|
134
|
+
* @returns void
|
|
135
|
+
*/
|
|
136
|
+
removeStateSnapshot(s) {
|
|
137
|
+
s && this._stateSnapshots.delete(s);
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Saves the current state snapshot for a given store and action.
|
|
141
|
+
* @param store The Pinia store instance.
|
|
142
|
+
* @param actionName The name of the action being executed.
|
|
143
|
+
* @param stateKeys The state keys to include in the snapshot, or 'all' for the full state.
|
|
144
|
+
* @returns A unique symbol key representing the saved snapshot.
|
|
145
|
+
*/
|
|
146
|
+
saveStateSnapshot(s, t, e) {
|
|
147
|
+
const i = $(
|
|
148
|
+
s.$state,
|
|
149
|
+
e
|
|
150
|
+
), r = /* @__PURE__ */ Symbol(`${s.$id}:${t}`);
|
|
151
|
+
return this._stateSnapshots.set(r, i), r;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Checks if the given store has rollback snapshots.
|
|
155
|
+
* @param store The Pinia store instance.
|
|
156
|
+
* @returns True if the store has rollback snapshots, false otherwise.
|
|
157
|
+
*/
|
|
158
|
+
storeHasRollbackSnapshots(s) {
|
|
159
|
+
return this._storeHasRollbackSnapshots.has(s.$id);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const A = "PluginSubscription", P = {
|
|
163
|
+
environment: "both",
|
|
164
|
+
hydration: "immediate"
|
|
165
|
+
};
|
|
166
|
+
function R(n) {
|
|
167
|
+
if (typeof window < "u" && typeof window.requestAnimationFrame == "function") {
|
|
168
|
+
window.requestAnimationFrame(() => globalThis.setTimeout(n, 0));
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
globalThis.setTimeout(n, 0);
|
|
41
172
|
}
|
|
42
|
-
function
|
|
43
|
-
return
|
|
173
|
+
function D(n) {
|
|
174
|
+
return n !== void 0 && !Array.isArray(n);
|
|
44
175
|
}
|
|
45
|
-
class
|
|
46
|
-
constructor(e, i
|
|
47
|
-
const
|
|
48
|
-
super(Array.isArray(
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
this
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this
|
|
176
|
+
class k extends m {
|
|
177
|
+
constructor(t, e, i) {
|
|
178
|
+
const r = Array.isArray(e) ? e : void 0, o = D(e) ? e : i;
|
|
179
|
+
super(Array.isArray(r) && !!r?.includes(A), C);
|
|
180
|
+
a(this, "_className", A);
|
|
181
|
+
a(this, "_hydrationScheduler");
|
|
182
|
+
a(this, "_onActionSubscriptions", []);
|
|
183
|
+
a(this, "_onActionAfterSubscriptions", {});
|
|
184
|
+
a(this, "_onActionOnErrorSubscriptions", {});
|
|
185
|
+
a(this, "_options");
|
|
186
|
+
a(this, "_pluginDebug");
|
|
187
|
+
a(this, "_resetStoreCallback", []);
|
|
188
|
+
a(this, "_storeRollbackSnapshotsHandler", new v());
|
|
189
|
+
a(this, "_subscribers", []);
|
|
190
|
+
a(this, "_subscribersDelivered", /* @__PURE__ */ new Set());
|
|
191
|
+
a(this, "_subscribersScheduled", /* @__PURE__ */ new Set());
|
|
192
|
+
a(this, "_subscriptions", []);
|
|
193
|
+
a(this, "_subscriptionsDelivered", /* @__PURE__ */ new Set());
|
|
194
|
+
a(this, "_subscriptionsScheduled", /* @__PURE__ */ new Set());
|
|
195
|
+
this._hydrationScheduler = o?.hydrationScheduler ?? R, this._options = o, this._pluginDebug = Array.isArray(r) ? r : void 0, this._subscribers = t;
|
|
196
|
+
}
|
|
197
|
+
set subscribers(t) {
|
|
198
|
+
this._subscribers = t;
|
|
64
199
|
}
|
|
65
200
|
get subscriptions() {
|
|
66
|
-
if (!
|
|
201
|
+
if (!y(this._subscriptions))
|
|
67
202
|
return this._subscriptions;
|
|
68
203
|
}
|
|
69
|
-
|
|
70
|
-
|
|
204
|
+
addOnActionAfterCallback(t, e, i) {
|
|
205
|
+
const r = f(t, e);
|
|
206
|
+
this._onActionAfterSubscriptions[r] || (this._onActionAfterSubscriptions[r] = []), this._onActionAfterSubscriptions[r]?.push(i);
|
|
207
|
+
}
|
|
208
|
+
addOnActionOnErrorCallback(t, e, i) {
|
|
209
|
+
const r = f(t, e);
|
|
210
|
+
this._onActionOnErrorSubscriptions[r] || (this._onActionOnErrorSubscriptions[r] = []), this._onActionOnErrorSubscriptions[r]?.push(i);
|
|
211
|
+
}
|
|
212
|
+
addResetStoreCallback(t) {
|
|
213
|
+
this._resetStoreCallback.push(t);
|
|
214
|
+
}
|
|
215
|
+
clearOnActionCallbacksSubscriptions(t) {
|
|
216
|
+
delete this._onActionAfterSubscriptions[t], delete this._onActionOnErrorSubscriptions[t];
|
|
217
|
+
}
|
|
218
|
+
clearStoreTracking(t) {
|
|
219
|
+
const e = `-${t.$id}`;
|
|
220
|
+
for (const i of Array.from(this._subscribersDelivered))
|
|
221
|
+
i.endsWith(e) && this._subscribersDelivered.delete(i);
|
|
222
|
+
for (const i of Array.from(this._subscribersScheduled))
|
|
223
|
+
i.endsWith(e) && this._subscribersScheduled.delete(i);
|
|
224
|
+
for (const i of Array.from(this._subscriptionsDelivered))
|
|
225
|
+
i.endsWith(e) && this._subscriptionsDelivered.delete(i);
|
|
226
|
+
for (const i of Array.from(this._subscriptionsScheduled))
|
|
227
|
+
i.endsWith(e) && this._subscriptionsScheduled.delete(i);
|
|
228
|
+
for (const i of Object.keys(this._onActionAfterSubscriptions))
|
|
229
|
+
i.endsWith(e) && delete this._onActionAfterSubscriptions[i];
|
|
230
|
+
for (const i of Object.keys(this._onActionOnErrorSubscriptions))
|
|
231
|
+
i.endsWith(e) && delete this._onActionOnErrorSubscriptions[i];
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Creates a callback collector for the specified action and store.
|
|
235
|
+
* @param actionName The name of the action to collect callbacks for.
|
|
236
|
+
* @param store The store instance associated with the action.
|
|
237
|
+
* @returns A function that collects callbacks for the specified action and store.
|
|
238
|
+
*/
|
|
239
|
+
createOnActionAfterCallbackCollector(t, e) {
|
|
240
|
+
return (i) => {
|
|
241
|
+
this.addOnActionAfterCallback(t, e, i);
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Creates a callback collector for the specified action and store that handles errors.
|
|
246
|
+
* @param actionName The name of the action to collect error callbacks for.
|
|
247
|
+
* @param store The store instance associated with the action.
|
|
248
|
+
* @returns A function that collects error callbacks for the specified action and store.
|
|
249
|
+
*/
|
|
250
|
+
createOnActionOnErrorCallbackCollector(t, e) {
|
|
251
|
+
return (i) => {
|
|
252
|
+
this.addOnActionOnErrorCallback(t, e, i);
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Rolls back the state snapshot for a given action if an error occurs, and removes the snapshot after the action completes or fails.
|
|
257
|
+
* @param actionName The name of the action being executed.
|
|
258
|
+
* @param store The Pinia store instance.
|
|
259
|
+
* @returns void
|
|
260
|
+
*/
|
|
261
|
+
createRollbackSnapshot(t, e) {
|
|
262
|
+
const {
|
|
263
|
+
after: i,
|
|
264
|
+
onError: r
|
|
265
|
+
} = this._storeRollbackSnapshotsHandler.createOnActionCallbacks(
|
|
266
|
+
t,
|
|
267
|
+
e
|
|
268
|
+
) ?? {};
|
|
269
|
+
!i || !r || (this.addOnActionAfterCallback(t, e, i), this.addOnActionOnErrorCallback(t, e, r));
|
|
71
270
|
}
|
|
72
271
|
defineCurrentEnvironment() {
|
|
73
272
|
return this._options?.runtimeEnvironment ?? (typeof window > "u" ? "server" : "client");
|
|
74
273
|
}
|
|
75
|
-
definePluginDebug(
|
|
76
|
-
return !!this._pluginDebug?.includes(
|
|
274
|
+
definePluginDebug(t) {
|
|
275
|
+
return !!this._pluginDebug?.includes(t.name);
|
|
77
276
|
}
|
|
78
|
-
definePluginExecution(
|
|
277
|
+
definePluginExecution(t) {
|
|
79
278
|
return {
|
|
80
|
-
...
|
|
279
|
+
...P,
|
|
81
280
|
...this._options?.execution ?? {},
|
|
82
|
-
...
|
|
83
|
-
...this._options?.subscriberExecution?.[
|
|
281
|
+
...t.execution ?? {},
|
|
282
|
+
...this._options?.subscriberExecution?.[t.name] ?? {}
|
|
84
283
|
};
|
|
85
284
|
}
|
|
86
|
-
defineHydrationScheduler(
|
|
87
|
-
return
|
|
285
|
+
defineHydrationScheduler(t) {
|
|
286
|
+
return t.hydrationScheduler ?? this._hydrationScheduler;
|
|
88
287
|
}
|
|
89
|
-
defineSubscriberKey(
|
|
90
|
-
return `${
|
|
288
|
+
defineSubscriberKey(t, e) {
|
|
289
|
+
return `${t.name}-${e.$id}`;
|
|
91
290
|
}
|
|
92
|
-
defineSubscriptionKey(
|
|
93
|
-
return `${
|
|
291
|
+
defineSubscriptionKey(t, e) {
|
|
292
|
+
return `${t}-${e.$id}`;
|
|
94
293
|
}
|
|
95
|
-
executeResetStoreCallbacks(
|
|
96
|
-
this._resetStoreCallback.forEach((
|
|
294
|
+
executeResetStoreCallbacks(t) {
|
|
295
|
+
this._resetStoreCallback.forEach((e) => e(t));
|
|
97
296
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
297
|
+
/**
|
|
298
|
+
* Executes the store's onAction subscription for the given plugin subscriber.
|
|
299
|
+
* @param store The Pinia store instance.
|
|
300
|
+
* @param subscriber The plugin subscriber.
|
|
301
|
+
* @returns void
|
|
302
|
+
*/
|
|
303
|
+
executeStoreOnActionSubscription(t) {
|
|
304
|
+
const e = this._onActionSubscriptions, i = this._storeRollbackSnapshotsHandler.storeHasRollbackSnapshots(t);
|
|
305
|
+
!e?.length && !i || t.$onAction(({ after: r, args: o, name: h, onError: c }) => {
|
|
306
|
+
const l = f(h, t);
|
|
307
|
+
this.debugLog(`storeOnActionSubscription ${l}`, { args: o, name: h, store: t }), i && this.createRollbackSnapshot(h, t), e?.length && e.forEach((b) => b({
|
|
308
|
+
after: this.createOnActionAfterCallbackCollector(h, t),
|
|
309
|
+
args: o,
|
|
310
|
+
name: h,
|
|
311
|
+
onError: this.createOnActionOnErrorCallbackCollector(h, t)
|
|
312
|
+
}));
|
|
313
|
+
const d = this._onActionAfterSubscriptions[l], S = this._onActionOnErrorSubscriptions[l];
|
|
314
|
+
this.clearOnActionCallbacksSubscriptions(l), d?.length && r((b) => {
|
|
315
|
+
d.forEach((p) => p(b));
|
|
316
|
+
}), S?.length && c((b) => {
|
|
317
|
+
S.forEach((p) => p(b));
|
|
318
|
+
});
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
executeSubscriber(t, e) {
|
|
322
|
+
const i = this.defineSubscriberKey(e, t.store), r = this.definePluginDebug(e);
|
|
323
|
+
if (this._subscribersDelivered.has(i) || !e.invoke(
|
|
324
|
+
t,
|
|
325
|
+
r
|
|
103
326
|
))
|
|
104
327
|
return;
|
|
105
|
-
this._subscribersDelivered.add(
|
|
106
|
-
let
|
|
328
|
+
this._subscribersDelivered.add(i);
|
|
329
|
+
let o;
|
|
107
330
|
try {
|
|
108
|
-
|
|
109
|
-
} catch (
|
|
110
|
-
this.logError(
|
|
331
|
+
o = e.hydrate?.(t, r);
|
|
332
|
+
} catch (c) {
|
|
333
|
+
this.logError(c, t.store, t.options);
|
|
111
334
|
return;
|
|
112
335
|
}
|
|
113
|
-
const
|
|
336
|
+
const h = () => {
|
|
114
337
|
try {
|
|
115
|
-
const
|
|
116
|
-
|
|
117
|
-
} catch (
|
|
118
|
-
this.logError(
|
|
338
|
+
const c = e.afterHydration?.(t, r);
|
|
339
|
+
c && typeof c.then == "function" && c.catch((l) => this.logError(l, t.store, t.options));
|
|
340
|
+
} catch (c) {
|
|
341
|
+
this.logError(c, t.store, t.options);
|
|
119
342
|
}
|
|
120
343
|
};
|
|
121
|
-
|
|
344
|
+
o && typeof o.then == "function" ? o.then(() => h()).catch((c) => this.logError(c, t.store, t.options)) : h(), e.subscriptions && this.subscriptionDelivery(t, e.subscriptions), e.storeMutationSubscription && this.storeMutationSubscription(e.storeMutationSubscription), this.storeOnActionSubscription(e), e.resetStoreCallback && this.addResetStoreCallback(e.resetStoreCallback);
|
|
122
345
|
}
|
|
123
|
-
executeSubscriberSafely(
|
|
346
|
+
executeSubscriberSafely(t, e) {
|
|
124
347
|
try {
|
|
125
|
-
this.executeSubscriber(
|
|
126
|
-
} catch (
|
|
127
|
-
this.logError(
|
|
348
|
+
this.executeSubscriber(t, e);
|
|
349
|
+
} catch (i) {
|
|
350
|
+
this.logError(i, t.store, t.options);
|
|
128
351
|
}
|
|
129
352
|
}
|
|
130
|
-
|
|
131
|
-
const s = this.defineHydrationScheduler(i);
|
|
132
|
-
this._subscribersScheduled.add(t), s(() => {
|
|
133
|
-
this._subscribersScheduled.delete(t), this.executeSubscriberSafely(e, i);
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
shouldInvokePlugin(e) {
|
|
137
|
-
const i = this.defineCurrentEnvironment();
|
|
138
|
-
return e.environment === "both" || e.environment === i;
|
|
139
|
-
}
|
|
140
|
-
shouldScheduleAfterHydration(e) {
|
|
141
|
-
return this.defineCurrentEnvironment() === "client" && e.hydration === "defer";
|
|
142
|
-
}
|
|
143
|
-
plugin({ store: e, options: i }) {
|
|
353
|
+
plugin({ store: t, options: e }) {
|
|
144
354
|
if (this._subscribers.length) {
|
|
145
|
-
this.debugLog(`plugin() - ${
|
|
355
|
+
this.debugLog(`plugin() - ${t.$id}`, [
|
|
146
356
|
"subscriber:",
|
|
147
357
|
this._subscribers,
|
|
148
358
|
"store:",
|
|
149
|
-
|
|
359
|
+
t,
|
|
150
360
|
"options:",
|
|
151
|
-
|
|
361
|
+
e
|
|
152
362
|
]);
|
|
153
363
|
try {
|
|
154
364
|
this._subscribers.forEach(
|
|
155
|
-
(
|
|
156
|
-
const
|
|
157
|
-
if (!(this._subscribersDelivered.has(
|
|
158
|
-
if (this.shouldScheduleAfterHydration(
|
|
159
|
-
this.queueSubscriberExecution({ store:
|
|
365
|
+
(i) => {
|
|
366
|
+
const r = this.defineSubscriberKey(i, t), o = this.definePluginExecution(i);
|
|
367
|
+
if (!(this._subscribersDelivered.has(r) || this._subscribersScheduled.has(r)) && this.shouldInvokePlugin(o)) {
|
|
368
|
+
if (this.shouldScheduleAfterHydration(o)) {
|
|
369
|
+
this.queueSubscriberExecution({ store: t, options: e }, i, r);
|
|
160
370
|
return;
|
|
161
371
|
}
|
|
162
|
-
this.executeSubscriber({ store:
|
|
372
|
+
this.executeSubscriber({ store: t, options: e }, i);
|
|
163
373
|
}
|
|
164
374
|
}
|
|
165
|
-
), this.rewriteResetStore({ store:
|
|
166
|
-
} catch (
|
|
167
|
-
this.logError(t, e
|
|
375
|
+
), this.rewriteResetStore({ store: t }, t.$state), this._storeRollbackSnapshotsHandler.initFromPluginContext({ store: t, options: e }), this.executeStoreOnActionSubscription(t), this.registerStoreCleanup(t);
|
|
376
|
+
} catch (i) {
|
|
377
|
+
this.logError(i, t, e);
|
|
168
378
|
}
|
|
169
379
|
}
|
|
170
380
|
}
|
|
171
|
-
|
|
172
|
-
const
|
|
173
|
-
|
|
174
|
-
this.
|
|
175
|
-
};
|
|
381
|
+
queueSubscriberExecution(t, e, i) {
|
|
382
|
+
const r = this.defineHydrationScheduler(e);
|
|
383
|
+
this._subscribersScheduled.add(i), r(() => {
|
|
384
|
+
this._subscribersScheduled.delete(i), this.executeSubscriberSafely(t, e);
|
|
385
|
+
});
|
|
176
386
|
}
|
|
177
|
-
registerStoreCleanup(
|
|
178
|
-
if (typeof
|
|
387
|
+
registerStoreCleanup(t) {
|
|
388
|
+
if (this._onActionSubscriptions = [], typeof t.$dispose != "function")
|
|
179
389
|
return;
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
const i =
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
t.endsWith(i) && this._subscribersScheduled.delete(t);
|
|
189
|
-
for (const t of Array.from(this._subscriptionsDelivered))
|
|
190
|
-
t.endsWith(i) && this._subscriptionsDelivered.delete(t);
|
|
191
|
-
for (const t of Array.from(this._subscriptionsScheduled))
|
|
192
|
-
t.endsWith(i) && this._subscriptionsScheduled.delete(t);
|
|
193
|
-
}
|
|
194
|
-
storeOnActionSubscription(e) {
|
|
195
|
-
const { store: i, callback: t } = e();
|
|
196
|
-
i.$onAction(({ after: s, args: n, name: d, onError: u }) => {
|
|
197
|
-
this.debugLog(`storeOnActionSubscription ${i.$id}`, { after: s, args: n, name: d, store: i }), t({ after: s, args: n, name: d, onError: u });
|
|
198
|
-
});
|
|
390
|
+
const e = t.$dispose.bind(t), i = t;
|
|
391
|
+
i.__piniaPluginSubscriptionDisposed || (i.__piniaPluginSubscriptionDisposed = !0, t.$dispose = () => (this.clearStoreTracking(t), this._storeRollbackSnapshotsHandler.clearStoreTracking(t), e()));
|
|
392
|
+
}
|
|
393
|
+
rewriteResetStore({ store: t }, e) {
|
|
394
|
+
const i = u(e);
|
|
395
|
+
t.$reset = () => {
|
|
396
|
+
this.debugLog("rewriteResetStore()", { initState: i, store: t }), this.executeResetStoreCallbacks(t), t.$patch(u(i));
|
|
397
|
+
};
|
|
199
398
|
}
|
|
200
|
-
|
|
201
|
-
const
|
|
202
|
-
|
|
203
|
-
|
|
399
|
+
shouldInvokePlugin(t) {
|
|
400
|
+
const e = this.defineCurrentEnvironment();
|
|
401
|
+
return t.environment === "both" || t.environment === e;
|
|
402
|
+
}
|
|
403
|
+
shouldScheduleAfterHydration(t) {
|
|
404
|
+
return this.defineCurrentEnvironment() === "client" && t.hydration === "defer";
|
|
405
|
+
}
|
|
406
|
+
storeOnActionSubscription(t) {
|
|
407
|
+
const { store: e, callback: i } = t?.storeOnActionSubscription?.() ?? {};
|
|
408
|
+
!e || !i || this._onActionSubscriptions.push(i);
|
|
409
|
+
}
|
|
410
|
+
storeMutationSubscription(t) {
|
|
411
|
+
const { store: e, callback: i } = t();
|
|
412
|
+
e.$subscribe((r) => {
|
|
413
|
+
this.debugLog(`$subscribe ${e.$id}`, { mutation: r, store: e }), i(r);
|
|
204
414
|
});
|
|
205
415
|
}
|
|
206
|
-
subscriptionDelivery(
|
|
207
|
-
Object.entries(
|
|
208
|
-
const
|
|
209
|
-
if (!(this._subscriptionsDelivered.has(
|
|
210
|
-
if (this.shouldScheduleAfterHydration(
|
|
211
|
-
const
|
|
212
|
-
this._subscriptionsScheduled.add(
|
|
213
|
-
this._subscriptionsScheduled.delete(
|
|
416
|
+
subscriptionDelivery(t, e) {
|
|
417
|
+
Object.entries(e).forEach(([i, r]) => {
|
|
418
|
+
const o = this.defineSubscriptionKey(i, t.store), h = this.definePluginExecution(r.subscription);
|
|
419
|
+
if (!(this._subscriptionsDelivered.has(o) || this._subscriptionsScheduled.has(o)) && this.shouldInvokePlugin(h)) {
|
|
420
|
+
if (this.shouldScheduleAfterHydration(h)) {
|
|
421
|
+
const c = this.defineHydrationScheduler(r.subscription);
|
|
422
|
+
this._subscriptionsScheduled.add(o), c(() => {
|
|
423
|
+
this._subscriptionsScheduled.delete(o), this.subscriptionDeliverySafely(t, i, r);
|
|
214
424
|
});
|
|
215
425
|
return;
|
|
216
426
|
}
|
|
217
|
-
this.subscriptionDeliverySafely(
|
|
427
|
+
this.subscriptionDeliverySafely(t, i, r);
|
|
218
428
|
}
|
|
219
429
|
});
|
|
220
430
|
}
|
|
221
|
-
subscriptionDeliverySafely({ store:
|
|
431
|
+
subscriptionDeliverySafely({ store: t, options: e }, i, r) {
|
|
222
432
|
try {
|
|
223
|
-
if (this._subscriptionsDelivered.has(this.defineSubscriptionKey(
|
|
433
|
+
if (this._subscriptionsDelivered.has(this.defineSubscriptionKey(i, t)))
|
|
224
434
|
return;
|
|
225
|
-
const { subscription:
|
|
226
|
-
this.debugLog(`subscriptionDelivery() - store: ${
|
|
435
|
+
const { subscription: o, subscriptionOptions: h, stores: c } = r;
|
|
436
|
+
this.debugLog(`subscriptionDelivery() - store: ${t.$id}`, [
|
|
227
437
|
"pluginName:",
|
|
228
|
-
|
|
438
|
+
i,
|
|
229
439
|
"subscription:",
|
|
230
|
-
|
|
440
|
+
o,
|
|
231
441
|
"options:",
|
|
232
|
-
|
|
442
|
+
r,
|
|
233
443
|
"stores:",
|
|
234
|
-
|
|
444
|
+
c
|
|
235
445
|
]);
|
|
236
|
-
const
|
|
237
|
-
storeOptions: { ...
|
|
446
|
+
const l = {
|
|
447
|
+
storeOptions: { ...e?.storeOptions ?? {}, ...h }
|
|
238
448
|
};
|
|
239
|
-
|
|
240
|
-
{ store:
|
|
449
|
+
o.invoke(
|
|
450
|
+
{ store: t, options: { ...e, ...l } },
|
|
241
451
|
this.debug
|
|
242
|
-
), this._subscriptionsDelivered.add(this.defineSubscriptionKey(
|
|
243
|
-
(
|
|
452
|
+
), this._subscriptionsDelivered.add(this.defineSubscriptionKey(i, t)), y(c) || c?.forEach(
|
|
453
|
+
(d) => o.invoke(
|
|
244
454
|
{
|
|
245
|
-
store:
|
|
455
|
+
store: d,
|
|
246
456
|
options: {
|
|
247
|
-
...
|
|
248
|
-
...
|
|
249
|
-
...
|
|
457
|
+
...e,
|
|
458
|
+
...l,
|
|
459
|
+
...d?.storeOptions ?? {}
|
|
250
460
|
}
|
|
251
461
|
},
|
|
252
462
|
this.debug
|
|
253
463
|
)
|
|
254
464
|
);
|
|
255
|
-
} catch (
|
|
256
|
-
this.logError("subscriptionDelivery()",
|
|
465
|
+
} catch (o) {
|
|
466
|
+
this.logError("subscriptionDelivery()", o, t, e);
|
|
257
467
|
}
|
|
258
468
|
}
|
|
259
469
|
}
|
|
260
|
-
function
|
|
261
|
-
const
|
|
262
|
-
return
|
|
470
|
+
function j(n, s) {
|
|
471
|
+
const t = new k(n, s);
|
|
472
|
+
return t.plugin.bind(t);
|
|
263
473
|
}
|
|
264
|
-
function
|
|
265
|
-
const
|
|
266
|
-
execution:
|
|
267
|
-
hydrationScheduler:
|
|
268
|
-
runtimeEnvironment:
|
|
269
|
-
subscriberExecution:
|
|
474
|
+
function K(n, s) {
|
|
475
|
+
const t = new k(n, s?.debug, {
|
|
476
|
+
execution: s?.execution,
|
|
477
|
+
hydrationScheduler: s?.hydrationScheduler,
|
|
478
|
+
runtimeEnvironment: s?.runtimeEnvironment,
|
|
479
|
+
subscriberExecution: s?.subscriberExecution
|
|
270
480
|
});
|
|
271
|
-
return
|
|
481
|
+
return t.plugin.bind(t);
|
|
272
482
|
}
|
|
273
483
|
export {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
484
|
+
T as CustomConsole,
|
|
485
|
+
W as PLUGIN_NAME,
|
|
486
|
+
L as PluginSubscriber,
|
|
487
|
+
k as PluginSubscription,
|
|
488
|
+
I as Store,
|
|
489
|
+
K as createHydrationPlugin,
|
|
490
|
+
j as createPlugin,
|
|
491
|
+
q as defineAStore,
|
|
492
|
+
G as defineAStoreCtx,
|
|
493
|
+
U as getDefineAStoreSetupContext,
|
|
494
|
+
z as getEnhancedStore,
|
|
495
|
+
B as getExtendingStore,
|
|
496
|
+
y as isEmpty,
|
|
497
|
+
J as setEnhancedStore
|
|
288
498
|
};
|
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
import type { PiniaPlugin } from "pinia";
|
|
2
2
|
import type { PluginSubscriber } from "../types/plugin";
|
|
3
|
-
import type { StoreOptions } from "../types/store";
|
|
3
|
+
import type { RollbackActionParams, StoreOptions } from "../types/store";
|
|
4
4
|
export declare function createPlugin(subscribers: PluginSubscriber[], debug?: string[]): PiniaPlugin;
|
|
5
5
|
declare module 'pinia' {
|
|
6
6
|
interface PiniaCustomProperties {
|
|
7
|
+
/**
|
|
8
|
+
* Executes an action and restores the previous state snapshot if it fails.
|
|
9
|
+
* Added to every store when the plugin is active.
|
|
10
|
+
*/
|
|
11
|
+
$rollbackAfterFailure: (params: RollbackActionParams, ...args: any[]) => Promise<void>;
|
|
7
12
|
}
|
|
8
13
|
interface DefineStoreOptionsBase<S, Store> {
|
|
9
14
|
storeOptions?: StoreOptions;
|
package/dist/types/plugin.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { PiniaPluginContext, StateTree, Store, SubscriptionCallbackMutation } from "pinia";
|
|
2
2
|
import type { StoreOptions } from "./store";
|
|
3
3
|
import type { Console, PluginSubscriberInterface } from ".";
|
|
4
|
+
export type CreateStateSnapshotKeys = (keyof StateTree)[] | 'all';
|
|
4
5
|
export type PluginHydrationScheduler = (callback: () => void) => void;
|
|
5
6
|
export type PluginHydrationTiming = 'defer' | 'immediate';
|
|
6
7
|
export type PluginRuntimeEnvironment = 'client' | 'server';
|
|
@@ -33,11 +34,13 @@ export interface NativePiniaSubscriptionReturn<Callback> {
|
|
|
33
34
|
store: Store;
|
|
34
35
|
callback: Callback;
|
|
35
36
|
}
|
|
37
|
+
export type StoreOnActionAfterCallbackParameter = (callback: (result?: unknown) => void) => void;
|
|
38
|
+
export type StoreOnActionOnErrorCallbackParameter = (callback: (error: unknown) => void) => void;
|
|
36
39
|
export interface StoreOnActionCallbackParameters {
|
|
37
|
-
after:
|
|
40
|
+
after: StoreOnActionAfterCallbackParameter;
|
|
38
41
|
args: any[] | object;
|
|
39
42
|
name: string;
|
|
40
|
-
onError?:
|
|
43
|
+
onError?: StoreOnActionOnErrorCallbackParameter;
|
|
41
44
|
}
|
|
42
45
|
export interface PluginSubscription {
|
|
43
46
|
stores?: Store[];
|
package/dist/types/store.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnyObject } from ".";
|
|
2
|
+
import type { CreateStateSnapshotKeys } from "./plugin";
|
|
2
3
|
import type { PiniaCustomProperties, Store, StoreDefinition } from "pinia";
|
|
3
4
|
import type { Ref } from "vue";
|
|
4
5
|
export type CustomStore<TStore, TState> = Store & TStore & TState & PiniaCustomProperties & StoreDefinition;
|
|
@@ -20,8 +21,18 @@ export type OptionBaseProperty = string | number | boolean | null | undefined |
|
|
|
20
21
|
export interface PluginStoreOptions {
|
|
21
22
|
storeOptions: StoreOptions;
|
|
22
23
|
}
|
|
24
|
+
export interface RollbackActionParams {
|
|
25
|
+
action: string;
|
|
26
|
+
stateKeys?: CreateStateSnapshotKeys;
|
|
27
|
+
}
|
|
28
|
+
export type RollbackAfterFailureParams = {
|
|
29
|
+
[key: string]: CreateStateSnapshotKeys;
|
|
30
|
+
};
|
|
23
31
|
export type StatePropertyValue = StdStatePropertyValue | Ref<StdStatePropertyValue> | StdStatePropertyValue[] | Ref<StdStatePropertyValue[]> | Ref<StdStatePropertyValue>[];
|
|
24
32
|
type StdStatePropertyValue = AnyObject | boolean | null | number | string | undefined;
|
|
25
|
-
export
|
|
33
|
+
export interface StoreOptions {
|
|
34
|
+
[key: string]: StoreOptionsPropertyValue;
|
|
35
|
+
rollbackAfterFailure?: RollbackAfterFailureParams;
|
|
36
|
+
}
|
|
26
37
|
export type StoreOptionsPropertyValue = OptionBaseProperty | OptionBaseProperty[] | ObjectBaseProperty | ObjectBaseProperty[];
|
|
27
38
|
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function deepClone<T>(value: T): T;
|
package/dist/utils/store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { DefineStoreOptions, StateTree, StoreDefinition } from "pinia";
|
|
1
|
+
import type { DefineStoreOptions, StateTree, Store, StoreDefinition } from "pinia";
|
|
2
2
|
import type { AnyObject } from "../types";
|
|
3
3
|
import type { DefineAStoreSetupContext, EmptyExtensions, PluginStoreOptions, StoreOptions } from "../types/store";
|
|
4
4
|
export declare const itemState: {
|
|
@@ -28,4 +28,11 @@ export declare function setEnhancedStore<TEnhancedStore>(ctx: DefineAStoreSetupC
|
|
|
28
28
|
* @deprecated Use getEnhancedStore instead.
|
|
29
29
|
*/
|
|
30
30
|
export declare function getExtendingStore<TEnhancedStore>(ctx: DefineAStoreSetupContext<TEnhancedStore>): TEnhancedStore;
|
|
31
|
+
/**
|
|
32
|
+
* Get the storage key for a given action and store combination.
|
|
33
|
+
* @param actionName The name of the action.
|
|
34
|
+
* @param store The Pinia store instance.
|
|
35
|
+
* @returns The storage key for the action and store combination.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getActionStoreKey(actionName: string, store: Store): string;
|
|
31
38
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pinia-plugin-subscription",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-beta.0",
|
|
4
4
|
"description": "Pinia plugin for Vue.js that helps building Pinia plugins by centralizing subscriber registration and providing a Store base class for store helpers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|