@buoy-gg/redux 7.0.35 → 7.0.38
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 +37 -9
- package/lib/commonjs/index.js +1 -256
- package/lib/commonjs/preset.js +1 -90
- package/lib/commonjs/redux/components/ReduxActionButton.js +1 -131
- package/lib/commonjs/redux/components/ReduxActionDetailContent.js +1 -437
- package/lib/commonjs/redux/components/ReduxActionDetailView.js +1 -401
- package/lib/commonjs/redux/components/ReduxActionInfoView.js +1 -836
- package/lib/commonjs/redux/components/ReduxActionItem.js +1 -334
- package/lib/commonjs/redux/components/ReduxAutoInstrument.js +1 -20
- package/lib/commonjs/redux/components/ReduxDetailViewToggle.js +1 -50
- package/lib/commonjs/redux/components/ReduxIcon.js +1 -18
- package/lib/commonjs/redux/components/ReduxModal.js +1 -703
- package/lib/commonjs/redux/hooks/useAutoInstrumentRedux.js +1 -187
- package/lib/commonjs/redux/hooks/useReduxActions.js +1 -58
- package/lib/commonjs/redux/sync/reduxSyncAdapter.js +1 -191
- package/lib/commonjs/redux/utils/activeStoreRegistry.js +1 -104
- package/lib/commonjs/redux/utils/autoInstrument.js +1 -231
- package/lib/commonjs/redux/utils/buoyReduxMiddleware.js +1 -202
- package/lib/commonjs/redux/utils/createReduxHistoryAdapter.js +1 -146
- package/lib/commonjs/redux/utils/devtoolsHook.js +1 -152
- package/lib/commonjs/redux/utils/reduxActionStore.js +1 -473
- package/lib/commonjs/redux/utils/snapshotProvider.js +1 -158
- package/lib/commonjs/redux/utils/testIDs.js +1 -75
- package/lib/module/index.js +1 -125
- package/lib/module/preset.js +1 -87
- package/lib/module/redux/components/ReduxActionButton.js +1 -128
- package/lib/module/redux/components/ReduxActionDetailContent.js +1 -433
- package/lib/module/redux/components/ReduxActionDetailView.js +1 -397
- package/lib/module/redux/components/ReduxActionInfoView.js +1 -831
- package/lib/module/redux/components/ReduxActionItem.js +1 -330
- package/lib/module/redux/components/ReduxAutoInstrument.js +1 -17
- package/lib/module/redux/components/ReduxDetailViewToggle.js +1 -45
- package/lib/module/redux/components/ReduxIcon.js +1 -8
- package/lib/module/redux/components/ReduxModal.js +1 -698
- package/lib/module/redux/hooks/useAutoInstrumentRedux.js +1 -183
- package/lib/module/redux/hooks/useReduxActions.js +1 -54
- package/lib/module/redux/sync/reduxSyncAdapter.js +1 -188
- package/lib/module/redux/utils/activeStoreRegistry.js +1 -92
- package/lib/module/redux/utils/autoInstrument.js +1 -201
- package/lib/module/redux/utils/buoyReduxMiddleware.js +1 -188
- package/lib/module/redux/utils/createReduxHistoryAdapter.js +1 -142
- package/lib/module/redux/utils/devtoolsHook.js +1 -145
- package/lib/module/redux/utils/reduxActionStore.js +1 -465
- package/lib/module/redux/utils/snapshotProvider.js +1 -157
- package/lib/module/redux/utils/testIDs.js +1 -68
- package/package.json +5 -5
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxActionButton.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxActionDetailContent.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxActionDetailView.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxActionInfoView.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxActionItem.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxAutoInstrument.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxDetailViewToggle.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxIcon.d.ts.map +0 -1
- package/lib/typescript/redux/components/ReduxModal.d.ts.map +0 -1
- package/lib/typescript/redux/hooks/useAutoInstrumentRedux.d.ts.map +0 -1
- package/lib/typescript/redux/hooks/useReduxActions.d.ts.map +0 -1
- package/lib/typescript/redux/sync/reduxSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/redux/types/index.d.ts.map +0 -1
- package/lib/typescript/redux/utils/activeStoreRegistry.d.ts.map +0 -1
- package/lib/typescript/redux/utils/autoInstrument.d.ts.map +0 -1
- package/lib/typescript/redux/utils/buoyReduxMiddleware.d.ts.map +0 -1
- package/lib/typescript/redux/utils/createReduxHistoryAdapter.d.ts.map +0 -1
- package/lib/typescript/redux/utils/devtoolsHook.d.ts.map +0 -1
- package/lib/typescript/redux/utils/reduxActionStore.d.ts.map +0 -1
- package/lib/typescript/redux/utils/snapshotProvider.d.ts.map +0 -1
- package/lib/typescript/redux/utils/testIDs.d.ts.map +0 -1
|
@@ -1,231 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.getActiveStore = getActiveStore;
|
|
7
|
-
Object.defineProperty(exports, "getInstrumentationStatus", {
|
|
8
|
-
enumerable: true,
|
|
9
|
-
get: function () {
|
|
10
|
-
return _activeStoreRegistry.getInstrumentationStatus;
|
|
11
|
-
}
|
|
12
|
-
});
|
|
13
|
-
exports.instrumentStore = instrumentStore;
|
|
14
|
-
exports.isAutoInstrumentActive = isAutoInstrumentActive;
|
|
15
|
-
exports.isStoreInstrumented = isStoreInstrumented;
|
|
16
|
-
Object.defineProperty(exports, "isTimeTravelAvailable", {
|
|
17
|
-
enumerable: true,
|
|
18
|
-
get: function () {
|
|
19
|
-
return _buoyReduxMiddleware.isTimeTravelAvailable;
|
|
20
|
-
}
|
|
21
|
-
});
|
|
22
|
-
Object.defineProperty(exports, "jumpToState", {
|
|
23
|
-
enumerable: true,
|
|
24
|
-
get: function () {
|
|
25
|
-
return _buoyReduxMiddleware.jumpToState;
|
|
26
|
-
}
|
|
27
|
-
});
|
|
28
|
-
exports.registerReduxStore = registerReduxStore;
|
|
29
|
-
Object.defineProperty(exports, "replayAction", {
|
|
30
|
-
enumerable: true,
|
|
31
|
-
get: function () {
|
|
32
|
-
return _buoyReduxMiddleware.replayAction;
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
exports.uninstrumentStore = uninstrumentStore;
|
|
36
|
-
var _reduxActionStore = require("./reduxActionStore");
|
|
37
|
-
var _buoyReduxMiddleware = require("./buoyReduxMiddleware");
|
|
38
|
-
var _activeStoreRegistry = require("./activeStoreRegistry");
|
|
39
|
-
/**
|
|
40
|
-
* Fallback auto-instrumentation for Redux stores.
|
|
41
|
-
*
|
|
42
|
-
* The PRIMARY capture path is the store-creation-time enhancer in
|
|
43
|
-
* devtoolsHook.ts (full capture, real time travel). This module is the
|
|
44
|
-
* fallback for stores created before our module loaded: it patches
|
|
45
|
-
* store.dispatch after the fact.
|
|
46
|
-
*
|
|
47
|
-
* Fallback limitation (inherent to patching, verified against redux 5.x):
|
|
48
|
-
* `middlewareAPI.dispatch` is a separate closure from `store.dispatch`, so
|
|
49
|
-
* actions dispatched from INSIDE middleware/thunks (RTK pending/fulfilled/
|
|
50
|
-
* rejected, RTK Query) bypass the patch. That's why this mechanism reports
|
|
51
|
-
* capture as "top-level-only" — see activeStoreRegistry.getInstrumentationStatus.
|
|
52
|
-
*/
|
|
53
|
-
|
|
54
|
-
// Re-exported for non-React callers (sync adapter, app code).
|
|
55
|
-
|
|
56
|
-
// ============================================
|
|
57
|
-
// Store Tracking
|
|
58
|
-
// ============================================
|
|
59
|
-
|
|
60
|
-
/** Symbol to mark stores that have been instrumented */
|
|
61
|
-
const INSTRUMENTED_SYMBOL = Symbol.for("@@buoy/instrumented");
|
|
62
|
-
|
|
63
|
-
/** Symbol to store original dispatch reference */
|
|
64
|
-
const ORIGINAL_DISPATCH_SYMBOL = Symbol.for("@@buoy/originalDispatch");
|
|
65
|
-
|
|
66
|
-
// ============================================
|
|
67
|
-
// Type Definitions
|
|
68
|
-
// ============================================
|
|
69
|
-
|
|
70
|
-
// ============================================
|
|
71
|
-
// Core Instrumentation
|
|
72
|
-
// ============================================
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Check if a store has already been instrumented (either mechanism)
|
|
76
|
-
*/
|
|
77
|
-
function isStoreInstrumented(store) {
|
|
78
|
-
const s = store;
|
|
79
|
-
return s[INSTRUMENTED_SYMBOL] === true || s[_activeStoreRegistry.ENHANCER_SYMBOL] === true;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
/**
|
|
83
|
-
* Instrument a Redux store for action capture (fallback path).
|
|
84
|
-
*
|
|
85
|
-
* Patches store.dispatch to capture top-level dispatches. No-ops (but still
|
|
86
|
-
* registers the store for getState/dispatch) when the enhancer or the
|
|
87
|
-
* explicit middleware is already capturing.
|
|
88
|
-
*
|
|
89
|
-
* @returns Cleanup function to restore original dispatch
|
|
90
|
-
*/
|
|
91
|
-
function instrumentStore(store, options = {}) {
|
|
92
|
-
const instrumentedStore = store;
|
|
93
|
-
|
|
94
|
-
// Store was created through the devtools-hook enhancer — full capture is
|
|
95
|
-
// already live; just (re)point the registry at it.
|
|
96
|
-
if (instrumentedStore[_activeStoreRegistry.ENHANCER_SYMBOL]) {
|
|
97
|
-
(0, _activeStoreRegistry.registerActiveStore)(store, "enhancer");
|
|
98
|
-
return () => {};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Skip if middleware is already handling action capture
|
|
102
|
-
if ((0, _buoyReduxMiddleware.isMiddlewareActive)()) {
|
|
103
|
-
(0, _activeStoreRegistry.registerActiveStore)(store, "middleware");
|
|
104
|
-
return () => {};
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Skip if already patched — update the registry even so (store swap case)
|
|
108
|
-
if (instrumentedStore[INSTRUMENTED_SYMBOL]) {
|
|
109
|
-
(0, _activeStoreRegistry.registerActiveStore)(store, "patch");
|
|
110
|
-
return () => {};
|
|
111
|
-
}
|
|
112
|
-
const {
|
|
113
|
-
maxActions = 200,
|
|
114
|
-
ignoreActions = []
|
|
115
|
-
} = options;
|
|
116
|
-
|
|
117
|
-
// Configure store
|
|
118
|
-
_reduxActionStore.reduxActionStore.setMaxActions(maxActions);
|
|
119
|
-
|
|
120
|
-
// Store original dispatch
|
|
121
|
-
const originalDispatch = store.dispatch.bind(store);
|
|
122
|
-
instrumentedStore[ORIGINAL_DISPATCH_SYMBOL] = originalDispatch;
|
|
123
|
-
|
|
124
|
-
// Create instrumented dispatch
|
|
125
|
-
const instrumentedDispatch = action => {
|
|
126
|
-
// Skip if action is not a plain object with a type property
|
|
127
|
-
// This filters out thunk functions, promises, and other non-action dispatches
|
|
128
|
-
if (typeof action !== "object" || action === null || typeof action.type !== "string") {
|
|
129
|
-
return originalDispatch(action);
|
|
130
|
-
}
|
|
131
|
-
const actionType = action.type;
|
|
132
|
-
|
|
133
|
-
// Don't record devtools internal actions
|
|
134
|
-
if (actionType.startsWith("@@buoy/")) {
|
|
135
|
-
return originalDispatch(action);
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
// Don't record Redux internal actions
|
|
139
|
-
if (actionType.startsWith("@@redux/")) {
|
|
140
|
-
return originalDispatch(action);
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// Check ignore list
|
|
144
|
-
if (ignoreActions.includes(actionType)) {
|
|
145
|
-
return originalDispatch(action);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Capture timing and state
|
|
149
|
-
const startTime = performance.now();
|
|
150
|
-
const prevState = store.getState();
|
|
151
|
-
const result = originalDispatch(action);
|
|
152
|
-
const nextState = store.getState();
|
|
153
|
-
const duration = performance.now() - startTime;
|
|
154
|
-
|
|
155
|
-
// Record the action
|
|
156
|
-
_reduxActionStore.reduxActionStore.addAction(action, prevState, nextState, duration);
|
|
157
|
-
return result;
|
|
158
|
-
};
|
|
159
|
-
|
|
160
|
-
// Replace dispatch
|
|
161
|
-
store.dispatch = instrumentedDispatch;
|
|
162
|
-
instrumentedStore[INSTRUMENTED_SYMBOL] = true;
|
|
163
|
-
(0, _activeStoreRegistry.registerActiveStore)(store, "patch");
|
|
164
|
-
|
|
165
|
-
// Return cleanup function
|
|
166
|
-
return () => {
|
|
167
|
-
uninstrumentStore(store);
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Remove dispatch-patch instrumentation from a store.
|
|
173
|
-
*
|
|
174
|
-
* Only restores the patched dispatch. (This used to also replaceReducer with a
|
|
175
|
-
* synthetic reducer that froze the host store permanently — that path is gone.)
|
|
176
|
-
* Enhancer-created stores are left untouched apart from the registry.
|
|
177
|
-
*/
|
|
178
|
-
function uninstrumentStore(store) {
|
|
179
|
-
const instrumentedStore = store;
|
|
180
|
-
if (instrumentedStore[INSTRUMENTED_SYMBOL]) {
|
|
181
|
-
const originalDispatch = instrumentedStore[ORIGINAL_DISPATCH_SYMBOL];
|
|
182
|
-
if (originalDispatch) {
|
|
183
|
-
store.dispatch = originalDispatch;
|
|
184
|
-
}
|
|
185
|
-
delete instrumentedStore[INSTRUMENTED_SYMBOL];
|
|
186
|
-
delete instrumentedStore[ORIGINAL_DISPATCH_SYMBOL];
|
|
187
|
-
}
|
|
188
|
-
(0, _activeStoreRegistry.unregisterActiveStore)(store);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/**
|
|
192
|
-
* Manually register a store with Buoy — the escape hatch for apps that can't
|
|
193
|
-
* render FloatingDevTools inside a react-redux Provider (or don't use
|
|
194
|
-
* react-redux at all). Instruments via the fallback dispatch patch.
|
|
195
|
-
*
|
|
196
|
-
* Prefer the zero-config paths; this exists so no app is ever stuck.
|
|
197
|
-
*/
|
|
198
|
-
function registerReduxStore(store, options = {}) {
|
|
199
|
-
return instrumentStore(store, options);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// ============================================
|
|
203
|
-
// Time-Travel / Introspection
|
|
204
|
-
// ============================================
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Time travel lives in buoyReduxMiddleware.ts and is re-exported here.
|
|
208
|
-
*
|
|
209
|
-
* It used to be reimplemented in this file, and the two copies drifted: this
|
|
210
|
-
* one learned to notice that a jump had been ignored, the one the modal's JUMP
|
|
211
|
-
* button actually calls never did. So the detection existed and no user could
|
|
212
|
-
* ever have seen it. One implementation, one behaviour.
|
|
213
|
-
*/
|
|
214
|
-
|
|
215
|
-
/**
|
|
216
|
-
* Get the currently active (instrumented) store.
|
|
217
|
-
*
|
|
218
|
-
* NOTE: on the middleware path this is the middleware `storeApi`
|
|
219
|
-
* ({getState, dispatch}) rather than the full Store object — every consumer
|
|
220
|
-
* in this package only needs those two.
|
|
221
|
-
*/
|
|
222
|
-
function getActiveStore() {
|
|
223
|
-
return (0, _activeStoreRegistry.getActiveStore)();
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
/**
|
|
227
|
-
* Check if auto-instrumentation is active
|
|
228
|
-
*/
|
|
229
|
-
function isAutoInstrumentActive() {
|
|
230
|
-
return (0, _activeStoreRegistry.getActiveStore)() !== null;
|
|
231
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.getActiveStore=getActiveStore,Object.defineProperty(exports,"getInstrumentationStatus",{enumerable:!0,get:function(){return _activeStoreRegistry.getInstrumentationStatus}}),exports.instrumentStore=instrumentStore,exports.isAutoInstrumentActive=isAutoInstrumentActive,exports.isStoreInstrumented=isStoreInstrumented,Object.defineProperty(exports,"isTimeTravelAvailable",{enumerable:!0,get:function(){return _buoyReduxMiddleware.isTimeTravelAvailable}}),Object.defineProperty(exports,"jumpToState",{enumerable:!0,get:function(){return _buoyReduxMiddleware.jumpToState}}),exports.registerReduxStore=registerReduxStore,Object.defineProperty(exports,"replayAction",{enumerable:!0,get:function(){return _buoyReduxMiddleware.replayAction}}),exports.uninstrumentStore=uninstrumentStore;var _reduxActionStore=require("./reduxActionStore"),_buoyReduxMiddleware=require("./buoyReduxMiddleware"),_activeStoreRegistry=require("./activeStoreRegistry");const INSTRUMENTED_SYMBOL=Symbol.for("@@buoy/instrumented"),ORIGINAL_DISPATCH_SYMBOL=Symbol.for("@@buoy/originalDispatch");function isStoreInstrumented(e){const t=e;return!0===t[INSTRUMENTED_SYMBOL]||!0===t[_activeStoreRegistry.ENHANCER_SYMBOL]}function instrumentStore(e,t={}){const r=e;if(r[_activeStoreRegistry.ENHANCER_SYMBOL])return(0,_activeStoreRegistry.registerActiveStore)(e,"enhancer"),()=>{};if((0,_buoyReduxMiddleware.isMiddlewareActive)())return(0,_activeStoreRegistry.registerActiveStore)(e,"middleware"),()=>{};if(r[INSTRUMENTED_SYMBOL])return(0,_activeStoreRegistry.registerActiveStore)(e,"patch"),()=>{};const{maxActions:i=200,ignoreActions:n=[]}=t;_reduxActionStore.reduxActionStore.setMaxActions(i);const o=e.dispatch.bind(e);return r[ORIGINAL_DISPATCH_SYMBOL]=o,e.dispatch=t=>{if("object"!=typeof t||null===t||"string"!=typeof t.type)return o(t);const r=t.type;if(r.startsWith("@@buoy/"))return o(t);if(r.startsWith("@@redux/"))return o(t);if(n.includes(r))return o(t);const i=performance.now(),u=e.getState(),s=o(t),c=e.getState(),S=performance.now()-i;return _reduxActionStore.reduxActionStore.addAction(t,u,c,S),s},r[INSTRUMENTED_SYMBOL]=!0,(0,_activeStoreRegistry.registerActiveStore)(e,"patch"),()=>{uninstrumentStore(e)}}function uninstrumentStore(e){const t=e;if(t[INSTRUMENTED_SYMBOL]){const r=t[ORIGINAL_DISPATCH_SYMBOL];r&&(e.dispatch=r),delete t[INSTRUMENTED_SYMBOL],delete t[ORIGINAL_DISPATCH_SYMBOL]}(0,_activeStoreRegistry.unregisterActiveStore)(e)}function registerReduxStore(e,t={}){return instrumentStore(e,t)}function getActiveStore(){return(0,_activeStoreRegistry.getActiveStore)()}function isAutoInstrumentActive(){return null!==(0,_activeStoreRegistry.getActiveStore)()}
|
|
@@ -1,202 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.buoyReduxMiddleware = exports.BUOY_REPLAY_ACTION = exports.BUOY_JUMP_TO_STATE = void 0;
|
|
7
|
-
exports.createBuoyReduxMiddleware = createBuoyReduxMiddleware;
|
|
8
|
-
exports.isMiddlewareActive = isMiddlewareActive;
|
|
9
|
-
Object.defineProperty(exports, "isTimeTravelAvailable", {
|
|
10
|
-
enumerable: true,
|
|
11
|
-
get: function () {
|
|
12
|
-
return _activeStoreRegistry.isTimeTravelAvailable;
|
|
13
|
-
}
|
|
14
|
-
});
|
|
15
|
-
exports.jumpToState = jumpToState;
|
|
16
|
-
exports.replayAction = replayAction;
|
|
17
|
-
exports.withBuoyDevTools = withBuoyDevTools;
|
|
18
|
-
var _reduxActionStore = require("./reduxActionStore");
|
|
19
|
-
var _activeStoreRegistry = require("./activeStoreRegistry");
|
|
20
|
-
/**
|
|
21
|
-
* Buoy Redux Middleware for Redux Toolkit
|
|
22
|
-
*
|
|
23
|
-
* @example
|
|
24
|
-
* ```tsx
|
|
25
|
-
* import { configureStore } from '@reduxjs/toolkit';
|
|
26
|
-
* import { buoyReduxMiddleware, withBuoyDevTools } from '@buoy-gg/redux';
|
|
27
|
-
*
|
|
28
|
-
* const store = configureStore({
|
|
29
|
-
* reducer: withBuoyDevTools(rootReducer), // Enable time-travel
|
|
30
|
-
* middleware: (getDefaultMiddleware) =>
|
|
31
|
-
* getDefaultMiddleware().concat(buoyReduxMiddleware),
|
|
32
|
-
* });
|
|
33
|
-
* ```
|
|
34
|
-
*/
|
|
35
|
-
|
|
36
|
-
// ============================================
|
|
37
|
-
// Middleware Active Tracking
|
|
38
|
-
// ============================================
|
|
39
|
-
|
|
40
|
-
/** Flag to indicate middleware is handling action capture */
|
|
41
|
-
let middlewareActive = false;
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Check if the explicit middleware is active
|
|
45
|
-
* Used by auto-instrument to avoid duplicate capture
|
|
46
|
-
*/
|
|
47
|
-
function isMiddlewareActive() {
|
|
48
|
-
return middlewareActive;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// ============================================
|
|
52
|
-
// Time-Travel Action Types
|
|
53
|
-
// ============================================
|
|
54
|
-
|
|
55
|
-
const BUOY_JUMP_TO_STATE = exports.BUOY_JUMP_TO_STATE = "@@buoy/JUMP_TO_STATE";
|
|
56
|
-
const BUOY_REPLAY_ACTION = exports.BUOY_REPLAY_ACTION = "@@buoy/REPLAY_ACTION";
|
|
57
|
-
/**
|
|
58
|
-
* Jump to a specific state (time-travel).
|
|
59
|
-
*
|
|
60
|
-
* Registry-backed, so it reaches the store on every capture path — but
|
|
61
|
-
* REACHING the store is not the same as being able to jump, and conflating the
|
|
62
|
-
* two is what made this fail invisibly. A jump is an action like any other: it
|
|
63
|
-
* only does something if a reducer handles it, and the only two things that
|
|
64
|
-
* install such a reducer are the devtools-hook enhancer and `withBuoyDevTools`.
|
|
65
|
-
* An app that captures through `buoyReduxMiddleware` alone dispatches the jump
|
|
66
|
-
* into a store that has never heard of it, gets its own state back, and shows
|
|
67
|
-
* a screen that does not move — with no error, because nothing went wrong.
|
|
68
|
-
*
|
|
69
|
-
* So the capability is checked up front and refused out loud. The UI asks the
|
|
70
|
-
* same question (`isTimeTravelAvailable`) and disables the button, which is the
|
|
71
|
-
* half a warning cannot do.
|
|
72
|
-
*/
|
|
73
|
-
function jumpToState(state) {
|
|
74
|
-
if ((0, _reduxActionStore.isEvictedState)(state)) {
|
|
75
|
-
console.warn("[BuoyRedux] Cannot jump - this action's state was evicted (raw state is retained for recent actions only)");
|
|
76
|
-
return;
|
|
77
|
-
}
|
|
78
|
-
const store = (0, _activeStoreRegistry.getActiveStore)();
|
|
79
|
-
if (!store) {
|
|
80
|
-
console.warn("[BuoyRedux] Cannot jump to state - no store instrumented");
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
|
-
if (!(0, _activeStoreRegistry.isTimeTravelAvailable)()) {
|
|
84
|
-
console.warn("[BuoyRedux] Cannot jump to state - the root reducer cannot serve a " + "state jump. Capture and time travel are wired separately: either put " + "`import '@buoy-gg/redux';` first in your app entry (so Buoy is the " + "store enhancer), or wrap your root reducer with withBuoyDevTools().");
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
store.dispatch({
|
|
88
|
-
type: BUOY_JUMP_TO_STATE,
|
|
89
|
-
payload: state
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Whether the JUMP affordance can do anything in this app. Re-exported from
|
|
95
|
-
* the registry so hosts have one import for the whole time-travel surface.
|
|
96
|
-
*/
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Replay an action (dispatch it again)
|
|
100
|
-
*/
|
|
101
|
-
function replayAction(action) {
|
|
102
|
-
const store = (0, _activeStoreRegistry.getActiveStore)();
|
|
103
|
-
if (store) {
|
|
104
|
-
store.dispatch(action);
|
|
105
|
-
} else {
|
|
106
|
-
console.warn("[BuoyRedux] Cannot replay action - no store instrumented");
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
/**
|
|
111
|
-
* Wrap your root reducer to enable time-travel support
|
|
112
|
-
*
|
|
113
|
-
* @example
|
|
114
|
-
* ```tsx
|
|
115
|
-
* const store = configureStore({
|
|
116
|
-
* reducer: withBuoyDevTools(rootReducer),
|
|
117
|
-
* middleware: (getDefault) => getDefault().concat(buoyReduxMiddleware),
|
|
118
|
-
* });
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
function withBuoyDevTools(reducer) {
|
|
122
|
-
// The other half of the time-travel wiring (see jumpToState): this is one of
|
|
123
|
-
// exactly two places that can answer BUOY_JUMP_TO_STATE.
|
|
124
|
-
(0, _activeStoreRegistry.markTimeTravelReducer)();
|
|
125
|
-
return (state, action) => {
|
|
126
|
-
// Handle jump to state action
|
|
127
|
-
if (action.type === BUOY_JUMP_TO_STATE) {
|
|
128
|
-
const jumpAction = action;
|
|
129
|
-
return jumpAction.payload;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// Pass through to original reducer
|
|
133
|
-
return reducer(state, action);
|
|
134
|
-
};
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Default middleware - just add to your store!
|
|
139
|
-
*/
|
|
140
|
-
const buoyReduxMiddleware = storeApi => {
|
|
141
|
-
// Mark middleware as active so auto-instrument knows to skip
|
|
142
|
-
middlewareActive = true;
|
|
143
|
-
|
|
144
|
-
// Register as the active store so getState/dispatch (MCP, desktop, time
|
|
145
|
-
// travel) work on the middleware path too — storeApi has both getState and
|
|
146
|
-
// dispatch, which is all the registry needs.
|
|
147
|
-
(0, _activeStoreRegistry.registerActiveStore)(storeApi, "middleware");
|
|
148
|
-
return next => action => {
|
|
149
|
-
const actionObj = action;
|
|
150
|
-
const actionType = actionObj.type;
|
|
151
|
-
|
|
152
|
-
// Don't record devtools internal actions
|
|
153
|
-
if (actionType?.startsWith("@@buoy/")) {
|
|
154
|
-
return next(action);
|
|
155
|
-
}
|
|
156
|
-
const startTime = performance.now();
|
|
157
|
-
const prevState = storeApi.getState();
|
|
158
|
-
const result = next(action);
|
|
159
|
-
const nextState = storeApi.getState();
|
|
160
|
-
const duration = performance.now() - startTime;
|
|
161
|
-
_reduxActionStore.reduxActionStore.addAction(actionObj, prevState, nextState, duration);
|
|
162
|
-
return result;
|
|
163
|
-
};
|
|
164
|
-
};
|
|
165
|
-
|
|
166
|
-
/**
|
|
167
|
-
* Create middleware with custom options
|
|
168
|
-
*/
|
|
169
|
-
exports.buoyReduxMiddleware = buoyReduxMiddleware;
|
|
170
|
-
function createBuoyReduxMiddleware(options = {}) {
|
|
171
|
-
const {
|
|
172
|
-
maxActions = 200,
|
|
173
|
-
ignoreActions = []
|
|
174
|
-
} = options;
|
|
175
|
-
_reduxActionStore.reduxActionStore.setMaxActions(maxActions);
|
|
176
|
-
return storeApi => {
|
|
177
|
-
// Mark middleware as active so auto-instrument knows to skip
|
|
178
|
-
middlewareActive = true;
|
|
179
|
-
|
|
180
|
-
// Register as the active store (see buoyReduxMiddleware above).
|
|
181
|
-
(0, _activeStoreRegistry.registerActiveStore)(storeApi, "middleware");
|
|
182
|
-
return next => action => {
|
|
183
|
-
const actionObj = action;
|
|
184
|
-
const actionType = actionObj.type || "";
|
|
185
|
-
|
|
186
|
-
// Don't record devtools internal actions
|
|
187
|
-
if (actionType?.startsWith("@@buoy/")) {
|
|
188
|
-
return next(action);
|
|
189
|
-
}
|
|
190
|
-
if (ignoreActions.includes(actionType)) {
|
|
191
|
-
return next(action);
|
|
192
|
-
}
|
|
193
|
-
const startTime = performance.now();
|
|
194
|
-
const prevState = storeApi.getState();
|
|
195
|
-
const result = next(action);
|
|
196
|
-
const nextState = storeApi.getState();
|
|
197
|
-
const duration = performance.now() - startTime;
|
|
198
|
-
_reduxActionStore.reduxActionStore.addAction(actionObj, prevState, nextState, duration);
|
|
199
|
-
return result;
|
|
200
|
-
};
|
|
201
|
-
};
|
|
202
|
-
}
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.buoyReduxMiddleware=exports.BUOY_REPLAY_ACTION=exports.BUOY_JUMP_TO_STATE=void 0,exports.createBuoyReduxMiddleware=createBuoyReduxMiddleware,exports.isMiddlewareActive=isMiddlewareActive,Object.defineProperty(exports,"isTimeTravelAvailable",{enumerable:!0,get:function(){return _activeStoreRegistry.isTimeTravelAvailable}}),exports.jumpToState=jumpToState,exports.replayAction=replayAction,exports.withBuoyDevTools=withBuoyDevTools;var _reduxActionStore=require("./reduxActionStore"),_activeStoreRegistry=require("./activeStoreRegistry");let middlewareActive=!1;function isMiddlewareActive(){return middlewareActive}const BUOY_JUMP_TO_STATE=exports.BUOY_JUMP_TO_STATE="@@buoy/JUMP_TO_STATE",BUOY_REPLAY_ACTION=exports.BUOY_REPLAY_ACTION="@@buoy/REPLAY_ACTION";function jumpToState(e){if((0,_reduxActionStore.isEvictedState)(e))return void console.warn("[BuoyRedux] Cannot jump - this action's state was evicted (raw state is retained for recent actions only)");const t=(0,_activeStoreRegistry.getActiveStore)();t?(0,_activeStoreRegistry.isTimeTravelAvailable)()?t.dispatch({type:BUOY_JUMP_TO_STATE,payload:e}):console.warn("[BuoyRedux] Cannot jump to state - the root reducer cannot serve a state jump. Capture and time travel are wired separately: either put `import '@buoy-gg/redux';` first in your app entry (so Buoy is the store enhancer), or wrap your root reducer with withBuoyDevTools()."):console.warn("[BuoyRedux] Cannot jump to state - no store instrumented")}function replayAction(e){const t=(0,_activeStoreRegistry.getActiveStore)();t?t.dispatch(e):console.warn("[BuoyRedux] Cannot replay action - no store instrumented")}function withBuoyDevTools(e){return(0,_activeStoreRegistry.markTimeTravelReducer)(),(t,r)=>r.type===BUOY_JUMP_TO_STATE?r.payload:e(t,r)}const buoyReduxMiddleware=e=>(middlewareActive=!0,(0,_activeStoreRegistry.registerActiveStore)(e,"middleware"),t=>r=>{const o=r,i=o.type;if(i?.startsWith("@@buoy/"))return t(r);const a=performance.now(),n=e.getState(),s=t(r),u=e.getState(),c=performance.now()-a;return _reduxActionStore.reduxActionStore.addAction(o,n,u,c),s});function createBuoyReduxMiddleware(e={}){const{maxActions:t=200,ignoreActions:r=[]}=e;return _reduxActionStore.reduxActionStore.setMaxActions(t),e=>(middlewareActive=!0,(0,_activeStoreRegistry.registerActiveStore)(e,"middleware"),t=>o=>{const i=o,a=i.type||"";if(a?.startsWith("@@buoy/"))return t(o);if(r.includes(a))return t(o);const n=performance.now(),s=e.getState(),u=t(o),c=e.getState(),d=performance.now()-n;return _reduxActionStore.reduxActionStore.addAction(i,s,c,d),u})}exports.buoyReduxMiddleware=buoyReduxMiddleware;
|
|
@@ -1,146 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.createReduxHistoryAdapter = createReduxHistoryAdapter;
|
|
7
|
-
exports.reduxHistoryAdapter = void 0;
|
|
8
|
-
var _reduxActionStore = require("./reduxActionStore");
|
|
9
|
-
var _ReduxIcon = require("../components/ReduxIcon");
|
|
10
|
-
/**
|
|
11
|
-
* Redux History Adapter
|
|
12
|
-
*
|
|
13
|
-
* Wraps the existing reduxActionStore to implement the universal HistoryAdapter interface.
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Redux adapter capabilities
|
|
18
|
-
* Note: Full time-travel requires the instrument() pattern from redux-devtools.
|
|
19
|
-
* This adapter provides history viewing with basic navigation.
|
|
20
|
-
*/
|
|
21
|
-
const REDUX_CAPABILITIES = {
|
|
22
|
-
timeTravel: false,
|
|
23
|
-
// Would need instrument() for true time travel
|
|
24
|
-
toggle: false,
|
|
25
|
-
// Would need instrument() for skip/toggle
|
|
26
|
-
edit: false,
|
|
27
|
-
diff: true,
|
|
28
|
-
// We have prevState/nextState
|
|
29
|
-
export: true,
|
|
30
|
-
import: false,
|
|
31
|
-
reset: true,
|
|
32
|
-
recording: true
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Convert ReduxAction to HistoryEntry
|
|
37
|
-
*/
|
|
38
|
-
function toHistoryEntry(action, index, _total) {
|
|
39
|
-
return {
|
|
40
|
-
id: action.id,
|
|
41
|
-
label: action.type,
|
|
42
|
-
timestamp: action.timestamp,
|
|
43
|
-
data: action.payload ?? action.action,
|
|
44
|
-
prevState: action.prevState,
|
|
45
|
-
nextState: action.nextState,
|
|
46
|
-
hasStateChange: action.hasStateChange,
|
|
47
|
-
duration: action.duration,
|
|
48
|
-
source: "redux",
|
|
49
|
-
isCurrent: index === 0,
|
|
50
|
-
// Most recent is current
|
|
51
|
-
isInFuture: false,
|
|
52
|
-
isSkipped: false,
|
|
53
|
-
meta: {
|
|
54
|
-
fullAction: action.action
|
|
55
|
-
}
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Options for creating a Redux history adapter
|
|
61
|
-
*/
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Create a Redux history adapter
|
|
65
|
-
*
|
|
66
|
-
* @param options - Optional configuration
|
|
67
|
-
* @returns HistoryAdapter instance
|
|
68
|
-
*/
|
|
69
|
-
function createReduxHistoryAdapter(options) {
|
|
70
|
-
const {
|
|
71
|
-
icon = _ReduxIcon.ReduxIcon,
|
|
72
|
-
color = "#764ABC",
|
|
73
|
-
// Redux purple
|
|
74
|
-
name = "Redux"
|
|
75
|
-
} = options ?? {};
|
|
76
|
-
let currentIndex = 0;
|
|
77
|
-
const adapter = {
|
|
78
|
-
// === Identity ===
|
|
79
|
-
id: "redux",
|
|
80
|
-
name,
|
|
81
|
-
icon,
|
|
82
|
-
color,
|
|
83
|
-
capabilities: REDUX_CAPABILITIES,
|
|
84
|
-
// === Subscription ===
|
|
85
|
-
subscribe: callback => {
|
|
86
|
-
return _reduxActionStore.reduxActionStore.subscribe(() => {
|
|
87
|
-
callback();
|
|
88
|
-
});
|
|
89
|
-
},
|
|
90
|
-
// === Data Access ===
|
|
91
|
-
getEntries: () => {
|
|
92
|
-
const actions = _reduxActionStore.reduxActionStore.getActions();
|
|
93
|
-
return actions.map((action, index) => toHistoryEntry(action, index, actions.length));
|
|
94
|
-
},
|
|
95
|
-
getEntryCount: () => {
|
|
96
|
-
return _reduxActionStore.reduxActionStore.getActions().length;
|
|
97
|
-
},
|
|
98
|
-
getCurrentState: () => {
|
|
99
|
-
const actions = _reduxActionStore.reduxActionStore.getActions();
|
|
100
|
-
if (actions.length === 0) return undefined;
|
|
101
|
-
// Most recent action's nextState is current state
|
|
102
|
-
return actions[0].nextState;
|
|
103
|
-
},
|
|
104
|
-
getStateAtEntry: entryId => {
|
|
105
|
-
const action = _reduxActionStore.reduxActionStore.getActionById(String(entryId));
|
|
106
|
-
return action?.nextState;
|
|
107
|
-
},
|
|
108
|
-
// === Navigation ===
|
|
109
|
-
get currentIndex() {
|
|
110
|
-
return currentIndex;
|
|
111
|
-
},
|
|
112
|
-
jumpTo: entryId => {
|
|
113
|
-
const actions = _reduxActionStore.reduxActionStore.getActions();
|
|
114
|
-
const index = actions.findIndex(a => a.id === String(entryId));
|
|
115
|
-
if (index !== -1) {
|
|
116
|
-
currentIndex = index;
|
|
117
|
-
// Note: This doesn't actually change app state without instrument()
|
|
118
|
-
// It just updates which entry is "selected" for viewing
|
|
119
|
-
}
|
|
120
|
-
},
|
|
121
|
-
// === Recording ===
|
|
122
|
-
get isRecording() {
|
|
123
|
-
return _reduxActionStore.reduxActionStore.getEnabled();
|
|
124
|
-
},
|
|
125
|
-
setRecording: enabled => {
|
|
126
|
-
_reduxActionStore.reduxActionStore.setEnabled(enabled);
|
|
127
|
-
},
|
|
128
|
-
// === Reset ===
|
|
129
|
-
reset: () => {
|
|
130
|
-
_reduxActionStore.reduxActionStore.clearActions();
|
|
131
|
-
currentIndex = 0;
|
|
132
|
-
},
|
|
133
|
-
// === Export ===
|
|
134
|
-
exportHistory: () => {
|
|
135
|
-
const actions = _reduxActionStore.reduxActionStore.getActions();
|
|
136
|
-
return JSON.stringify(actions, null, 2);
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
return adapter;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Default Redux adapter instance
|
|
144
|
-
* Use this if you only have one Redux store
|
|
145
|
-
*/
|
|
146
|
-
const reduxHistoryAdapter = exports.reduxHistoryAdapter = createReduxHistoryAdapter();
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.createReduxHistoryAdapter=createReduxHistoryAdapter,exports.reduxHistoryAdapter=void 0;var _reduxActionStore=require("./reduxActionStore"),_ReduxIcon=require("../components/ReduxIcon");const REDUX_CAPABILITIES={timeTravel:!1,toggle:!1,edit:!1,diff:!0,export:!0,import:!1,reset:!0,recording:!0};function toHistoryEntry(t,e,r){return{id:t.id,label:t.type,timestamp:t.timestamp,data:t.payload??t.action,prevState:t.prevState,nextState:t.nextState,hasStateChange:t.hasStateChange,duration:t.duration,source:"redux",isCurrent:0===e,isInFuture:!1,isSkipped:!1,meta:{fullAction:t.action}}}function createReduxHistoryAdapter(t){const{icon:e=_ReduxIcon.ReduxIcon,color:r="#764ABC",name:o="Redux"}=t??{};let n=0;return{id:"redux",name:o,icon:e,color:r,capabilities:REDUX_CAPABILITIES,subscribe:t=>_reduxActionStore.reduxActionStore.subscribe(()=>{t()}),getEntries:()=>{const t=_reduxActionStore.reduxActionStore.getActions();return t.map((e,r)=>toHistoryEntry(e,r,t.length))},getEntryCount:()=>_reduxActionStore.reduxActionStore.getActions().length,getCurrentState:()=>{const t=_reduxActionStore.reduxActionStore.getActions();if(0!==t.length)return t[0].nextState},getStateAtEntry:t=>{const e=_reduxActionStore.reduxActionStore.getActionById(String(t));return e?.nextState},get currentIndex(){return n},jumpTo:t=>{const e=_reduxActionStore.reduxActionStore.getActions().findIndex(e=>e.id===String(t));-1!==e&&(n=e)},get isRecording(){return _reduxActionStore.reduxActionStore.getEnabled()},setRecording:t=>{_reduxActionStore.reduxActionStore.setEnabled(t)},reset:()=>{_reduxActionStore.reduxActionStore.clearActions(),n=0},exportHistory:()=>{const t=_reduxActionStore.reduxActionStore.getActions();return JSON.stringify(t,null,2)}}}const reduxHistoryAdapter=exports.reduxHistoryAdapter=createReduxHistoryAdapter();
|