@ngstato/core 0.1.1 → 0.2.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/README.md +17 -3
- package/dist/{index.d.cts → index.d.mts} +28 -2
- package/dist/index.d.ts +28 -2
- package/dist/index.js +228 -3
- package/dist/index.js.map +1 -1
- package/dist/{index.cjs → index.mjs} +213 -21
- package/dist/index.mjs.map +1 -0
- package/package.json +22 -4
- package/dist/index.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -23,14 +23,21 @@ const store = createStore({
|
|
|
23
23
|
}
|
|
24
24
|
},
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
selectors: {
|
|
27
27
|
total: (state) => state.users.length
|
|
28
|
-
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
effects: [
|
|
31
|
+
[
|
|
32
|
+
(state) => state.users.length,
|
|
33
|
+
(count) => console.log('Total users:', count)
|
|
34
|
+
]
|
|
35
|
+
]
|
|
29
36
|
})
|
|
30
37
|
|
|
31
38
|
await store.loadUsers()
|
|
32
39
|
console.log(store.users) // User[]
|
|
33
|
-
console.log(store.total) // number
|
|
40
|
+
console.log(store.total) // number (selector memoïzé)
|
|
34
41
|
```
|
|
35
42
|
|
|
36
43
|
## Helpers
|
|
@@ -43,6 +50,13 @@ console.log(store.total) // number
|
|
|
43
50
|
| `retryable()` | Retry avec backoff fixe ou exponentiel |
|
|
44
51
|
| `fromStream()` | Realtime — WebSocket, Firebase, Supabase |
|
|
45
52
|
| `optimistic()` | Optimistic update + rollback automatique |
|
|
53
|
+
| `withPersist()` | Persistance localStorage/sessionStorage + migration |
|
|
54
|
+
|
|
55
|
+
## Nouvautés v0.2
|
|
56
|
+
|
|
57
|
+
- `selectors` memoïzés (recalcul seulement quand les dépendances changent)
|
|
58
|
+
- `effects` réactifs explicites avec cleanup automatique
|
|
59
|
+
- `withPersist()` pour hydrater/persister le state
|
|
46
60
|
|
|
47
61
|
## Documentation
|
|
48
62
|
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
type StateSlice<T> = Omit<T, 'actions' | 'computed' | 'hooks'>;
|
|
1
|
+
type StateSlice<T> = Omit<T, 'actions' | 'computed' | 'selectors' | 'hooks'>;
|
|
2
2
|
type Action<S> = (state: S, ...args: any[]) => void | Promise<void> | (() => void);
|
|
3
3
|
type ActionsMap<S> = Record<string, Action<S>>;
|
|
4
4
|
type ComputedFn<S> = (state: S) => unknown;
|
|
5
|
+
type SelectorFn<S> = (state: S) => unknown;
|
|
6
|
+
type EffectDepsFn<S> = (state: S) => unknown | unknown[];
|
|
7
|
+
type EffectCleanup = void | (() => void);
|
|
8
|
+
type EffectRunner<S> = (depsValue: unknown | unknown[], ctx: {
|
|
9
|
+
state: Readonly<S>;
|
|
10
|
+
store: any;
|
|
11
|
+
prevDepsValue?: unknown | unknown[];
|
|
12
|
+
}) => EffectCleanup | Promise<EffectCleanup>;
|
|
13
|
+
type EffectEntry<S> = [EffectDepsFn<S>, EffectRunner<S>];
|
|
5
14
|
interface StatoHooks<S> {
|
|
6
15
|
onInit?: (store: S) => void | Promise<void>;
|
|
7
16
|
onDestroy?: (store: S) => void | Promise<void>;
|
|
@@ -13,6 +22,8 @@ interface StatoHooks<S> {
|
|
|
13
22
|
interface StatoStoreConfig<S extends object> {
|
|
14
23
|
actions?: ActionsMap<StateSlice<S>>;
|
|
15
24
|
computed?: Record<string, ComputedFn<StateSlice<S>> | unknown[]>;
|
|
25
|
+
selectors?: Record<string, SelectorFn<StateSlice<S>> | unknown[]>;
|
|
26
|
+
effects?: EffectEntry<StateSlice<S>>[];
|
|
16
27
|
hooks?: StatoHooks<any>;
|
|
17
28
|
[key: string]: unknown;
|
|
18
29
|
}
|
|
@@ -95,6 +106,21 @@ declare function fromStream<S, T>(setupFn: (state: S) => StatoObservable<T>, upd
|
|
|
95
106
|
|
|
96
107
|
declare function optimistic<S, A extends unknown[]>(immediate: (state: S, ...args: A) => void, confirm: (state: S, ...args: A) => Promise<void>): (state: S, ...args: A) => Promise<void>;
|
|
97
108
|
|
|
109
|
+
interface PersistStorage {
|
|
110
|
+
getItem(key: string): string | null;
|
|
111
|
+
setItem(key: string, value: string): void;
|
|
112
|
+
removeItem(key: string): void;
|
|
113
|
+
}
|
|
114
|
+
interface PersistOptions<S extends object> {
|
|
115
|
+
key: string;
|
|
116
|
+
version?: number;
|
|
117
|
+
storage?: PersistStorage;
|
|
118
|
+
pick?: (keyof S)[];
|
|
119
|
+
migrate?: (data: unknown, fromVersion: number) => Partial<S>;
|
|
120
|
+
onError?: (error: Error) => void;
|
|
121
|
+
}
|
|
122
|
+
declare function withPersist<S extends object>(config: S & StatoStoreConfig<S>, options: PersistOptions<StateSlice<S>>): S & StatoStoreConfig<S>;
|
|
123
|
+
|
|
98
124
|
interface ActionLog {
|
|
99
125
|
id: number;
|
|
100
126
|
name: string;
|
|
@@ -124,4 +150,4 @@ declare function createDevTools(maxLogs?: number): DevToolsInstance;
|
|
|
124
150
|
declare const devTools: DevToolsInstance;
|
|
125
151
|
declare function connectDevTools(store: any, storeName: string): void;
|
|
126
152
|
|
|
127
|
-
export { type ActionLog, type DevToolsInstance, type DevToolsState, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, abortable, configureHttp, connectDevTools, createDevTools, createHttp, createStore, debounced, devTools, fromStream, http, optimistic, retryable, throttled };
|
|
153
|
+
export { type ActionLog, type DevToolsInstance, type DevToolsState, type EffectDepsFn, type EffectEntry, type EffectRunner, type PersistOptions, type PersistStorage, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, abortable, configureHttp, connectDevTools, createDevTools, createHttp, createStore, debounced, devTools, fromStream, http, optimistic, retryable, throttled, withPersist };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
type StateSlice<T> = Omit<T, 'actions' | 'computed' | 'hooks'>;
|
|
1
|
+
type StateSlice<T> = Omit<T, 'actions' | 'computed' | 'selectors' | 'hooks'>;
|
|
2
2
|
type Action<S> = (state: S, ...args: any[]) => void | Promise<void> | (() => void);
|
|
3
3
|
type ActionsMap<S> = Record<string, Action<S>>;
|
|
4
4
|
type ComputedFn<S> = (state: S) => unknown;
|
|
5
|
+
type SelectorFn<S> = (state: S) => unknown;
|
|
6
|
+
type EffectDepsFn<S> = (state: S) => unknown | unknown[];
|
|
7
|
+
type EffectCleanup = void | (() => void);
|
|
8
|
+
type EffectRunner<S> = (depsValue: unknown | unknown[], ctx: {
|
|
9
|
+
state: Readonly<S>;
|
|
10
|
+
store: any;
|
|
11
|
+
prevDepsValue?: unknown | unknown[];
|
|
12
|
+
}) => EffectCleanup | Promise<EffectCleanup>;
|
|
13
|
+
type EffectEntry<S> = [EffectDepsFn<S>, EffectRunner<S>];
|
|
5
14
|
interface StatoHooks<S> {
|
|
6
15
|
onInit?: (store: S) => void | Promise<void>;
|
|
7
16
|
onDestroy?: (store: S) => void | Promise<void>;
|
|
@@ -13,6 +22,8 @@ interface StatoHooks<S> {
|
|
|
13
22
|
interface StatoStoreConfig<S extends object> {
|
|
14
23
|
actions?: ActionsMap<StateSlice<S>>;
|
|
15
24
|
computed?: Record<string, ComputedFn<StateSlice<S>> | unknown[]>;
|
|
25
|
+
selectors?: Record<string, SelectorFn<StateSlice<S>> | unknown[]>;
|
|
26
|
+
effects?: EffectEntry<StateSlice<S>>[];
|
|
16
27
|
hooks?: StatoHooks<any>;
|
|
17
28
|
[key: string]: unknown;
|
|
18
29
|
}
|
|
@@ -95,6 +106,21 @@ declare function fromStream<S, T>(setupFn: (state: S) => StatoObservable<T>, upd
|
|
|
95
106
|
|
|
96
107
|
declare function optimistic<S, A extends unknown[]>(immediate: (state: S, ...args: A) => void, confirm: (state: S, ...args: A) => Promise<void>): (state: S, ...args: A) => Promise<void>;
|
|
97
108
|
|
|
109
|
+
interface PersistStorage {
|
|
110
|
+
getItem(key: string): string | null;
|
|
111
|
+
setItem(key: string, value: string): void;
|
|
112
|
+
removeItem(key: string): void;
|
|
113
|
+
}
|
|
114
|
+
interface PersistOptions<S extends object> {
|
|
115
|
+
key: string;
|
|
116
|
+
version?: number;
|
|
117
|
+
storage?: PersistStorage;
|
|
118
|
+
pick?: (keyof S)[];
|
|
119
|
+
migrate?: (data: unknown, fromVersion: number) => Partial<S>;
|
|
120
|
+
onError?: (error: Error) => void;
|
|
121
|
+
}
|
|
122
|
+
declare function withPersist<S extends object>(config: S & StatoStoreConfig<S>, options: PersistOptions<StateSlice<S>>): S & StatoStoreConfig<S>;
|
|
123
|
+
|
|
98
124
|
interface ActionLog {
|
|
99
125
|
id: number;
|
|
100
126
|
name: string;
|
|
@@ -124,4 +150,4 @@ declare function createDevTools(maxLogs?: number): DevToolsInstance;
|
|
|
124
150
|
declare const devTools: DevToolsInstance;
|
|
125
151
|
declare function connectDevTools(store: any, storeName: string): void;
|
|
126
152
|
|
|
127
|
-
export { type ActionLog, type DevToolsInstance, type DevToolsState, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, abortable, configureHttp, connectDevTools, createDevTools, createHttp, createStore, debounced, devTools, fromStream, http, optimistic, retryable, throttled };
|
|
153
|
+
export { type ActionLog, type DevToolsInstance, type DevToolsState, type EffectDepsFn, type EffectEntry, type EffectRunner, type PersistOptions, type PersistStorage, type RequestOptions, type StatoConfig, type StatoHooks, StatoHttp, StatoHttpError, type StatoStoreConfig, type StatoStoreInstance, abortable, configureHttp, connectDevTools, createDevTools, createHttp, createStore, debounced, devTools, fromStream, http, optimistic, retryable, throttled, withPersist };
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
1
3
|
// src/store.ts
|
|
2
4
|
var StatoStore = class {
|
|
3
5
|
// Le state interne — jamais accessible directement
|
|
@@ -8,12 +10,44 @@ var StatoStore = class {
|
|
|
8
10
|
_actions = {};
|
|
9
11
|
// Les computed enregistrés
|
|
10
12
|
_computed = {};
|
|
13
|
+
_selectors = {};
|
|
11
14
|
// Les cleanups à appeler à la destruction
|
|
12
15
|
_cleanups = [];
|
|
13
16
|
// Les hooks lifecycle
|
|
14
17
|
_hooks;
|
|
18
|
+
_publicStore = null;
|
|
19
|
+
_effects = [];
|
|
20
|
+
_createMemoizedSelector(fn) {
|
|
21
|
+
let initialized = false;
|
|
22
|
+
let cachedResult;
|
|
23
|
+
let trackedKeys = [];
|
|
24
|
+
let trackedValues = [];
|
|
25
|
+
return () => {
|
|
26
|
+
if (initialized && trackedKeys.length) {
|
|
27
|
+
const unchanged = trackedKeys.every(
|
|
28
|
+
(key, index) => Object.is(this._state[key], trackedValues[index])
|
|
29
|
+
);
|
|
30
|
+
if (unchanged) return cachedResult;
|
|
31
|
+
}
|
|
32
|
+
const reads = /* @__PURE__ */ new Set();
|
|
33
|
+
const trackingState = new Proxy(this._state, {
|
|
34
|
+
get: (target, prop, receiver) => {
|
|
35
|
+
if (typeof prop === "string" && prop in target) {
|
|
36
|
+
reads.add(prop);
|
|
37
|
+
}
|
|
38
|
+
return Reflect.get(target, prop, receiver);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
const result = fn(trackingState);
|
|
42
|
+
trackedKeys = Array.from(reads);
|
|
43
|
+
trackedValues = trackedKeys.map((key) => this._state[key]);
|
|
44
|
+
cachedResult = result;
|
|
45
|
+
initialized = true;
|
|
46
|
+
return result;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
15
49
|
constructor(config) {
|
|
16
|
-
const { actions, computed, hooks, ...initialState } = config;
|
|
50
|
+
const { actions, computed, selectors, effects, hooks, ...initialState } = config;
|
|
17
51
|
this._state = initialState;
|
|
18
52
|
this._hooks = hooks ?? {};
|
|
19
53
|
if (actions) {
|
|
@@ -28,6 +62,27 @@ var StatoStore = class {
|
|
|
28
62
|
}
|
|
29
63
|
}
|
|
30
64
|
}
|
|
65
|
+
if (selectors) {
|
|
66
|
+
for (const [name, fn] of Object.entries(selectors)) {
|
|
67
|
+
if (typeof fn === "function") {
|
|
68
|
+
this._selectors[name] = this._createMemoizedSelector(fn);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (effects) {
|
|
73
|
+
for (const entry of effects) {
|
|
74
|
+
const [deps, run] = entry;
|
|
75
|
+
if (typeof deps === "function" && typeof run === "function") {
|
|
76
|
+
this._effects.push({
|
|
77
|
+
deps,
|
|
78
|
+
run,
|
|
79
|
+
hasRun: false,
|
|
80
|
+
running: false,
|
|
81
|
+
rerunRequested: false
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
31
86
|
}
|
|
32
87
|
// ── Lire le state ──────────────────────────────────
|
|
33
88
|
getState() {
|
|
@@ -36,8 +91,56 @@ var StatoStore = class {
|
|
|
36
91
|
// ── Modifier le state — usage interne uniquement ───
|
|
37
92
|
_setState(partial) {
|
|
38
93
|
this._state = { ...this._state, ...partial };
|
|
94
|
+
this._runEffects();
|
|
39
95
|
this._notify();
|
|
40
96
|
}
|
|
97
|
+
_normalizeDeps(value) {
|
|
98
|
+
return Array.isArray(value) ? value : [value];
|
|
99
|
+
}
|
|
100
|
+
_depsChanged(prev, next) {
|
|
101
|
+
if (!prev) return true;
|
|
102
|
+
if (prev.length !== next.length) return true;
|
|
103
|
+
for (let i = 0; i < next.length; i++) {
|
|
104
|
+
if (!Object.is(prev[i], next[i])) return true;
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
_runEffects(force = false) {
|
|
109
|
+
for (const effect of this._effects) {
|
|
110
|
+
const depsValue = effect.deps(this._state);
|
|
111
|
+
const depsArray = this._normalizeDeps(depsValue);
|
|
112
|
+
const shouldRun = force || this._depsChanged(effect.prevDeps, depsArray);
|
|
113
|
+
if (!shouldRun) continue;
|
|
114
|
+
const execute = async () => {
|
|
115
|
+
if (effect.running) {
|
|
116
|
+
effect.rerunRequested = true;
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
effect.running = true;
|
|
120
|
+
effect.rerunRequested = false;
|
|
121
|
+
const prevDepsValue = effect.prevDeps;
|
|
122
|
+
effect.prevDeps = depsArray;
|
|
123
|
+
try {
|
|
124
|
+
effect.cleanup?.();
|
|
125
|
+
const maybeCleanup = await effect.run(depsValue, {
|
|
126
|
+
state: { ...this._state },
|
|
127
|
+
store: this._publicStore,
|
|
128
|
+
prevDepsValue
|
|
129
|
+
});
|
|
130
|
+
effect.cleanup = typeof maybeCleanup === "function" ? maybeCleanup : void 0;
|
|
131
|
+
effect.hasRun = true;
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this._hooks.onError?.(error, "effect");
|
|
134
|
+
} finally {
|
|
135
|
+
effect.running = false;
|
|
136
|
+
if (effect.rerunRequested) {
|
|
137
|
+
this._runEffects();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
void execute();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
41
144
|
// ── Notifier tous les abonnés ──────────────────────
|
|
42
145
|
_notify() {
|
|
43
146
|
for (const subscriber of this._subscribers) {
|
|
@@ -80,16 +183,34 @@ var StatoStore = class {
|
|
|
80
183
|
if (!fn) throw new Error(`[Stato] Computed "${name}" introuvable`);
|
|
81
184
|
return fn();
|
|
82
185
|
}
|
|
186
|
+
getSelector(name) {
|
|
187
|
+
const fn = this._selectors[name];
|
|
188
|
+
if (!fn) throw new Error(`[Stato] Selector "${name}" introuvable`);
|
|
189
|
+
return fn();
|
|
190
|
+
}
|
|
83
191
|
// ── Enregistrer un cleanup (pour fromStream) ───────
|
|
84
192
|
registerCleanup(fn) {
|
|
85
193
|
this._cleanups.push(fn);
|
|
86
194
|
}
|
|
195
|
+
hydrate(partial) {
|
|
196
|
+
this._setState(partial);
|
|
197
|
+
}
|
|
198
|
+
setPublicStore(publicStore) {
|
|
199
|
+
this._publicStore = publicStore;
|
|
200
|
+
this._runEffects(true);
|
|
201
|
+
}
|
|
87
202
|
// ── Lifecycle — appelé par l'adaptateur Angular ────
|
|
88
203
|
init(publicStore) {
|
|
204
|
+
this._publicStore = publicStore;
|
|
89
205
|
this._hooks.onInit?.(publicStore);
|
|
206
|
+
this._runEffects(true);
|
|
90
207
|
}
|
|
91
208
|
destroy(publicStore) {
|
|
92
209
|
this._hooks.onDestroy?.(publicStore);
|
|
210
|
+
for (const effect of this._effects) {
|
|
211
|
+
effect.cleanup?.();
|
|
212
|
+
effect.cleanup = void 0;
|
|
213
|
+
}
|
|
93
214
|
for (const cleanup of this._cleanups) {
|
|
94
215
|
cleanup();
|
|
95
216
|
}
|
|
@@ -117,7 +238,7 @@ function createStore(config) {
|
|
|
117
238
|
configurable: true
|
|
118
239
|
});
|
|
119
240
|
}
|
|
120
|
-
const { actions, computed } = config;
|
|
241
|
+
const { actions, computed, selectors } = config;
|
|
121
242
|
if (actions) {
|
|
122
243
|
for (const name of Object.keys(actions)) {
|
|
123
244
|
publicStore[name] = (...args) => store.dispatch(name, ...args);
|
|
@@ -132,6 +253,16 @@ function createStore(config) {
|
|
|
132
253
|
});
|
|
133
254
|
}
|
|
134
255
|
}
|
|
256
|
+
if (selectors) {
|
|
257
|
+
for (const name of Object.keys(selectors)) {
|
|
258
|
+
Object.defineProperty(publicStore, name, {
|
|
259
|
+
get: () => store.getSelector(name),
|
|
260
|
+
enumerable: true,
|
|
261
|
+
configurable: true
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
store.setPublicStore(publicStore);
|
|
135
266
|
return publicStore;
|
|
136
267
|
}
|
|
137
268
|
|
|
@@ -364,6 +495,85 @@ function optimistic(immediate, confirm) {
|
|
|
364
495
|
};
|
|
365
496
|
}
|
|
366
497
|
|
|
498
|
+
// src/helpers/with-persist.ts
|
|
499
|
+
function resolveStorage(custom) {
|
|
500
|
+
if (custom) return custom;
|
|
501
|
+
if (typeof window === "undefined") return null;
|
|
502
|
+
try {
|
|
503
|
+
return window.localStorage;
|
|
504
|
+
} catch {
|
|
505
|
+
return null;
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
function pickState(state, keys) {
|
|
509
|
+
if (!keys?.length) return state;
|
|
510
|
+
const picked = {};
|
|
511
|
+
for (const key of keys) {
|
|
512
|
+
picked[key] = state[key];
|
|
513
|
+
}
|
|
514
|
+
return picked;
|
|
515
|
+
}
|
|
516
|
+
function withPersist(config, options) {
|
|
517
|
+
const {
|
|
518
|
+
key,
|
|
519
|
+
version = 1,
|
|
520
|
+
storage: customStorage,
|
|
521
|
+
pick,
|
|
522
|
+
migrate,
|
|
523
|
+
onError
|
|
524
|
+
} = options;
|
|
525
|
+
const storage = resolveStorage(customStorage);
|
|
526
|
+
const userHooks = config.hooks ?? {};
|
|
527
|
+
const mergedHooks = {
|
|
528
|
+
...userHooks,
|
|
529
|
+
onInit(store) {
|
|
530
|
+
try {
|
|
531
|
+
if (!storage) return userHooks.onInit?.(store);
|
|
532
|
+
const raw = storage.getItem(key);
|
|
533
|
+
if (!raw) return userHooks.onInit?.(store);
|
|
534
|
+
const parsed = JSON.parse(raw);
|
|
535
|
+
const data = parsed.v === version ? parsed.data : migrate ? migrate(parsed.data, parsed.v) : parsed.data;
|
|
536
|
+
if (data && typeof data === "object") {
|
|
537
|
+
store.__store__?.hydrate?.(data);
|
|
538
|
+
}
|
|
539
|
+
} catch (error) {
|
|
540
|
+
onError?.(error);
|
|
541
|
+
}
|
|
542
|
+
return userHooks.onInit?.(store);
|
|
543
|
+
},
|
|
544
|
+
onStateChange(prev, next) {
|
|
545
|
+
try {
|
|
546
|
+
if (storage) {
|
|
547
|
+
const payload = {
|
|
548
|
+
v: version,
|
|
549
|
+
data: pickState(next, pick)
|
|
550
|
+
};
|
|
551
|
+
storage.setItem(key, JSON.stringify(payload));
|
|
552
|
+
}
|
|
553
|
+
} catch (error) {
|
|
554
|
+
onError?.(error);
|
|
555
|
+
}
|
|
556
|
+
userHooks.onStateChange?.(prev, next);
|
|
557
|
+
},
|
|
558
|
+
onDestroy(store) {
|
|
559
|
+
return userHooks.onDestroy?.(store);
|
|
560
|
+
},
|
|
561
|
+
onAction(name, args) {
|
|
562
|
+
return userHooks.onAction?.(name, args);
|
|
563
|
+
},
|
|
564
|
+
onActionDone(name, duration) {
|
|
565
|
+
return userHooks.onActionDone?.(name, duration);
|
|
566
|
+
},
|
|
567
|
+
onError(error, actionName) {
|
|
568
|
+
return userHooks.onError?.(error, actionName);
|
|
569
|
+
}
|
|
570
|
+
};
|
|
571
|
+
return {
|
|
572
|
+
...config,
|
|
573
|
+
hooks: mergedHooks
|
|
574
|
+
};
|
|
575
|
+
}
|
|
576
|
+
|
|
367
577
|
// src/devtools.ts
|
|
368
578
|
function createDevTools(maxLogs = 50) {
|
|
369
579
|
let counter = 0;
|
|
@@ -450,6 +660,21 @@ function connectDevTools(store, storeName) {
|
|
|
450
660
|
};
|
|
451
661
|
}
|
|
452
662
|
|
|
453
|
-
|
|
663
|
+
exports.StatoHttp = StatoHttp;
|
|
664
|
+
exports.StatoHttpError = StatoHttpError;
|
|
665
|
+
exports.abortable = abortable;
|
|
666
|
+
exports.configureHttp = configureHttp;
|
|
667
|
+
exports.connectDevTools = connectDevTools;
|
|
668
|
+
exports.createDevTools = createDevTools;
|
|
669
|
+
exports.createHttp = createHttp;
|
|
670
|
+
exports.createStore = createStore;
|
|
671
|
+
exports.debounced = debounced;
|
|
672
|
+
exports.devTools = devTools;
|
|
673
|
+
exports.fromStream = fromStream;
|
|
674
|
+
exports.http = http;
|
|
675
|
+
exports.optimistic = optimistic;
|
|
676
|
+
exports.retryable = retryable;
|
|
677
|
+
exports.throttled = throttled;
|
|
678
|
+
exports.withPersist = withPersist;
|
|
454
679
|
//# sourceMappingURL=index.js.map
|
|
455
680
|
//# sourceMappingURL=index.js.map
|