@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.
Files changed (44) hide show
  1. package/lib/commonjs/components/EventsCopySettingsView.js +39 -8
  2. package/lib/commonjs/components/UnifiedEventDetail.js +32 -1
  3. package/lib/commonjs/components/UnifiedEventFilters.js +50 -21
  4. package/lib/commonjs/components/UnifiedEventItem.js +6 -1
  5. package/lib/commonjs/hooks/useUnifiedEvents.js +137 -28
  6. package/lib/commonjs/index.js +6 -0
  7. package/lib/commonjs/stores/unifiedEventStore.js +61 -16
  8. package/lib/commonjs/types/copySettings.js +29 -0
  9. package/lib/commonjs/utils/autoDiscoverEventSources.js +261 -39
  10. package/lib/commonjs/utils/badgeSelectionStorage.js +32 -0
  11. package/lib/commonjs/utils/eventExportFormatter.js +778 -1
  12. package/lib/module/components/EventsCopySettingsView.js +40 -9
  13. package/lib/module/components/UnifiedEventDetail.js +32 -1
  14. package/lib/module/components/UnifiedEventFilters.js +50 -21
  15. package/lib/module/components/UnifiedEventItem.js +6 -1
  16. package/lib/module/hooks/useUnifiedEvents.js +140 -31
  17. package/lib/module/index.js +4 -1
  18. package/lib/module/stores/unifiedEventStore.js +58 -16
  19. package/lib/module/types/copySettings.js +29 -0
  20. package/lib/module/utils/autoDiscoverEventSources.js +260 -39
  21. package/lib/module/utils/badgeSelectionStorage.js +30 -0
  22. package/lib/module/utils/eventExportFormatter.js +777 -1
  23. package/lib/typescript/components/UnifiedEventFilters.d.ts +3 -0
  24. package/lib/typescript/hooks/useUnifiedEvents.d.ts +2 -0
  25. package/lib/typescript/index.d.ts +1 -1
  26. package/lib/typescript/stores/unifiedEventStore.d.ts +18 -2
  27. package/lib/typescript/types/copySettings.d.ts +25 -1
  28. package/lib/typescript/types/index.d.ts +3 -1
  29. package/lib/typescript/utils/autoDiscoverEventSources.d.ts +17 -0
  30. package/lib/typescript/utils/badgeSelectionStorage.d.ts +9 -0
  31. package/lib/typescript/utils/eventExportFormatter.d.ts +4 -0
  32. package/package.json +3 -3
  33. package/src/components/EventsCopySettingsView.tsx +41 -5
  34. package/src/components/UnifiedEventDetail.tsx +28 -0
  35. package/src/components/UnifiedEventFilters.tsx +88 -21
  36. package/src/components/UnifiedEventItem.tsx +5 -0
  37. package/src/hooks/useUnifiedEvents.ts +153 -25
  38. package/src/index.tsx +4 -0
  39. package/src/stores/unifiedEventStore.ts +58 -12
  40. package/src/types/copySettings.ts +31 -1
  41. package/src/types/index.ts +4 -1
  42. package/src/utils/autoDiscoverEventSources.ts +268 -44
  43. package/src/utils/badgeSelectionStorage.ts +30 -0
  44. 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
- // Run setup if needed
60
- if (source.setup) {
61
- await source.setup();
62
- }
63
-
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);
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
- this.networkEventIdMap.clear();
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 [sourceId, unsubscribe] of this.sourceUnsubscribers) {
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: async () => {
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
- startNetworkListener,
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
- startNetworkListener();
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
- // Add listener to process network events into the store
230
- listenerUnsubscribe = addNetworkListener(event => {
231
- networkEventStore.processNetworkEvent(event);
232
- });
233
-
234
- // Subscribe to network event store
235
- storeUnsubscribe = networkEventStore.subscribe(events => {
236
- for (const networkEvent of events) {
237
- const ne = networkEvent;
238
- const existingUnifiedId = networkEventIdMap.get(ne.id);
239
- if (!existingUnifiedId) {
240
- // New event
241
- const unifiedEvent = transformNetworkEvent(networkEvent);
242
- networkEventIdMap.set(ne.id, unifiedEvent.id);
243
- onEvent(unifiedEvent);
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
- routeObserver
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 routeObserver.addListener(event => {
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