@okyrychenko-dev/react-action-guard 0.5.0 → 0.6.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 +147 -17
- package/dist/index.cjs +145 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +146 -36
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -154,10 +154,12 @@ Gets detailed information about all active blockers for a specific scope.
|
|
|
154
154
|
**BlockerInfo:**
|
|
155
155
|
|
|
156
156
|
- `id: string` - Unique identifier of the blocker
|
|
157
|
-
- `reason
|
|
158
|
-
- `priority: number` - Priority level (0
|
|
157
|
+
- `reason: string` - Reason for blocking (defaults to "Unknown")
|
|
158
|
+
- `priority: number` - Priority level (higher = higher priority, minimum value is 0)
|
|
159
159
|
- `scope: string | string[]` - Scope(s) being blocked
|
|
160
|
-
- `timestamp: number` - When the blocker was added
|
|
160
|
+
- `timestamp: number` - When the blocker was added (milliseconds since epoch)
|
|
161
|
+
- `timeout?: number` - Optional timeout duration in milliseconds
|
|
162
|
+
- `onTimeout?: (blockerId: string) => void` - Optional callback when timeout expires
|
|
161
163
|
|
|
162
164
|
**Example:**
|
|
163
165
|
|
|
@@ -433,22 +435,30 @@ Direct access to the Zustand store for advanced use cases (requires a selector).
|
|
|
433
435
|
**Methods:**
|
|
434
436
|
|
|
435
437
|
- `addBlocker(id, config)` - Manually add a blocker (re-adding with the same ID replaces config)
|
|
438
|
+
- `updateBlocker(id, config)` - Update blocker metadata (timeout restarts if new `timeout` value provided)
|
|
436
439
|
- `removeBlocker(id)` - Manually remove a blocker
|
|
437
440
|
- `isBlocked(scope)` - Check if scope is blocked
|
|
438
441
|
- `getBlockingInfo(scope)` - Get detailed blocking information
|
|
439
|
-
- `clearAllBlockers()` - Remove all blockers
|
|
440
|
-
- `clearBlockersForScope(scope)` - Remove blockers for specific scope
|
|
442
|
+
- `clearAllBlockers()` - Remove all blockers (emits `"clear"` middleware event)
|
|
443
|
+
- `clearBlockersForScope(scope)` - Remove blockers for specific scope (emits `"clear_scope"` middleware event)
|
|
441
444
|
- `registerMiddleware(name, middleware)` - Register middleware manually
|
|
442
445
|
- `unregisterMiddleware(name)` - Unregister middleware manually
|
|
443
446
|
|
|
447
|
+
**Note about `updateBlocker` and timeouts:**
|
|
448
|
+
- If you pass a **new** `timeout` value, the timer will be **restarted**
|
|
449
|
+
- If you **don't** pass `timeout`, the existing timer continues unchanged
|
|
450
|
+
- Set `timeout: 0` to **clear** an existing timeout
|
|
451
|
+
- `addBlocker` always resets/creates a new timeout timer when called with the same ID
|
|
452
|
+
|
|
444
453
|
**Example:**
|
|
445
454
|
|
|
446
455
|
```jsx
|
|
447
456
|
import { useUIBlockingStore } from "@okyrychenko-dev/react-action-guard";
|
|
448
457
|
|
|
449
458
|
function AdvancedComponent() {
|
|
450
|
-
const { addBlocker, removeBlocker } = useUIBlockingStore((state) => ({
|
|
459
|
+
const { addBlocker, updateBlocker, removeBlocker } = useUIBlockingStore((state) => ({
|
|
451
460
|
addBlocker: state.addBlocker,
|
|
461
|
+
updateBlocker: state.updateBlocker,
|
|
452
462
|
removeBlocker: state.removeBlocker,
|
|
453
463
|
}));
|
|
454
464
|
|
|
@@ -461,12 +471,13 @@ function AdvancedComponent() {
|
|
|
461
471
|
};
|
|
462
472
|
|
|
463
473
|
const updatePriority = () => {
|
|
464
|
-
//
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
474
|
+
// Update metadata - timeout continues if not changed
|
|
475
|
+
updateBlocker("custom-blocker", { priority: 200 });
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
const extendTimeout = () => {
|
|
479
|
+
// Update timeout - timer restarts with new value
|
|
480
|
+
updateBlocker("custom-blocker", { timeout: 60000 });
|
|
470
481
|
};
|
|
471
482
|
|
|
472
483
|
const stopBlocking = () => {
|
|
@@ -507,6 +518,30 @@ Advanced store helpers are re-exported from the internal toolkit for custom setu
|
|
|
507
518
|
|
|
508
519
|
The library includes a powerful middleware system that allows you to hook into blocker lifecycle events for analytics, logging, and performance monitoring.
|
|
509
520
|
|
|
521
|
+
### Middleware Actions
|
|
522
|
+
|
|
523
|
+
Middleware receives events for the following actions:
|
|
524
|
+
|
|
525
|
+
- `"add"` - Blocker was added
|
|
526
|
+
- `"update"` - Blocker metadata was updated
|
|
527
|
+
- `"remove"` - Blocker was removed
|
|
528
|
+
- `"timeout"` - Blocker was auto-removed due to timeout
|
|
529
|
+
- `"clear"` - All blockers were cleared (includes `count` field)
|
|
530
|
+
- `"clear_scope"` - Blockers for specific scope were cleared (includes `scope` and `count` fields)
|
|
531
|
+
|
|
532
|
+
**MiddlewareContext type:**
|
|
533
|
+
```typescript
|
|
534
|
+
{
|
|
535
|
+
action: "add" | "update" | "remove" | "timeout" | "clear" | "clear_scope";
|
|
536
|
+
blockerId: string;
|
|
537
|
+
config?: BlockerConfig;
|
|
538
|
+
timestamp: number;
|
|
539
|
+
prevState?: BlockerConfig; // Available for "update" and "remove"
|
|
540
|
+
scope?: string; // Available for "clear_scope"
|
|
541
|
+
count?: number; // Available for "clear" and "clear_scope"
|
|
542
|
+
}
|
|
543
|
+
```
|
|
544
|
+
|
|
510
545
|
### Built-in Middleware
|
|
511
546
|
|
|
512
547
|
#### Analytics Middleware
|
|
@@ -570,8 +605,6 @@ configureMiddleware([
|
|
|
570
605
|
|
|
571
606
|
Note: `configureMiddleware` registers middleware on the global store. If you use `UIBlockingProvider`, register middleware via the provider's `middlewares` prop instead.
|
|
572
607
|
|
|
573
|
-
Note: Middleware action types include `update` and `cancel`, but the store currently emits `add`, `remove`, and `timeout`.
|
|
574
|
-
|
|
575
608
|
### Custom Middleware
|
|
576
609
|
|
|
577
610
|
Create your own middleware to handle blocker events:
|
|
@@ -580,14 +613,20 @@ Create your own middleware to handle blocker events:
|
|
|
580
613
|
import { configureMiddleware } from "@okyrychenko-dev/react-action-guard";
|
|
581
614
|
|
|
582
615
|
const myCustomMiddleware = (context) => {
|
|
583
|
-
const { action, blockerId, config, timestamp } = context;
|
|
616
|
+
const { action, blockerId, config, timestamp, scope, count } = context;
|
|
584
617
|
|
|
585
618
|
if (action === "add") {
|
|
586
619
|
console.log(`Blocker added: ${blockerId}`, config);
|
|
587
|
-
} else if (action === "remove") {
|
|
588
|
-
console.log(`Blocker removed: ${blockerId}`);
|
|
589
620
|
} else if (action === "update") {
|
|
590
621
|
console.log(`Blocker updated: ${blockerId}`, config);
|
|
622
|
+
} else if (action === "remove") {
|
|
623
|
+
console.log(`Blocker removed: ${blockerId}`);
|
|
624
|
+
} else if (action === "timeout") {
|
|
625
|
+
console.log(`Blocker timed out: ${blockerId}`);
|
|
626
|
+
} else if (action === "clear") {
|
|
627
|
+
console.log(`All blockers cleared (${count} total)`);
|
|
628
|
+
} else if (action === "clear_scope") {
|
|
629
|
+
console.log(`Cleared ${count} blocker(s) for scope: ${scope}`);
|
|
591
630
|
}
|
|
592
631
|
};
|
|
593
632
|
|
|
@@ -887,6 +926,97 @@ function StorageQuotaGuard() {
|
|
|
887
926
|
}
|
|
888
927
|
```
|
|
889
928
|
|
|
929
|
+
### Clearing Blockers on Navigation
|
|
930
|
+
|
|
931
|
+
Clear blockers when navigating away or on specific events:
|
|
932
|
+
|
|
933
|
+
```jsx
|
|
934
|
+
import { useUIBlockingStore } from "@okyrychenko-dev/react-action-guard";
|
|
935
|
+
import { useEffect } from "react";
|
|
936
|
+
|
|
937
|
+
function CheckoutPage() {
|
|
938
|
+
const { clearBlockersForScope, clearAllBlockers } = useUIBlockingStore(
|
|
939
|
+
(state) => ({
|
|
940
|
+
clearBlockersForScope: state.clearBlockersForScope,
|
|
941
|
+
clearAllBlockers: state.clearAllBlockers,
|
|
942
|
+
})
|
|
943
|
+
);
|
|
944
|
+
|
|
945
|
+
// Clear checkout-specific blockers when leaving the page
|
|
946
|
+
useEffect(() => {
|
|
947
|
+
return () => {
|
|
948
|
+
// Clean up checkout blockers on unmount
|
|
949
|
+
clearBlockersForScope("checkout");
|
|
950
|
+
};
|
|
951
|
+
}, [clearBlockersForScope]);
|
|
952
|
+
|
|
953
|
+
const handleCancelOrder = () => {
|
|
954
|
+
// Clear all blockers when user explicitly cancels
|
|
955
|
+
clearAllBlockers();
|
|
956
|
+
navigate("/");
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
return (
|
|
960
|
+
<div>
|
|
961
|
+
<CheckoutForm />
|
|
962
|
+
<button onClick={handleCancelOrder}>Cancel Order</button>
|
|
963
|
+
</div>
|
|
964
|
+
);
|
|
965
|
+
}
|
|
966
|
+
```
|
|
967
|
+
|
|
968
|
+
### Managing Session Timeouts with Dynamic Updates
|
|
969
|
+
|
|
970
|
+
Extend or update blocker timeouts dynamically:
|
|
971
|
+
|
|
972
|
+
```jsx
|
|
973
|
+
import { useUIBlockingStore } from "@okyrychenko-dev/react-action-guard";
|
|
974
|
+
|
|
975
|
+
function SessionManager() {
|
|
976
|
+
const { addBlocker, updateBlocker, removeBlocker } = useUIBlockingStore(
|
|
977
|
+
(state) => ({
|
|
978
|
+
addBlocker: state.addBlocker,
|
|
979
|
+
updateBlocker: state.updateBlocker,
|
|
980
|
+
removeBlocker: state.removeBlocker,
|
|
981
|
+
})
|
|
982
|
+
);
|
|
983
|
+
|
|
984
|
+
const startSession = () => {
|
|
985
|
+
addBlocker("session-timeout", {
|
|
986
|
+
scope: "global",
|
|
987
|
+
reason: "Session expiring soon",
|
|
988
|
+
priority: 50,
|
|
989
|
+
timeout: 300000, // 5 minutes
|
|
990
|
+
onTimeout: () => {
|
|
991
|
+
logout();
|
|
992
|
+
showNotification("Session expired");
|
|
993
|
+
},
|
|
994
|
+
});
|
|
995
|
+
};
|
|
996
|
+
|
|
997
|
+
const extendSession = () => {
|
|
998
|
+
// Extend timeout - timer restarts with new value
|
|
999
|
+
updateBlocker("session-timeout", {
|
|
1000
|
+
timeout: 600000, // 10 minutes
|
|
1001
|
+
reason: "Session extended",
|
|
1002
|
+
});
|
|
1003
|
+
};
|
|
1004
|
+
|
|
1005
|
+
const endSession = () => {
|
|
1006
|
+
removeBlocker("session-timeout");
|
|
1007
|
+
logout();
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
return (
|
|
1011
|
+
<div>
|
|
1012
|
+
<button onClick={startSession}>Start Session</button>
|
|
1013
|
+
<button onClick={extendSession}>Extend Session</button>
|
|
1014
|
+
<button onClick={endSession}>Logout</button>
|
|
1015
|
+
</div>
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
```
|
|
1019
|
+
|
|
890
1020
|
## Development
|
|
891
1021
|
|
|
892
1022
|
```bash
|
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,16 @@ function normalizeScopeToArray(scope) {
|
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
// src/store/uiBlockingStore.actions.ts
|
|
27
|
+
var normalizePriority = (priority, fallback = DEFAULT_PRIORITY) => {
|
|
28
|
+
return priority !== void 0 ? Math.max(0, priority) : fallback;
|
|
29
|
+
};
|
|
30
|
+
var createMiddlewareContext = (action, blockerId, config, prevState) => ({
|
|
31
|
+
action,
|
|
32
|
+
blockerId,
|
|
33
|
+
config,
|
|
34
|
+
timestamp: Date.now(),
|
|
35
|
+
...prevState && { prevState }
|
|
36
|
+
});
|
|
27
37
|
var createUIBlockingActions = (set, get) => ({
|
|
28
38
|
// State
|
|
29
39
|
activeBlockers: /* @__PURE__ */ new Map(),
|
|
@@ -34,7 +44,6 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
34
44
|
newMiddlewares.set(name, middleware);
|
|
35
45
|
return { middlewares: newMiddlewares };
|
|
36
46
|
});
|
|
37
|
-
console.log(`[UIBlocking] Registered middleware: ${name}`);
|
|
38
47
|
},
|
|
39
48
|
unregisterMiddleware: (name) => {
|
|
40
49
|
set((state) => {
|
|
@@ -42,7 +51,6 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
42
51
|
newMiddlewares.delete(name);
|
|
43
52
|
return { middlewares: newMiddlewares };
|
|
44
53
|
});
|
|
45
|
-
console.log(`[UIBlocking] Unregistered middleware: ${name}`);
|
|
46
54
|
},
|
|
47
55
|
runMiddlewares: async (context) => {
|
|
48
56
|
const { middlewares } = get();
|
|
@@ -72,17 +80,14 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
72
80
|
timeoutId = setTimeout(() => {
|
|
73
81
|
if (get().activeBlockers.has(id)) {
|
|
74
82
|
config.onTimeout?.(id);
|
|
75
|
-
void get().runMiddlewares(
|
|
76
|
-
|
|
77
|
-
blockerId: id,
|
|
78
|
-
config: {
|
|
83
|
+
void get().runMiddlewares(
|
|
84
|
+
createMiddlewareContext("timeout", id, {
|
|
79
85
|
scope: config.scope,
|
|
80
86
|
reason: config.reason,
|
|
81
87
|
priority: config.priority,
|
|
82
88
|
timeout: config.timeout
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
});
|
|
89
|
+
})
|
|
90
|
+
);
|
|
86
91
|
get().removeBlocker(id);
|
|
87
92
|
}
|
|
88
93
|
}, config.timeout);
|
|
@@ -92,7 +97,7 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
92
97
|
const storedBlocker = {
|
|
93
98
|
scope: config.scope ?? DEFAULT_SCOPE,
|
|
94
99
|
reason: config.reason ?? DEFAULT_REASON,
|
|
95
|
-
priority: config.priority
|
|
100
|
+
priority: normalizePriority(config.priority),
|
|
96
101
|
timestamp: config.timestamp ?? Date.now(),
|
|
97
102
|
timeout: config.timeout,
|
|
98
103
|
timeoutId,
|
|
@@ -101,17 +106,92 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
101
106
|
newBlockers.set(id, storedBlocker);
|
|
102
107
|
return { activeBlockers: newBlockers };
|
|
103
108
|
});
|
|
104
|
-
void get().runMiddlewares(
|
|
105
|
-
|
|
106
|
-
blockerId: id,
|
|
107
|
-
config: {
|
|
109
|
+
void get().runMiddlewares(
|
|
110
|
+
createMiddlewareContext("add", id, {
|
|
108
111
|
scope: config.scope,
|
|
109
112
|
reason: config.reason,
|
|
110
113
|
priority: config.priority,
|
|
111
114
|
timeout: config.timeout
|
|
112
|
-
}
|
|
113
|
-
|
|
115
|
+
})
|
|
116
|
+
);
|
|
117
|
+
},
|
|
118
|
+
/**
|
|
119
|
+
* Update blocker metadata. If timeout is updated, the timer will be restarted.
|
|
120
|
+
*
|
|
121
|
+
* @param id - Unique blocker identifier
|
|
122
|
+
* @param config - Partial blocker configuration to merge
|
|
123
|
+
*
|
|
124
|
+
*/
|
|
125
|
+
updateBlocker: (id, config = {}) => {
|
|
126
|
+
const existingBlocker = get().activeBlockers.get(id);
|
|
127
|
+
if (!existingBlocker) {
|
|
128
|
+
get().addBlocker(id, config);
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
let timeoutId = existingBlocker.timeoutId;
|
|
132
|
+
const timeoutChanged = config.timeout !== void 0 && config.timeout !== existingBlocker.timeout;
|
|
133
|
+
if (timeoutChanged) {
|
|
134
|
+
if (existingBlocker.timeoutId) {
|
|
135
|
+
clearTimeout(existingBlocker.timeoutId);
|
|
136
|
+
}
|
|
137
|
+
if (config.timeout && config.timeout > 0) {
|
|
138
|
+
const newTimeout = config.timeout;
|
|
139
|
+
const newOnTimeout = config.onTimeout ?? existingBlocker.onTimeout;
|
|
140
|
+
timeoutId = setTimeout(() => {
|
|
141
|
+
if (get().activeBlockers.has(id)) {
|
|
142
|
+
newOnTimeout?.(id);
|
|
143
|
+
void get().runMiddlewares(
|
|
144
|
+
createMiddlewareContext("timeout", id, {
|
|
145
|
+
scope: config.scope ?? existingBlocker.scope,
|
|
146
|
+
reason: config.reason ?? existingBlocker.reason,
|
|
147
|
+
priority: config.priority ?? existingBlocker.priority,
|
|
148
|
+
timeout: newTimeout
|
|
149
|
+
})
|
|
150
|
+
);
|
|
151
|
+
get().removeBlocker(id);
|
|
152
|
+
}
|
|
153
|
+
}, newTimeout);
|
|
154
|
+
} else {
|
|
155
|
+
timeoutId = void 0;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const updatedBlocker = {
|
|
159
|
+
...existingBlocker,
|
|
160
|
+
scope: config.scope ?? existingBlocker.scope,
|
|
161
|
+
reason: config.reason ?? existingBlocker.reason,
|
|
162
|
+
priority: normalizePriority(config.priority, existingBlocker.priority),
|
|
163
|
+
timestamp: config.timestamp ?? existingBlocker.timestamp,
|
|
164
|
+
timeout: config.timeout ?? existingBlocker.timeout,
|
|
165
|
+
timeoutId,
|
|
166
|
+
onTimeout: config.onTimeout ?? existingBlocker.onTimeout
|
|
167
|
+
};
|
|
168
|
+
set((state) => {
|
|
169
|
+
const newBlockers = new Map(state.activeBlockers);
|
|
170
|
+
newBlockers.set(id, updatedBlocker);
|
|
171
|
+
return { activeBlockers: newBlockers };
|
|
114
172
|
});
|
|
173
|
+
void get().runMiddlewares(
|
|
174
|
+
createMiddlewareContext(
|
|
175
|
+
"update",
|
|
176
|
+
id,
|
|
177
|
+
{
|
|
178
|
+
scope: updatedBlocker.scope,
|
|
179
|
+
reason: updatedBlocker.reason,
|
|
180
|
+
priority: updatedBlocker.priority,
|
|
181
|
+
timeout: updatedBlocker.timeout,
|
|
182
|
+
onTimeout: updatedBlocker.onTimeout,
|
|
183
|
+
timestamp: updatedBlocker.timestamp
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
scope: existingBlocker.scope,
|
|
187
|
+
reason: existingBlocker.reason,
|
|
188
|
+
priority: existingBlocker.priority,
|
|
189
|
+
timeout: existingBlocker.timeout,
|
|
190
|
+
onTimeout: existingBlocker.onTimeout,
|
|
191
|
+
timestamp: existingBlocker.timestamp
|
|
192
|
+
}
|
|
193
|
+
)
|
|
194
|
+
);
|
|
115
195
|
},
|
|
116
196
|
/**
|
|
117
197
|
* Remove a blocker from the store
|
|
@@ -130,13 +210,7 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
130
210
|
return { activeBlockers: newBlockers };
|
|
131
211
|
});
|
|
132
212
|
if (prevBlocker) {
|
|
133
|
-
void get().runMiddlewares(
|
|
134
|
-
action: "remove",
|
|
135
|
-
blockerId: id,
|
|
136
|
-
config: prevBlocker,
|
|
137
|
-
timestamp: Date.now(),
|
|
138
|
-
prevState: prevBlocker
|
|
139
|
-
});
|
|
213
|
+
void get().runMiddlewares(createMiddlewareContext("remove", id, prevBlocker, prevBlocker));
|
|
140
214
|
}
|
|
141
215
|
},
|
|
142
216
|
/**
|
|
@@ -183,12 +257,21 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
183
257
|
*/
|
|
184
258
|
clearAllBlockers: () => {
|
|
185
259
|
const { activeBlockers } = get();
|
|
260
|
+
const count = activeBlockers.size;
|
|
186
261
|
for (const [, blocker] of activeBlockers) {
|
|
187
262
|
if (blocker.timeoutId) {
|
|
188
263
|
clearTimeout(blocker.timeoutId);
|
|
189
264
|
}
|
|
190
265
|
}
|
|
191
266
|
set({ activeBlockers: /* @__PURE__ */ new Map() });
|
|
267
|
+
if (count > 0) {
|
|
268
|
+
void get().runMiddlewares({
|
|
269
|
+
action: "clear",
|
|
270
|
+
blockerId: "*",
|
|
271
|
+
timestamp: Date.now(),
|
|
272
|
+
count
|
|
273
|
+
});
|
|
274
|
+
}
|
|
192
275
|
},
|
|
193
276
|
/**
|
|
194
277
|
* Clear all blockers for a specific scope
|
|
@@ -198,10 +281,14 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
198
281
|
*/
|
|
199
282
|
clearBlockersForScope: (scope) => {
|
|
200
283
|
const { activeBlockers } = get();
|
|
284
|
+
let count = 0;
|
|
201
285
|
for (const [, blocker] of activeBlockers) {
|
|
202
286
|
const blockerScopes = normalizeScopeToArray(blocker.scope);
|
|
203
|
-
if (blockerScopes.includes(scope)
|
|
204
|
-
|
|
287
|
+
if (blockerScopes.includes(scope)) {
|
|
288
|
+
if (blocker.timeoutId) {
|
|
289
|
+
clearTimeout(blocker.timeoutId);
|
|
290
|
+
}
|
|
291
|
+
count++;
|
|
205
292
|
}
|
|
206
293
|
}
|
|
207
294
|
set((state) => {
|
|
@@ -214,6 +301,15 @@ var createUIBlockingActions = (set, get) => ({
|
|
|
214
301
|
}
|
|
215
302
|
return { activeBlockers: newBlockers };
|
|
216
303
|
});
|
|
304
|
+
if (count > 0) {
|
|
305
|
+
void get().runMiddlewares({
|
|
306
|
+
action: "clear_scope",
|
|
307
|
+
blockerId: "*",
|
|
308
|
+
timestamp: Date.now(),
|
|
309
|
+
scope,
|
|
310
|
+
count
|
|
311
|
+
});
|
|
312
|
+
}
|
|
217
313
|
}
|
|
218
314
|
});
|
|
219
315
|
var {
|
|
@@ -273,9 +369,11 @@ var useAsyncAction = (actionId, scope, options) => {
|
|
|
273
369
|
addBlocker: state.addBlocker,
|
|
274
370
|
removeBlocker: state.removeBlocker
|
|
275
371
|
}));
|
|
372
|
+
const counterRef = react.useRef(0);
|
|
276
373
|
const executeWithBlocking = react.useCallback(
|
|
277
374
|
async (asyncFn) => {
|
|
278
|
-
|
|
375
|
+
counterRef.current += 1;
|
|
376
|
+
const blockerId = `${actionId}-${String(counterRef.current)}`;
|
|
279
377
|
try {
|
|
280
378
|
addBlocker(blockerId, {
|
|
281
379
|
scope,
|
|
@@ -610,14 +708,16 @@ var getActionEmoji = (action) => {
|
|
|
610
708
|
switch (action) {
|
|
611
709
|
case "add":
|
|
612
710
|
return "\u2795";
|
|
613
|
-
case "remove":
|
|
614
|
-
return "\u2796";
|
|
615
711
|
case "update":
|
|
616
712
|
return "\u{1F504}";
|
|
617
|
-
case "
|
|
618
|
-
return "\
|
|
713
|
+
case "remove":
|
|
714
|
+
return "\u2796";
|
|
619
715
|
case "timeout":
|
|
620
716
|
return "\u23F1\uFE0F";
|
|
717
|
+
case "clear":
|
|
718
|
+
return "\u{1F9F9}";
|
|
719
|
+
case "clear_scope":
|
|
720
|
+
return "\u{1F3AF}";
|
|
621
721
|
default:
|
|
622
722
|
return "\u2753";
|
|
623
723
|
}
|
|
@@ -638,13 +738,23 @@ var extractConfigDetails = (config) => {
|
|
|
638
738
|
};
|
|
639
739
|
var formatLogData = (context) => {
|
|
640
740
|
const configDetails = extractConfigDetails(context.config);
|
|
741
|
+
const logData = {};
|
|
742
|
+
if (context.scope !== void 0) {
|
|
743
|
+
logData.scope = context.scope;
|
|
744
|
+
}
|
|
745
|
+
if (context.count !== void 0) {
|
|
746
|
+
logData.count = context.count;
|
|
747
|
+
}
|
|
748
|
+
if (Object.keys(configDetails).length > 0) {
|
|
749
|
+
logData.config = configDetails;
|
|
750
|
+
}
|
|
641
751
|
if (context.prevState) {
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
752
|
+
logData.prevState = extractConfigDetails(context.prevState);
|
|
753
|
+
}
|
|
754
|
+
if (Object.keys(logData).length === 0) {
|
|
755
|
+
return configDetails;
|
|
646
756
|
}
|
|
647
|
-
return configDetails;
|
|
757
|
+
return Object.keys(logData).length === 1 && logData.config ? configDetails : logData;
|
|
648
758
|
};
|
|
649
759
|
|
|
650
760
|
// src/middleware/loggerMiddleware.ts
|