@buoy-gg/events 2.1.2 → 2.1.3
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/lib/commonjs/components/EventsCopySettingsView.js +39 -8
- package/lib/commonjs/components/UnifiedEventDetail.js +32 -1
- package/lib/commonjs/components/UnifiedEventFilters.js +50 -21
- package/lib/commonjs/components/UnifiedEventItem.js +6 -1
- package/lib/commonjs/hooks/useUnifiedEvents.js +137 -28
- package/lib/commonjs/index.js +6 -0
- package/lib/commonjs/stores/unifiedEventStore.js +61 -16
- package/lib/commonjs/types/copySettings.js +29 -0
- package/lib/commonjs/utils/autoDiscoverEventSources.js +261 -39
- package/lib/commonjs/utils/badgeSelectionStorage.js +32 -0
- package/lib/commonjs/utils/eventExportFormatter.js +778 -1
- package/lib/module/components/EventsCopySettingsView.js +40 -9
- package/lib/module/components/UnifiedEventDetail.js +32 -1
- package/lib/module/components/UnifiedEventFilters.js +50 -21
- package/lib/module/components/UnifiedEventItem.js +6 -1
- package/lib/module/hooks/useUnifiedEvents.js +140 -31
- package/lib/module/index.js +4 -1
- package/lib/module/stores/unifiedEventStore.js +58 -16
- package/lib/module/types/copySettings.js +29 -0
- package/lib/module/utils/autoDiscoverEventSources.js +260 -39
- package/lib/module/utils/badgeSelectionStorage.js +30 -0
- package/lib/module/utils/eventExportFormatter.js +777 -1
- package/lib/typescript/components/UnifiedEventFilters.d.ts +3 -0
- package/lib/typescript/hooks/useUnifiedEvents.d.ts +2 -0
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/stores/unifiedEventStore.d.ts +18 -2
- package/lib/typescript/types/copySettings.d.ts +25 -1
- package/lib/typescript/types/index.d.ts +3 -1
- package/lib/typescript/utils/autoDiscoverEventSources.d.ts +17 -0
- package/lib/typescript/utils/badgeSelectionStorage.d.ts +9 -0
- package/lib/typescript/utils/eventExportFormatter.d.ts +4 -0
- package/package.json +3 -3
- package/src/components/EventsCopySettingsView.tsx +41 -5
- package/src/components/UnifiedEventDetail.tsx +28 -0
- package/src/components/UnifiedEventFilters.tsx +88 -21
- package/src/components/UnifiedEventItem.tsx +5 -0
- package/src/hooks/useUnifiedEvents.ts +153 -25
- package/src/index.tsx +4 -0
- package/src/stores/unifiedEventStore.ts +58 -12
- package/src/types/copySettings.ts +31 -1
- package/src/types/index.ts +4 -1
- package/src/utils/autoDiscoverEventSources.ts +268 -44
- package/src/utils/badgeSelectionStorage.ts +30 -0
- package/src/utils/eventExportFormatter.ts +797 -0
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* Uses auto-discovery to find installed tool packages - no hard dependencies required!
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import { getCachedDiscovery } from "../utils/autoDiscoverEventSources";
|
|
12
|
+
import { getCachedDiscovery, getAggregatedSubscriberCounts } from "../utils/autoDiscoverEventSources";
|
|
13
13
|
const MAX_EVENTS = 200;
|
|
14
14
|
class UnifiedEventStore {
|
|
15
15
|
events = [];
|
|
@@ -55,18 +55,21 @@ class UnifiedEventStore {
|
|
|
55
55
|
if (this.sourceUnsubscribers.has(source.id)) {
|
|
56
56
|
return; // Already subscribed
|
|
57
57
|
}
|
|
58
|
+
try {
|
|
59
|
+
// Run setup if needed
|
|
60
|
+
if (source.setup) {
|
|
61
|
+
await source.setup();
|
|
62
|
+
}
|
|
58
63
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
if (unsubscribe) {
|
|
69
|
-
this.sourceUnsubscribers.set(source.id, unsubscribe);
|
|
64
|
+
// Subscribe and track the unsubscriber
|
|
65
|
+
const unsubscribe = await source.subscribe(event => {
|
|
66
|
+
this.addEvent(event);
|
|
67
|
+
});
|
|
68
|
+
if (unsubscribe) {
|
|
69
|
+
this.sourceUnsubscribers.set(source.id, unsubscribe);
|
|
70
|
+
}
|
|
71
|
+
} catch {
|
|
72
|
+
// Silently fail - source may not be available
|
|
70
73
|
}
|
|
71
74
|
}
|
|
72
75
|
|
|
@@ -143,7 +146,8 @@ class UnifiedEventStore {
|
|
|
143
146
|
unsubscribeFromNetwork() {
|
|
144
147
|
this.unsubscribeFromSource("network");
|
|
145
148
|
this.activeSources.delete("network");
|
|
146
|
-
|
|
149
|
+
// Don't clear networkEventIdMap - it's needed to deduplicate events
|
|
150
|
+
// when resubscribing while requests are still in flight
|
|
147
151
|
}
|
|
148
152
|
|
|
149
153
|
/**
|
|
@@ -190,6 +194,27 @@ class UnifiedEventStore {
|
|
|
190
194
|
this.activeSources.delete("route");
|
|
191
195
|
}
|
|
192
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Subscribe to render events (if @buoy-gg/highlight-updates is installed)
|
|
199
|
+
*/
|
|
200
|
+
subscribeToRender() {
|
|
201
|
+
const {
|
|
202
|
+
sources
|
|
203
|
+
} = getCachedDiscovery();
|
|
204
|
+
const renderSource = sources.find(s => s.id === "render");
|
|
205
|
+
if (renderSource) {
|
|
206
|
+
this.subscribeToSource(renderSource);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Unsubscribe from render events
|
|
212
|
+
*/
|
|
213
|
+
unsubscribeFromRender() {
|
|
214
|
+
this.unsubscribeFromSource("render");
|
|
215
|
+
this.activeSources.delete("render");
|
|
216
|
+
}
|
|
217
|
+
|
|
193
218
|
/**
|
|
194
219
|
* Add an event to the store
|
|
195
220
|
*/
|
|
@@ -253,7 +278,8 @@ class UnifiedEventStore {
|
|
|
253
278
|
"react-query": 0,
|
|
254
279
|
"react-query-query": 0,
|
|
255
280
|
"react-query-mutation": 0,
|
|
256
|
-
route: 0
|
|
281
|
+
route: 0,
|
|
282
|
+
render: 0
|
|
257
283
|
};
|
|
258
284
|
for (const event of this.events) {
|
|
259
285
|
counts[event.source]++;
|
|
@@ -306,7 +332,7 @@ class UnifiedEventStore {
|
|
|
306
332
|
*/
|
|
307
333
|
unsubscribeAll() {
|
|
308
334
|
// Unsubscribe from all tracked sources
|
|
309
|
-
for (const [
|
|
335
|
+
for (const [, unsubscribe] of this.sourceUnsubscribers) {
|
|
310
336
|
unsubscribe();
|
|
311
337
|
}
|
|
312
338
|
this.sourceUnsubscribers.clear();
|
|
@@ -334,6 +360,8 @@ class UnifiedEventStore {
|
|
|
334
360
|
return this.sourceUnsubscribers.has("react-query");
|
|
335
361
|
case "route":
|
|
336
362
|
return this.sourceUnsubscribers.has("route-events");
|
|
363
|
+
case "render":
|
|
364
|
+
return this.sourceUnsubscribers.has("render");
|
|
337
365
|
default:
|
|
338
366
|
return false;
|
|
339
367
|
}
|
|
@@ -351,9 +379,18 @@ class UnifiedEventStore {
|
|
|
351
379
|
"react-query": this.sourceUnsubscribers.has("react-query"),
|
|
352
380
|
"react-query-query": this.sourceUnsubscribers.has("react-query"),
|
|
353
381
|
"react-query-mutation": this.sourceUnsubscribers.has("react-query"),
|
|
354
|
-
route: this.sourceUnsubscribers.has("route-events")
|
|
382
|
+
route: this.sourceUnsubscribers.has("route-events"),
|
|
383
|
+
render: this.sourceUnsubscribers.has("render")
|
|
355
384
|
};
|
|
356
385
|
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Get subscriber counts from all underlying event stores.
|
|
389
|
+
* Useful for debugging the event system.
|
|
390
|
+
*/
|
|
391
|
+
getSubscriberCounts() {
|
|
392
|
+
return getAggregatedSubscriberCounts();
|
|
393
|
+
}
|
|
357
394
|
}
|
|
358
395
|
|
|
359
396
|
// Singleton instance
|
|
@@ -370,6 +407,8 @@ export const subscribeToReactQuery = () => unifiedEventStore.subscribeToReactQue
|
|
|
370
407
|
export const unsubscribeFromReactQuery = () => unifiedEventStore.unsubscribeFromReactQuery();
|
|
371
408
|
export const subscribeToRoutes = () => unifiedEventStore.subscribeToRoutes();
|
|
372
409
|
export const unsubscribeFromRoutes = () => unifiedEventStore.unsubscribeFromRoutes();
|
|
410
|
+
export const subscribeToRender = () => unifiedEventStore.subscribeToRender();
|
|
411
|
+
export const unsubscribeFromRender = () => unifiedEventStore.unsubscribeFromRender();
|
|
373
412
|
export const getEvents = enabledSources => unifiedEventStore.getEvents(enabledSources);
|
|
374
413
|
export const getActiveSources = () => unifiedEventStore.getActiveSources();
|
|
375
414
|
export const getSourceCounts = () => unifiedEventStore.getSourceCounts();
|
|
@@ -384,4 +423,7 @@ export const unsubscribeAll = () => unifiedEventStore.unsubscribeAll();
|
|
|
384
423
|
export const getDiscoveredSources = () => unifiedEventStore.getDiscoveredSources();
|
|
385
424
|
export const getAvailableEventSources = () => unifiedEventStore.getAvailableEventSources();
|
|
386
425
|
export const subscribeToAll = () => unifiedEventStore.subscribeToAll();
|
|
426
|
+
export const getSubscriberCounts = () => unifiedEventStore.getSubscriberCounts();
|
|
427
|
+
|
|
428
|
+
// Re-export type for convenience
|
|
387
429
|
//# sourceMappingURL=unifiedEventStore.js.map
|
|
@@ -160,6 +160,30 @@ export const COPY_PRESETS = {
|
|
|
160
160
|
reduxChangedOnly: true,
|
|
161
161
|
showStorageDiff: false,
|
|
162
162
|
stripVerboseFields: true
|
|
163
|
+
},
|
|
164
|
+
/**
|
|
165
|
+
* Mermaid Diagram - Visual sequence diagram for flow visualization
|
|
166
|
+
*/
|
|
167
|
+
mermaid: {
|
|
168
|
+
timestampFormat: "relative",
|
|
169
|
+
includeSource: true,
|
|
170
|
+
includeStatus: true,
|
|
171
|
+
includeTitle: true,
|
|
172
|
+
includeSubtitle: false,
|
|
173
|
+
includeCorrelation: true,
|
|
174
|
+
includeDuration: true,
|
|
175
|
+
includeSummaryHeader: false,
|
|
176
|
+
includeTotalDuration: false,
|
|
177
|
+
includeEventData: false,
|
|
178
|
+
dataSizeThreshold: 1,
|
|
179
|
+
format: "mermaid",
|
|
180
|
+
filterMode: "all",
|
|
181
|
+
filterSources: [],
|
|
182
|
+
compactMode: false,
|
|
183
|
+
smartJsonParsing: true,
|
|
184
|
+
reduxChangedOnly: true,
|
|
185
|
+
showStorageDiff: true,
|
|
186
|
+
stripVerboseFields: true
|
|
163
187
|
}
|
|
164
188
|
};
|
|
165
189
|
/**
|
|
@@ -210,6 +234,11 @@ export const PRESET_METADATA = {
|
|
|
210
234
|
label: "Minimal",
|
|
211
235
|
description: "Quick reference",
|
|
212
236
|
color: "#6B7280" // Gray
|
|
237
|
+
},
|
|
238
|
+
mermaid: {
|
|
239
|
+
label: "Diagram",
|
|
240
|
+
description: "Visual flow",
|
|
241
|
+
color: "#A855F7" // Purple
|
|
213
242
|
}
|
|
214
243
|
};
|
|
215
244
|
//# sourceMappingURL=copySettings.js.map
|
|
@@ -47,9 +47,7 @@ function tryLoadStorageSource() {
|
|
|
47
47
|
name: "Storage",
|
|
48
48
|
eventSources: ["storage-async", "storage-mmkv"],
|
|
49
49
|
available: true,
|
|
50
|
-
setup
|
|
51
|
-
await storageEventStore.startCapturing();
|
|
52
|
-
},
|
|
50
|
+
// No setup needed - onEvent() auto-starts capturing via Subscribable pattern
|
|
53
51
|
subscribe: onEvent => {
|
|
54
52
|
return storageEventStore.onEvent(event => {
|
|
55
53
|
const unifiedEvent = transformStorageEvent(event);
|
|
@@ -207,55 +205,55 @@ function transformReduxAction(action) {
|
|
|
207
205
|
function tryLoadNetworkSource() {
|
|
208
206
|
try {
|
|
209
207
|
// @ts-ignore - Dynamic import that may not exist
|
|
208
|
+
// Note: We use networkListener (the getter) instead of startNetworkListener
|
|
209
|
+
// because startNetworkListener is not exported from the main package
|
|
210
210
|
const {
|
|
211
211
|
networkEventStore,
|
|
212
|
-
|
|
212
|
+
networkListener,
|
|
213
213
|
addNetworkListener
|
|
214
214
|
} = require("@buoy-gg/network");
|
|
215
215
|
|
|
216
|
-
// Map network event IDs to unified event IDs for updates
|
|
216
|
+
// Map network event IDs to unified event IDs for updates (request -> response)
|
|
217
217
|
const networkEventIdMap = new Map();
|
|
218
|
-
let storeUnsubscribe = null;
|
|
219
|
-
let listenerUnsubscribe = null;
|
|
220
218
|
return {
|
|
221
219
|
id: "network",
|
|
222
220
|
name: "Network",
|
|
223
221
|
eventSources: ["network"],
|
|
224
222
|
available: true,
|
|
225
223
|
setup: () => {
|
|
226
|
-
|
|
224
|
+
// Get the network listener singleton and start it if not already active
|
|
225
|
+
const listener = networkListener();
|
|
226
|
+
if (!listener.isActive) {
|
|
227
|
+
listener.startListening();
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Ensure events flow into the store. The network panel does this via
|
|
231
|
+
// addNetworkListener, but if events package loads first, we need to
|
|
232
|
+
// set it up ourselves.
|
|
233
|
+
if (listener.listenerCount === 0) {
|
|
234
|
+
addNetworkListener(event => {
|
|
235
|
+
networkEventStore.processNetworkEvent(event);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
227
238
|
},
|
|
228
239
|
subscribe: onEvent => {
|
|
229
|
-
//
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
} else {
|
|
245
|
-
// Existing event updated (e.g., pending -> success/error)
|
|
246
|
-
// Create updated unified event with same ID so store can update it
|
|
247
|
-
const unifiedEvent = transformNetworkEvent(networkEvent);
|
|
248
|
-
unifiedEvent.id = existingUnifiedId; // Keep the same unified ID
|
|
249
|
-
onEvent(unifiedEvent);
|
|
250
|
-
}
|
|
240
|
+
// Use onEvent() pattern - same as storage
|
|
241
|
+
// This fires for each individual event (request or response/error update)
|
|
242
|
+
return networkEventStore.onEvent(event => {
|
|
243
|
+
const ne = event;
|
|
244
|
+
const existingUnifiedId = networkEventIdMap.get(ne.id);
|
|
245
|
+
if (!existingUnifiedId) {
|
|
246
|
+
// New event (request started)
|
|
247
|
+
const unifiedEvent = transformNetworkEvent(event);
|
|
248
|
+
networkEventIdMap.set(ne.id, unifiedEvent.id);
|
|
249
|
+
onEvent(unifiedEvent);
|
|
250
|
+
} else {
|
|
251
|
+
// Existing event updated (response received or error)
|
|
252
|
+
const unifiedEvent = transformNetworkEvent(event);
|
|
253
|
+
unifiedEvent.id = existingUnifiedId; // Keep the same unified ID
|
|
254
|
+
onEvent(unifiedEvent);
|
|
251
255
|
}
|
|
252
256
|
});
|
|
253
|
-
return () => {
|
|
254
|
-
listenerUnsubscribe?.();
|
|
255
|
-
storeUnsubscribe?.();
|
|
256
|
-
listenerUnsubscribe = null;
|
|
257
|
-
storeUnsubscribe = null;
|
|
258
|
-
};
|
|
259
257
|
}
|
|
260
258
|
};
|
|
261
259
|
} catch {
|
|
@@ -460,15 +458,16 @@ function tryLoadRouteEventsSource() {
|
|
|
460
458
|
try {
|
|
461
459
|
// @ts-ignore - Dynamic import that may not exist
|
|
462
460
|
const {
|
|
463
|
-
|
|
461
|
+
routeEventStore
|
|
464
462
|
} = require("@buoy-gg/route-events");
|
|
465
463
|
return {
|
|
466
464
|
id: "route-events",
|
|
467
465
|
name: "Routes",
|
|
468
466
|
eventSources: ["route"],
|
|
469
467
|
available: true,
|
|
468
|
+
// No setup needed - onEvent() auto-starts listening via Subscribable pattern
|
|
470
469
|
subscribe: onEvent => {
|
|
471
|
-
return
|
|
470
|
+
return routeEventStore.onEvent(event => {
|
|
472
471
|
const unifiedEvent = transformRouteEvent(event);
|
|
473
472
|
onEvent(unifiedEvent);
|
|
474
473
|
});
|
|
@@ -516,6 +515,134 @@ function transformRouteEvent(event) {
|
|
|
516
515
|
};
|
|
517
516
|
}
|
|
518
517
|
|
|
518
|
+
// ============================================================================
|
|
519
|
+
// Render Events Source Discovery (Highlight Updates)
|
|
520
|
+
// ============================================================================
|
|
521
|
+
|
|
522
|
+
function tryLoadHighlightUpdatesSource() {
|
|
523
|
+
try {
|
|
524
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
525
|
+
const highlightUpdates = require("@buoy-gg/highlight-updates");
|
|
526
|
+
|
|
527
|
+
// Verify the required exports exist
|
|
528
|
+
if (!highlightUpdates.RenderTracker || !highlightUpdates.HighlightUpdatesController) {
|
|
529
|
+
return null;
|
|
530
|
+
}
|
|
531
|
+
return {
|
|
532
|
+
id: "render",
|
|
533
|
+
name: "Render",
|
|
534
|
+
eventSources: ["render"],
|
|
535
|
+
available: true,
|
|
536
|
+
setup: () => {
|
|
537
|
+
// @ts-ignore
|
|
538
|
+
const {
|
|
539
|
+
HighlightUpdatesController
|
|
540
|
+
} = require("@buoy-gg/highlight-updates");
|
|
541
|
+
// Enable background tracking (NOT the visual toggle) - this sets up render
|
|
542
|
+
// interception without affecting the user's visual highlight toggle state
|
|
543
|
+
if (HighlightUpdatesController) {
|
|
544
|
+
HighlightUpdatesController.enableBackgroundTracking();
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
subscribe: onEvent => {
|
|
548
|
+
// @ts-ignore
|
|
549
|
+
const {
|
|
550
|
+
RenderTracker,
|
|
551
|
+
HighlightUpdatesController
|
|
552
|
+
} = require("@buoy-gg/highlight-updates");
|
|
553
|
+
|
|
554
|
+
// Ensure background tracking is enabled (separate from visual toggle)
|
|
555
|
+
if (HighlightUpdatesController && !HighlightUpdatesController.isBackgroundTrackingEnabled()) {
|
|
556
|
+
HighlightUpdatesController.enableBackgroundTracking();
|
|
557
|
+
}
|
|
558
|
+
const unsubscribeCallback = RenderTracker.onRenderEvent((event, render) => {
|
|
559
|
+
const unifiedEvent = transformRenderEvent(event, render);
|
|
560
|
+
onEvent(unifiedEvent);
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
// Return a wrapped unsubscribe that also disables background tracking
|
|
564
|
+
return () => {
|
|
565
|
+
unsubscribeCallback();
|
|
566
|
+
HighlightUpdatesController.disableBackgroundTracking();
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
};
|
|
570
|
+
} catch {
|
|
571
|
+
return null;
|
|
572
|
+
}
|
|
573
|
+
}
|
|
574
|
+
function transformRenderEvent(event, render) {
|
|
575
|
+
const e = event;
|
|
576
|
+
const r = render;
|
|
577
|
+
|
|
578
|
+
// Use component name if available, otherwise display name (View, Text, etc.)
|
|
579
|
+
const title = r.componentName || r.displayName || r.viewType;
|
|
580
|
+
|
|
581
|
+
// Build subtitle from cause info
|
|
582
|
+
const subtitleParts = [];
|
|
583
|
+
|
|
584
|
+
// Add cause type
|
|
585
|
+
const causeLabels = {
|
|
586
|
+
mount: "mounted",
|
|
587
|
+
props: "props changed",
|
|
588
|
+
state: "state changed",
|
|
589
|
+
hooks: "hooks changed",
|
|
590
|
+
context: "context changed",
|
|
591
|
+
parent: "parent re-rendered",
|
|
592
|
+
unknown: "re-rendered"
|
|
593
|
+
};
|
|
594
|
+
subtitleParts.push(causeLabels[e.cause.type] || e.cause.type);
|
|
595
|
+
|
|
596
|
+
// Add changed keys if props changed
|
|
597
|
+
if (e.cause.type === "props" && e.cause.changedKeys?.length) {
|
|
598
|
+
const keys = e.cause.changedKeys.slice(0, 3).join(", ");
|
|
599
|
+
const more = e.cause.changedKeys.length > 3 ? ` +${e.cause.changedKeys.length - 3}` : "";
|
|
600
|
+
subtitleParts.push(`[${keys}${more}]`);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Add hook change description if available
|
|
604
|
+
if (e.cause.hookChanges?.length) {
|
|
605
|
+
const firstChange = e.cause.hookChanges[0];
|
|
606
|
+
if (firstChange.description) {
|
|
607
|
+
subtitleParts.push(firstChange.description);
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
// Add render number
|
|
612
|
+
subtitleParts.push(`#${e.renderNumber}`);
|
|
613
|
+
|
|
614
|
+
// Determine status based on cause type
|
|
615
|
+
let status = "neutral";
|
|
616
|
+
switch (e.cause.type) {
|
|
617
|
+
case "mount":
|
|
618
|
+
status = "neutral"; // First render is expected
|
|
619
|
+
break;
|
|
620
|
+
case "props":
|
|
621
|
+
case "state":
|
|
622
|
+
case "hooks":
|
|
623
|
+
case "context":
|
|
624
|
+
status = "success"; // Intentional re-renders
|
|
625
|
+
break;
|
|
626
|
+
case "parent":
|
|
627
|
+
status = "pending"; // Potentially wasteful (yellow highlight)
|
|
628
|
+
break;
|
|
629
|
+
default:
|
|
630
|
+
status = "neutral";
|
|
631
|
+
}
|
|
632
|
+
return {
|
|
633
|
+
id: generateEventId("render"),
|
|
634
|
+
source: "render",
|
|
635
|
+
timestamp: e.timestamp,
|
|
636
|
+
title,
|
|
637
|
+
subtitle: subtitleParts.join(" · "),
|
|
638
|
+
status,
|
|
639
|
+
originalEvent: {
|
|
640
|
+
event: e,
|
|
641
|
+
render: r
|
|
642
|
+
}
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
|
|
519
646
|
// ============================================================================
|
|
520
647
|
// Main Auto-Discovery Function
|
|
521
648
|
// ============================================================================
|
|
@@ -542,7 +669,7 @@ export function autoDiscoverEventSources() {
|
|
|
542
669
|
const availableEventSources = new Set();
|
|
543
670
|
|
|
544
671
|
// Try to load each source
|
|
545
|
-
const loaders = [tryLoadStorageSource, tryLoadReduxSource, tryLoadNetworkSource, tryLoadReactQuerySource, tryLoadRouteEventsSource];
|
|
672
|
+
const loaders = [tryLoadStorageSource, tryLoadReduxSource, tryLoadNetworkSource, tryLoadReactQuerySource, tryLoadRouteEventsSource, tryLoadHighlightUpdatesSource];
|
|
546
673
|
for (const loader of loaders) {
|
|
547
674
|
const source = loader();
|
|
548
675
|
if (source && source.available) {
|
|
@@ -601,6 +728,11 @@ export function getSourceDisplayConfig(source) {
|
|
|
601
728
|
label: "Route",
|
|
602
729
|
color: "#06B6D4",
|
|
603
730
|
icon: "navigate-outline"
|
|
731
|
+
},
|
|
732
|
+
render: {
|
|
733
|
+
label: "Render",
|
|
734
|
+
color: "#F472B6",
|
|
735
|
+
icon: "layers-outline"
|
|
604
736
|
}
|
|
605
737
|
};
|
|
606
738
|
return configs[source] || {
|
|
@@ -630,4 +762,93 @@ export function getCachedDiscovery() {
|
|
|
630
762
|
export function clearDiscoveryCache() {
|
|
631
763
|
cachedDiscovery = null;
|
|
632
764
|
}
|
|
765
|
+
|
|
766
|
+
// ============================================================================
|
|
767
|
+
// Subscriber Count Aggregation
|
|
768
|
+
// ============================================================================
|
|
769
|
+
|
|
770
|
+
/**
|
|
771
|
+
* Get subscriber counts from all discovered event stores.
|
|
772
|
+
* Useful for debugging and monitoring the event system.
|
|
773
|
+
*/
|
|
774
|
+
export function getAggregatedSubscriberCounts() {
|
|
775
|
+
const sources = [];
|
|
776
|
+
let totalSubscribers = 0;
|
|
777
|
+
|
|
778
|
+
// Try to get counts from storage store
|
|
779
|
+
try {
|
|
780
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
781
|
+
const {
|
|
782
|
+
storageEventStore
|
|
783
|
+
} = require("@buoy-gg/storage");
|
|
784
|
+
const counts = storageEventStore.getSubscriberCounts();
|
|
785
|
+
sources.push({
|
|
786
|
+
sourceId: "storage",
|
|
787
|
+
counts
|
|
788
|
+
});
|
|
789
|
+
totalSubscribers += counts.total;
|
|
790
|
+
} catch {
|
|
791
|
+
// Package not installed
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Try to get counts from network store
|
|
795
|
+
try {
|
|
796
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
797
|
+
const {
|
|
798
|
+
networkEventStore
|
|
799
|
+
} = require("@buoy-gg/network");
|
|
800
|
+
const counts = networkEventStore.getSubscriberCounts();
|
|
801
|
+
sources.push({
|
|
802
|
+
sourceId: "network",
|
|
803
|
+
counts
|
|
804
|
+
});
|
|
805
|
+
totalSubscribers += counts.total;
|
|
806
|
+
} catch {
|
|
807
|
+
// Package not installed
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
// Try to get counts from route events store
|
|
811
|
+
try {
|
|
812
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
813
|
+
const {
|
|
814
|
+
routeEventStore
|
|
815
|
+
} = require("@buoy-gg/route-events");
|
|
816
|
+
const counts = routeEventStore.getSubscriberCounts();
|
|
817
|
+
sources.push({
|
|
818
|
+
sourceId: "route-events",
|
|
819
|
+
counts
|
|
820
|
+
});
|
|
821
|
+
totalSubscribers += counts.total;
|
|
822
|
+
} catch {
|
|
823
|
+
// Package not installed
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
// Try to get counts from render tracker (highlight-updates)
|
|
827
|
+
try {
|
|
828
|
+
// @ts-ignore - Dynamic import that may not exist
|
|
829
|
+
const {
|
|
830
|
+
RenderTracker,
|
|
831
|
+
HighlightUpdatesController
|
|
832
|
+
} = require("@buoy-gg/highlight-updates");
|
|
833
|
+
const callbackCount = RenderTracker.getRenderEventCallbackCount();
|
|
834
|
+
// Also count the visual highlight tool as a subscriber when enabled
|
|
835
|
+
const visualToolEnabled = HighlightUpdatesController?.isEnabled?.() ? 1 : 0;
|
|
836
|
+
const counts = {
|
|
837
|
+
eventCallbacks: callbackCount,
|
|
838
|
+
arrayListeners: visualToolEnabled,
|
|
839
|
+
total: callbackCount + visualToolEnabled
|
|
840
|
+
};
|
|
841
|
+
sources.push({
|
|
842
|
+
sourceId: "render",
|
|
843
|
+
counts
|
|
844
|
+
});
|
|
845
|
+
totalSubscribers += counts.total;
|
|
846
|
+
} catch {
|
|
847
|
+
// Package not installed
|
|
848
|
+
}
|
|
849
|
+
return {
|
|
850
|
+
sources,
|
|
851
|
+
totalSubscribers
|
|
852
|
+
};
|
|
853
|
+
}
|
|
633
854
|
//# sourceMappingURL=autoDiscoverEventSources.js.map
|
|
@@ -49,4 +49,34 @@ export async function clearEnabledSources() {
|
|
|
49
49
|
// Silently fail
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Save the capturing state to persistent storage
|
|
55
|
+
*/
|
|
56
|
+
export async function saveCapturingState(isCapturing) {
|
|
57
|
+
try {
|
|
58
|
+
const key = devToolsStorageKeys.events.isCapturing();
|
|
59
|
+
await persistentStorage.setItem(key, JSON.stringify(isCapturing));
|
|
60
|
+
} catch {
|
|
61
|
+
// Silently fail - persistence is optional
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Load the capturing state from persistent storage
|
|
67
|
+
* Returns null if no saved state exists (defaults to true on first load)
|
|
68
|
+
*/
|
|
69
|
+
export async function loadCapturingState() {
|
|
70
|
+
try {
|
|
71
|
+
const key = devToolsStorageKeys.events.isCapturing();
|
|
72
|
+
const value = await persistentStorage.getItem(key);
|
|
73
|
+
if (value !== null && value !== "") {
|
|
74
|
+
return JSON.parse(value);
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
77
|
+
} catch {
|
|
78
|
+
// Silently fail - return null to use defaults
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
52
82
|
//# sourceMappingURL=badgeSelectionStorage.js.map
|