@buoy-gg/storage 7.0.41 → 7.0.43

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 (180) hide show
  1. package/README.md +11 -90
  2. package/lib/commonjs/index.js +1 -353
  3. package/lib/commonjs/preset.js +1 -85
  4. package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +1 -36
  5. package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +1 -12
  6. package/lib/commonjs/storage/components/DiffViewer/themes/diffThemes.js +1 -24
  7. package/lib/commonjs/storage/components/GameUIStorageBrowser.js +3 -1259
  8. package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -257
  9. package/lib/commonjs/storage/components/MMKVInstanceSelector.js +1 -419
  10. package/lib/commonjs/storage/components/SelectionActionBar.js +1 -207
  11. package/lib/commonjs/storage/components/StorageActionButtons.js +1 -242
  12. package/lib/commonjs/storage/components/StorageBrowserMode.js +1 -61
  13. package/lib/commonjs/storage/components/StorageEventActionButton.js +1 -121
  14. package/lib/commonjs/storage/components/StorageEventCard.js +1 -118
  15. package/lib/commonjs/storage/components/StorageEventDetailContent.js +1 -494
  16. package/lib/commonjs/storage/components/StorageEventFilterView.js +1 -160
  17. package/lib/commonjs/storage/components/StorageEventsSection.js +1 -24
  18. package/lib/commonjs/storage/components/StorageFilterCards.js +1 -231
  19. package/lib/commonjs/storage/components/StorageKeyCard.js +1 -520
  20. package/lib/commonjs/storage/components/StorageKeyDetailScreen.js +1 -579
  21. package/lib/commonjs/storage/components/StorageKeyRow.js +1 -559
  22. package/lib/commonjs/storage/components/StorageKeySection.js +1 -160
  23. package/lib/commonjs/storage/components/StorageKeyStats.js +1 -345
  24. package/lib/commonjs/storage/components/StorageModalWithTabs.js +1 -954
  25. package/lib/commonjs/storage/components/StorageSaveNotice.js +1 -171
  26. package/lib/commonjs/storage/components/StorageSection.js +1 -43
  27. package/lib/commonjs/storage/components/StorageTypeFilterBar.js +1 -144
  28. package/lib/commonjs/storage/hooks/useAsyncStorageKeys.js +1 -141
  29. package/lib/commonjs/storage/hooks/useMMKVInstances.js +1 -210
  30. package/lib/commonjs/storage/hooks/useMMKVKeys.js +1 -376
  31. package/lib/commonjs/storage/hooks/useSecureStoreKeys.js +1 -202
  32. package/lib/commonjs/storage/hooks/useStorageEvents.js +1 -61
  33. package/lib/commonjs/storage/stores/storageEventStore.js +1 -312
  34. package/lib/commonjs/storage/sync/storageSyncAdapter.js +1 -492
  35. package/lib/commonjs/storage/types.js +1 -5
  36. package/lib/commonjs/storage/utils/AsyncStorageListener.js +1 -691
  37. package/lib/commonjs/storage/utils/AsyncStorageListener.web.js +1 -89
  38. package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +1 -203
  39. package/lib/commonjs/storage/utils/MMKVListener.js +1 -416
  40. package/lib/commonjs/storage/utils/SecureStoreRegistry.js +1 -200
  41. package/lib/commonjs/storage/utils/asyncStorageCompat.js +1 -89
  42. package/lib/commonjs/storage/utils/browserStorageLifecycle.js +1 -10
  43. package/lib/commonjs/storage/utils/browserStorageLifecycle.web.js +1 -70
  44. package/lib/commonjs/storage/utils/clearAllStorage.js +1 -48
  45. package/lib/commonjs/storage/utils/deleteStorageKeys.js +1 -82
  46. package/lib/commonjs/storage/utils/lineDiff.js +1 -30
  47. package/lib/commonjs/storage/utils/mmkvAvailability.js +1 -62
  48. package/lib/commonjs/storage/utils/mmkvAvailability.web.js +1 -21
  49. package/lib/commonjs/storage/utils/mmkvTypeDetection.js +1 -154
  50. package/lib/commonjs/storage/utils/requiredStorageKeyScope.js +1 -17
  51. package/lib/commonjs/storage/utils/setStorageValue.js +1 -218
  52. package/lib/commonjs/storage/utils/snapshotProvider.js +1 -382
  53. package/lib/commonjs/storage/utils/storageActionHelpers.js +1 -46
  54. package/lib/commonjs/storage/utils/storageBrowserRefresh.js +1 -49
  55. package/lib/commonjs/storage/utils/storageLabels.js +1 -13
  56. package/lib/commonjs/storage/utils/storageLabels.web.js +1 -13
  57. package/lib/commonjs/storage/utils/storageOps.js +1 -53
  58. package/lib/commonjs/storage/utils/storageQueryUtils.js +1 -35
  59. package/lib/commonjs/storage/utils/storageTimeTravelUtils.js +1 -288
  60. package/lib/commonjs/storage/utils/valueType.js +1 -83
  61. package/lib/module/index.js +1 -114
  62. package/lib/module/preset.js +1 -82
  63. package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +1 -32
  64. package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +1 -9
  65. package/lib/module/storage/components/DiffViewer/themes/diffThemes.js +1 -10
  66. package/lib/module/storage/components/GameUIStorageBrowser.js +3 -1257
  67. package/lib/module/storage/components/MMKVInstanceInfoPanel.js +1 -253
  68. package/lib/module/storage/components/MMKVInstanceSelector.js +1 -415
  69. package/lib/module/storage/components/SelectionActionBar.js +1 -204
  70. package/lib/module/storage/components/StorageActionButtons.js +1 -238
  71. package/lib/module/storage/components/StorageBrowserMode.js +1 -57
  72. package/lib/module/storage/components/StorageEventActionButton.js +1 -118
  73. package/lib/module/storage/components/StorageEventCard.js +1 -113
  74. package/lib/module/storage/components/StorageEventDetailContent.js +1 -490
  75. package/lib/module/storage/components/StorageEventFilterView.js +1 -156
  76. package/lib/module/storage/components/StorageEventsSection.js +1 -20
  77. package/lib/module/storage/components/StorageFilterCards.js +1 -227
  78. package/lib/module/storage/components/StorageKeyCard.js +1 -517
  79. package/lib/module/storage/components/StorageKeyDetailScreen.js +1 -577
  80. package/lib/module/storage/components/StorageKeyRow.js +1 -554
  81. package/lib/module/storage/components/StorageKeySection.js +1 -155
  82. package/lib/module/storage/components/StorageKeyStats.js +1 -342
  83. package/lib/module/storage/components/StorageModalWithTabs.js +1 -949
  84. package/lib/module/storage/components/StorageSaveNotice.js +1 -168
  85. package/lib/module/storage/components/StorageSection.js +1 -40
  86. package/lib/module/storage/components/StorageTypeFilterBar.js +1 -139
  87. package/lib/module/storage/hooks/useAsyncStorageKeys.js +1 -136
  88. package/lib/module/storage/hooks/useMMKVInstances.js +1 -204
  89. package/lib/module/storage/hooks/useMMKVKeys.js +1 -371
  90. package/lib/module/storage/hooks/useSecureStoreKeys.js +1 -199
  91. package/lib/module/storage/hooks/useStorageEvents.js +1 -58
  92. package/lib/module/storage/stores/storageEventStore.js +1 -301
  93. package/lib/module/storage/sync/storageSyncAdapter.js +1 -486
  94. package/lib/module/storage/types.js +1 -3
  95. package/lib/module/storage/utils/AsyncStorageListener.js +1 -679
  96. package/lib/module/storage/utils/AsyncStorageListener.web.js +1 -76
  97. package/lib/module/storage/utils/MMKVInstanceRegistry.js +1 -197
  98. package/lib/module/storage/utils/MMKVListener.js +1 -403
  99. package/lib/module/storage/utils/SecureStoreRegistry.js +1 -194
  100. package/lib/module/storage/utils/asyncStorageCompat.js +1 -81
  101. package/lib/module/storage/utils/browserStorageLifecycle.js +1 -6
  102. package/lib/module/storage/utils/browserStorageLifecycle.web.js +1 -66
  103. package/lib/module/storage/utils/clearAllStorage.js +1 -43
  104. package/lib/module/storage/utils/deleteStorageKeys.js +1 -78
  105. package/lib/module/storage/utils/lineDiff.js +1 -12
  106. package/lib/module/storage/utils/mmkvAvailability.js +1 -56
  107. package/lib/module/storage/utils/mmkvAvailability.web.js +1 -15
  108. package/lib/module/storage/utils/mmkvTypeDetection.js +1 -148
  109. package/lib/module/storage/utils/requiredStorageKeyScope.js +1 -13
  110. package/lib/module/storage/utils/setStorageValue.js +1 -209
  111. package/lib/module/storage/utils/snapshotProvider.js +1 -380
  112. package/lib/module/storage/utils/storageActionHelpers.js +1 -42
  113. package/lib/module/storage/utils/storageBrowserRefresh.js +1 -44
  114. package/lib/module/storage/utils/storageLabels.js +1 -9
  115. package/lib/module/storage/utils/storageLabels.web.js +1 -9
  116. package/lib/module/storage/utils/storageOps.js +1 -46
  117. package/lib/module/storage/utils/storageQueryUtils.js +1 -30
  118. package/lib/module/storage/utils/storageTimeTravelUtils.js +1 -281
  119. package/lib/module/storage/utils/valueType.js +1 -76
  120. package/lib/web/index.mjs +2 -3
  121. package/package.json +6 -10
  122. package/lib/typescript/index.d.ts.map +0 -1
  123. package/lib/typescript/preset.d.ts.map +0 -1
  124. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +0 -1
  125. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +0 -1
  126. package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts.map +0 -1
  127. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +0 -1
  128. package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts.map +0 -1
  129. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +0 -1
  130. package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +0 -1
  131. package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +0 -1
  132. package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +0 -1
  133. package/lib/typescript/storage/components/StorageEventActionButton.d.ts.map +0 -1
  134. package/lib/typescript/storage/components/StorageEventCard.d.ts.map +0 -1
  135. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +0 -1
  136. package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +0 -1
  137. package/lib/typescript/storage/components/StorageEventsSection.d.ts.map +0 -1
  138. package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +0 -1
  139. package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +0 -1
  140. package/lib/typescript/storage/components/StorageKeyDetailScreen.d.ts.map +0 -1
  141. package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +0 -1
  142. package/lib/typescript/storage/components/StorageKeySection.d.ts.map +0 -1
  143. package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +0 -1
  144. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +0 -1
  145. package/lib/typescript/storage/components/StorageSaveNotice.d.ts.map +0 -1
  146. package/lib/typescript/storage/components/StorageSection.d.ts.map +0 -1
  147. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts.map +0 -1
  148. package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +0 -1
  149. package/lib/typescript/storage/hooks/useMMKVInstances.d.ts.map +0 -1
  150. package/lib/typescript/storage/hooks/useMMKVKeys.d.ts.map +0 -1
  151. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts.map +0 -1
  152. package/lib/typescript/storage/hooks/useStorageEvents.d.ts.map +0 -1
  153. package/lib/typescript/storage/stores/storageEventStore.d.ts.map +0 -1
  154. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts.map +0 -1
  155. package/lib/typescript/storage/types.d.ts.map +0 -1
  156. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +0 -1
  157. package/lib/typescript/storage/utils/AsyncStorageListener.web.d.ts.map +0 -1
  158. package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +0 -1
  159. package/lib/typescript/storage/utils/MMKVListener.d.ts.map +0 -1
  160. package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts.map +0 -1
  161. package/lib/typescript/storage/utils/asyncStorageCompat.d.ts.map +0 -1
  162. package/lib/typescript/storage/utils/browserStorageLifecycle.d.ts.map +0 -1
  163. package/lib/typescript/storage/utils/browserStorageLifecycle.web.d.ts.map +0 -1
  164. package/lib/typescript/storage/utils/clearAllStorage.d.ts.map +0 -1
  165. package/lib/typescript/storage/utils/deleteStorageKeys.d.ts.map +0 -1
  166. package/lib/typescript/storage/utils/lineDiff.d.ts.map +0 -1
  167. package/lib/typescript/storage/utils/mmkvAvailability.d.ts.map +0 -1
  168. package/lib/typescript/storage/utils/mmkvAvailability.web.d.ts.map +0 -1
  169. package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts.map +0 -1
  170. package/lib/typescript/storage/utils/requiredStorageKeyScope.d.ts.map +0 -1
  171. package/lib/typescript/storage/utils/setStorageValue.d.ts.map +0 -1
  172. package/lib/typescript/storage/utils/snapshotProvider.d.ts.map +0 -1
  173. package/lib/typescript/storage/utils/storageActionHelpers.d.ts.map +0 -1
  174. package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts.map +0 -1
  175. package/lib/typescript/storage/utils/storageLabels.d.ts.map +0 -1
  176. package/lib/typescript/storage/utils/storageLabels.web.d.ts.map +0 -1
  177. package/lib/typescript/storage/utils/storageOps.d.ts.map +0 -1
  178. package/lib/typescript/storage/utils/storageQueryUtils.d.ts.map +0 -1
  179. package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts.map +0 -1
  180. package/lib/typescript/storage/utils/valueType.d.ts.map +0 -1
@@ -1,76 +1 @@
1
- "use strict";
2
-
3
- import { subscribeToBrowserStorage } from '@buoy-gg/shared-ui/utils';
4
- const listeners = new Set();
5
- let stop;
6
- let paused = false;
7
- const ignoredKeys = new Set(['@react_buoy_storage_event_filters', '@react_buoy_storage_key_filters', '@react_buoy_storage_is_monitoring', 'REACT_QUERY_OFFLINE_CACHE']);
8
- const ignored = key => [...ignoredKeys].some(prefix => key.startsWith(prefix));
9
- export async function startListening() {
10
- if (stop || typeof window === 'undefined') return;
11
- stop = subscribeToBrowserStorage(change => {
12
- if (paused || change.area !== 'localStorage' || change.key !== undefined && ignored(change.key)) return;
13
- const {
14
- area: _,
15
- action,
16
- ...data
17
- } = change;
18
- if (data.prevPairs) data.prevPairs = data.prevPairs.filter(([key]) => !ignored(key));
19
- const event = {
20
- action,
21
- data,
22
- timestamp: new Date()
23
- };
24
- for (const listener of [...listeners]) {
25
- try {
26
- listener(event);
27
- } catch {/* Keep observing other consumers. */}
28
- }
29
- });
30
- }
31
- export function stopListening() {
32
- stop?.();
33
- stop = undefined;
34
- }
35
- export function addListener(listener) {
36
- listeners.add(listener);
37
- return () => {
38
- listeners.delete(listener);
39
- };
40
- }
41
- export function removeAllListeners() {
42
- listeners.clear();
43
- }
44
- export function isListening() {
45
- return !!stop;
46
- }
47
- export function getListenerCount() {
48
- return listeners.size;
49
- }
50
- export function pauseCapture() {
51
- paused = true;
52
- }
53
- export function resumeCapture() {
54
- paused = false;
55
- }
56
- export function isPaused() {
57
- return paused;
58
- }
59
- const asyncStorageListener = {
60
- startListening,
61
- stopListening,
62
- addListener,
63
- removeAllListeners,
64
- pause: pauseCapture,
65
- resume: resumeCapture,
66
- get isActive() {
67
- return isListening();
68
- },
69
- get listenerCount() {
70
- return listeners.size;
71
- },
72
- get paused() {
73
- return paused;
74
- }
75
- };
76
- export default asyncStorageListener;
1
+ "use strict";import{subscribeToBrowserStorage as f}from"@buoy-gg/shared-ui/utils";const t=new Set;let r;let n=false;const p=new Set(["@react_buoy_storage_event_filters","@react_buoy_storage_key_filters","@react_buoy_storage_is_monitoring","REACT_QUERY_OFFLINE_CACHE"]);const u=e=>[...p].some(i=>e.startsWith(i));export async function startListening(){if(r||typeof window==="undefined")return;r=f(e=>{if(n||e.area!=="localStorage"||e.key!==void 0&&u(e.key))return;const{area:i,action:a,...s}=e;if(s.prevPairs)s.prevPairs=s.prevPairs.filter(([o])=>!u(o));const c={action:a,data:s,timestamp:new Date};for(const o of[...t]){try{o(c)}catch{}}})}export function stopListening(){r?.();r=void 0}export function addListener(e){t.add(e);return()=>{t.delete(e)}}export function removeAllListeners(){t.clear()}export function isListening(){return!!r}export function getListenerCount(){return t.size}export function pauseCapture(){n=true}export function resumeCapture(){n=false}export function isPaused(){return n}const d={startListening,stopListening,addListener,removeAllListeners,pause:pauseCapture,resume:resumeCapture,get isActive(){return isListening()},get listenerCount(){return t.size},get paused(){return n}};export default d;
@@ -1,197 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * MMKV Instance Registry
5
- *
6
- * Centralized registry for tracking all MMKV instances in the application.
7
- * Provides a singleton pattern to manage multiple MMKV instances and their metadata.
8
- *
9
- * @module MMKVInstanceRegistry
10
- * @since 1.0.0
11
- */
12
-
13
- // Static ESM import. This was previously a dynamic `require('./MMKVListener')`
14
- // inside register/unregister "to avoid a circular dependency" — but MMKVListener
15
- // imports only ./mmkvTypeDetection, never this file, so there is no cycle. The
16
- // require() form threw `ReferenceError: require is not defined` when this source
17
- // is bundled as ESM (the desktop dashboard imports it through Vite), crashing on
18
- // StorageInline unmount. A static import behaves identically on Metro and Vite.
19
- import { mmkvListener } from "./MMKVListener";
20
-
21
- /**
22
- * Type-safe representation of an MMKV instance.
23
- * Uses conditional typing to avoid hard dependency on react-native-mmkv.
24
- *
25
- * @public
26
- */
27
-
28
- /**
29
- * Metadata about a registered MMKV instance
30
- *
31
- * @public
32
- */
33
-
34
- /**
35
- * Configuration options for registering an MMKV instance
36
- *
37
- * @public
38
- */
39
-
40
- class MMKVInstanceRegistry {
41
- instances = new Map();
42
-
43
- /**
44
- * Register an MMKV instance for monitoring
45
- *
46
- * @param id - Unique identifier for this instance
47
- * @param instance - The MMKV instance to register
48
- * @param config - Optional configuration (e.g., encrypted flag)
49
- */
50
- register(id, instance, config) {
51
- const instanceInfo = {
52
- id,
53
- instance,
54
- encrypted: config?.encrypted ?? false,
55
- readOnly: instance.isReadOnly ?? false
56
- };
57
- this.instances.set(id, instanceInfo);
58
- }
59
-
60
- /**
61
- * Unregister an MMKV instance
62
- */
63
- unregister(id) {
64
- this.instances.delete(id);
65
- }
66
-
67
- /**
68
- * Get a specific instance by ID
69
- */
70
- get(id) {
71
- return this.instances.get(id);
72
- }
73
-
74
- /**
75
- * Get all registered instances
76
- */
77
- getAll() {
78
- return Array.from(this.instances.values());
79
- }
80
-
81
- /**
82
- * Check if an instance is registered
83
- */
84
- has(id) {
85
- return this.instances.has(id);
86
- }
87
-
88
- /**
89
- * Get count of registered instances
90
- */
91
- count() {
92
- return this.instances.size;
93
- }
94
- }
95
-
96
- // Singleton instance
97
- export const mmkvInstanceRegistry = new MMKVInstanceRegistry();
98
-
99
- /**
100
- * Register an MMKV instance with React Buoy DevTools for monitoring and debugging.
101
- *
102
- * **⚠️ REQUIRED**: Manual registration is required for `react-native-mmkv` v4.
103
- * Auto-detection is not possible due to Metro bundler and ES6 module limitations.
104
- *
105
- * Call this function immediately after creating each MMKV instance you want to monitor.
106
- * The DevTools will then be able to:
107
- * - Display all keys and values
108
- * - Show real-time updates when data changes
109
- * - Allow editing values directly from the DevTools
110
- * - Track storage size and performance
111
- *
112
- * @param id - Unique identifier for this MMKV instance. Should match the `id` you used when creating the instance.
113
- * @param instance - The MMKV instance returned from `createMMKV()`
114
- * @param config - Optional configuration
115
- * @param config.encrypted - Set to `true` if this instance uses encryption (has an `encryptionKey`)
116
- *
117
- * @example
118
- * **Basic usage:**
119
- * ```typescript
120
- * import { createMMKV } from 'react-native-mmkv';
121
- * import { registerMMKVInstance } from '@buoy-gg/storage';
122
- *
123
- * // Create and register default instance
124
- * export const storage = createMMKV({ id: 'mmkv.default' });
125
- * registerMMKVInstance('mmkv.default', storage);
126
- * ```
127
- *
128
- * @example
129
- * **With encryption:**
130
- * ```typescript
131
- * import { createMMKV } from 'react-native-mmkv';
132
- * import { registerMMKVInstance } from '@buoy-gg/storage';
133
- *
134
- * // Create encrypted instance
135
- * export const secureStorage = createMMKV({
136
- * id: 'secure-storage',
137
- * encryptionKey: 'my-encryption-key'
138
- * });
139
- *
140
- * // Register with encrypted flag
141
- * registerMMKVInstance('secure-storage', secureStorage, { encrypted: true });
142
- * ```
143
- *
144
- * @example
145
- * **Multiple instances:**
146
- * ```typescript
147
- * import { createMMKV } from 'react-native-mmkv';
148
- * import { registerMMKVInstance } from '@buoy-gg/storage';
149
- *
150
- * // User preferences
151
- * export const userPrefs = createMMKV({ id: 'user-prefs' });
152
- * registerMMKVInstance('user-prefs', userPrefs);
153
- *
154
- * // Cache
155
- * export const cache = createMMKV({ id: 'cache' });
156
- * registerMMKVInstance('cache', cache);
157
- *
158
- * // Auth (encrypted)
159
- * export const auth = createMMKV({ id: 'auth', encryptionKey: 'key' });
160
- * registerMMKVInstance('auth', auth, { encrypted: true });
161
- * ```
162
- *
163
- * @public
164
- * @since 1.0.0
165
- */
166
- export function registerMMKVInstance(id, instance, config) {
167
- // Register in registry
168
- mmkvInstanceRegistry.register(id, instance, config);
169
-
170
- // Add listener for real-time monitoring (CRITICAL: enables event emission)
171
- // v4: Use ONLY native listener (addOnValueChangedListener), skip method wrapping
172
- mmkvListener.addInstance(instance, id);
173
- }
174
-
175
- /**
176
- * Unregister an MMKV instance from DevTools monitoring.
177
- *
178
- * This stops the DevTools from tracking changes to this instance.
179
- * Typically not needed unless you're dynamically creating/destroying instances.
180
- *
181
- * @param id - The instance ID to unregister
182
- *
183
- * @example
184
- * ```typescript
185
- * unregisterMMKVInstance('cache');
186
- * ```
187
- *
188
- * @public
189
- * @since 1.0.0
190
- */
191
- export function unregisterMMKVInstance(id) {
192
- // Remove listener first
193
- mmkvListener.removeInstance(id);
194
-
195
- // Then remove from registry
196
- mmkvInstanceRegistry.unregister(id);
197
- }
1
+ "use strict";import{mmkvListener as n}from"./MMKVListener";class a{instances=new Map;register(e,s,r){const i={id:e,instance:s,encrypted:r?.encrypted??false,readOnly:s.isReadOnly??false};this.instances.set(e,i)}unregister(e){this.instances.delete(e)}get(e){return this.instances.get(e)}getAll(){return Array.from(this.instances.values())}has(e){return this.instances.has(e)}count(){return this.instances.size}}export const mmkvInstanceRegistry=new a;export function registerMMKVInstance(t,e,s){mmkvInstanceRegistry.register(t,e,s);n.addInstance(e,t)}export function unregisterMMKVInstance(t){n.removeInstance(t);mmkvInstanceRegistry.unregister(t)}
@@ -1,403 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * MMKVListener - Hybrid Monitoring Strategy
5
- *
6
- * This module provides comprehensive monitoring for MMKV storage instances using
7
- * a hybrid approach that combines:
8
- *
9
- * 1. MMKV's built-in addOnValueChangedListener() - for write operations
10
- * 2. Method wrapping - for read operations and type detection
11
- *
12
- * Why Hybrid Strategy?
13
- * - MMKV listeners only fire on writes (set/delete), not reads
14
- * - MMKV listeners don't provide value type information
15
- * - Method wrapping captures ALL operations with full context
16
- * - Combining both gives complete observability
17
- *
18
- * Key Differences from AsyncStorage:
19
- * - Synchronous API (no async/await needed)
20
- * - Multi-instance support (track multiple MMKV instances)
21
- * - Native types (string, number, boolean, buffer)
22
- * - Built-in listener support (MMKV.addOnValueChangedListener)
23
- *
24
- * @see AsyncStorageListener.ts for AsyncStorage equivalent
25
- */
26
-
27
- // Use 'any' type for MMKV to avoid hard dependency on react-native-mmkv
28
-
29
- import { detectMMKVType } from "./mmkvTypeDetection";
30
-
31
- // MMKV method signatures
32
-
33
- /**
34
- * Event types for MMKV operations
35
- */
36
-
37
- /**
38
- * Instance tracking for MMKV monitoring
39
- */
40
-
41
- /**
42
- * Singleton class for monitoring MMKV operations across multiple instances
43
- *
44
- * Uses a hybrid monitoring strategy:
45
- * 1. MMKV's built-in listener API for write notifications
46
- * 2. Method wrapping for read operations and type information
47
- *
48
- * @example
49
- * ```typescript
50
- * import { MMKV } from 'react-native-mmkv';
51
- * import { mmkvListener } from './MMKVListener';
52
- *
53
- * const storage = new MMKV();
54
- *
55
- * // Start monitoring this instance
56
- * mmkvListener.addInstance(storage, 'mmkv.default');
57
- *
58
- * // Add listener for all MMKV events
59
- * const unsubscribe = mmkvListener.addListener((event) => {
60
- * console.log(`[${event.instanceId}] ${event.action}:`, event.data);
61
- * });
62
- *
63
- * // Cleanup
64
- * unsubscribe();
65
- * mmkvListener.removeInstance('mmkv.default');
66
- * ```
67
- */
68
- class MMKVListener {
69
- listeners = [];
70
- instances = new Map();
71
-
72
- // Keys to ignore to prevent dev tools from triggering self-events
73
- ignoredKeys = new Set(["@react_buoy_storage_event_filters", "@react_buoy_storage_key_filters", "@react_buoy_storage_is_monitoring", "REACT_QUERY_OFFLINE_CACHE"]);
74
-
75
- /**
76
- * Determines if a storage key should be ignored
77
- */
78
- shouldIgnoreKey(key) {
79
- if (this.ignoredKeys.has(key)) return true;
80
- for (const ignoredKey of this.ignoredKeys) {
81
- if (key.startsWith(ignoredKey)) return true;
82
- }
83
- return false;
84
- }
85
-
86
- /**
87
- * Emit an MMKV event to all registered listeners
88
- */
89
- emit(event) {
90
- if (this.listeners.length === 0) return;
91
- this.listeners.forEach(listener => {
92
- try {
93
- listener(event);
94
- } catch (error) {
95
- // Error in MMKV event listener - continuing with others
96
- }
97
- });
98
- }
99
-
100
- /**
101
- * Add an MMKV instance for monitoring
102
- *
103
- * This method sets up both native MMKV listeners and method wrapping
104
- * to provide complete observability.
105
- *
106
- * @param instance - MMKV instance to monitor
107
- * @param instanceId - Unique identifier for this instance
108
- *
109
- * @example
110
- * ```typescript
111
- * const storage = new MMKV();
112
- * mmkvListener.addInstance(storage, 'mmkv.default');
113
- *
114
- * const secureStorage = new MMKV({ id: 'secure', encryptionKey: key });
115
- * mmkvListener.addInstance(secureStorage, 'secure');
116
- * ```
117
- */
118
- addInstance(instance, instanceId) {
119
- // Check if already monitoring this instance
120
- if (this.instances.has(instanceId)) {
121
- return;
122
- }
123
-
124
- // v4 COMPATIBILITY: Use ONLY native listener (no method wrapping)
125
- // react-native-mmkv v4 instances have frozen/read-only methods that cannot be wrapped
126
- // The native listener (addOnValueChangedListener) is sufficient for monitoring writes
127
-
128
- let nativeListenerUnsubscribe;
129
-
130
- // Seed the shadow copy so the FIRST observed write already knows what it
131
- // replaced. Without this, every key's first event would claim the key never
132
- // existed even when it was carried over from a previous launch.
133
- const lastKnownValues = new Map();
134
- try {
135
- for (const key of instance.getAllKeys() ?? []) {
136
- if (this.shouldIgnoreKey(key)) continue;
137
- lastKnownValues.set(key, detectMMKVType(instance, key).value);
138
- }
139
- } catch {
140
- // Key scan unavailable — prevValue is simply absent until each key is
141
- // written once, which is strictly better than reporting a wrong value.
142
- }
143
- if (typeof instance.addOnValueChangedListener === "function") {
144
- try {
145
- nativeListenerUnsubscribe = instance.addOnValueChangedListener(key => {
146
- // Ignore dev tools keys
147
- if (this.shouldIgnoreKey(key)) return;
148
-
149
- // Detect the value type
150
- const {
151
- value,
152
- type
153
- } = detectMMKVType(instance, key);
154
-
155
- // Read the shadow copy BEFORE overwriting it — this is the value the
156
- // write replaced. `undefined` means the key did not exist.
157
- const prevValue = lastKnownValues.get(key);
158
-
159
- // Determine action: if value is undefined/unknown, it was deleted
160
- const isDelete = type === "unknown" || value === undefined;
161
- if (isDelete) {
162
- lastKnownValues.delete(key);
163
-
164
- // Key was deleted
165
- const event = {
166
- action: "delete",
167
- timestamp: new Date(),
168
- instanceId,
169
- data: {
170
- key,
171
- prevValue,
172
- success: true
173
- }
174
- };
175
- this.emit(event);
176
- } else {
177
- lastKnownValues.set(key, value);
178
-
179
- // Key was set/updated
180
- const action = type === "string" ? "set.string" : type === "number" ? "set.number" : type === "boolean" ? "set.boolean" : type === "buffer" ? "set.buffer" : "set.string"; // fallback
181
-
182
- const event = {
183
- action,
184
- timestamp: new Date(),
185
- instanceId,
186
- data: {
187
- key,
188
- value,
189
- prevValue,
190
- valueType: type,
191
- success: true
192
- }
193
- };
194
- this.emit(event);
195
- }
196
- });
197
- } catch (error) {
198
- // Could not add native listener
199
- }
200
- }
201
-
202
- // Store instance tracking (no originalMethods needed for v4)
203
- this.instances.set(instanceId, {
204
- instance,
205
- instanceId,
206
- originalMethods: {},
207
- // Not used in v4
208
- nativeListenerUnsubscribe,
209
- lastKnownValues
210
- });
211
- }
212
-
213
- /**
214
- * Remove an MMKV instance from monitoring
215
- *
216
- * Restores original methods and removes native listener.
217
- *
218
- * @param instanceId - Identifier of instance to stop monitoring
219
- */
220
- removeInstance(instanceId) {
221
- const tracked = this.instances.get(instanceId);
222
- if (!tracked) {
223
- return;
224
- }
225
- const {
226
- nativeListenerUnsubscribe
227
- } = tracked;
228
-
229
- // Remove native listener. The return of addOnValueChangedListener varies by
230
- // implementation: a bare unsubscribe function, or a Listener object with a
231
- // `.remove()` method (react-native-mmkv v4 and the desktop RemoteMMKV
232
- // back-end). Handle both, and never let teardown throw — this runs during
233
- // React unmount, where an exception escapes every error boundary and blanks
234
- // the whole app.
235
- try {
236
- if (typeof nativeListenerUnsubscribe === "function") {
237
- nativeListenerUnsubscribe();
238
- } else if (typeof nativeListenerUnsubscribe?.remove === "function") {
239
- nativeListenerUnsubscribe.remove();
240
- }
241
- } catch {
242
- /* listener already gone / back-end offline — nothing to clean up */
243
- }
244
-
245
- // Remove from tracking
246
- this.instances.delete(instanceId);
247
- }
248
-
249
- /**
250
- * Remove all monitored instances
251
- */
252
- removeAllInstances() {
253
- const instanceIds = Array.from(this.instances.keys());
254
- instanceIds.forEach(id => this.removeInstance(id));
255
- }
256
-
257
- /**
258
- * Add a listener for MMKV events across all monitored instances
259
- *
260
- * @param listener - Callback function to handle MMKV events
261
- * @returns Unsubscribe function to remove the listener
262
- *
263
- * @example
264
- * ```typescript
265
- * const unsubscribe = mmkvListener.addListener((event) => {
266
- * console.log(`[${event.instanceId}] ${event.action}:`, event.data);
267
- * });
268
- *
269
- * // Later, remove the listener
270
- * unsubscribe();
271
- * ```
272
- */
273
- addListener(listener) {
274
- this.listeners.push(listener);
275
-
276
- // Return unsubscribe function
277
- return () => {
278
- const index = this.listeners.indexOf(listener);
279
- if (index > -1) {
280
- this.listeners.splice(index, 1);
281
- }
282
- };
283
- }
284
-
285
- /**
286
- * Remove all registered event listeners
287
- */
288
- removeAllListeners() {
289
- this.listeners = [];
290
- }
291
-
292
- /**
293
- * Check if an instance is currently being monitored
294
- */
295
- hasInstance(instanceId) {
296
- return this.instances.has(instanceId);
297
- }
298
-
299
- /**
300
- * Get list of all monitored instance IDs
301
- */
302
- getMonitoredInstances() {
303
- return Array.from(this.instances.keys());
304
- }
305
-
306
- /**
307
- * Get the number of currently monitored instances
308
- */
309
- get instanceCount() {
310
- return this.instances.size;
311
- }
312
-
313
- /**
314
- * Get the number of currently registered event listeners
315
- */
316
- get listenerCount() {
317
- return this.listeners.length;
318
- }
319
-
320
- /**
321
- * Check if any instances are being monitored
322
- */
323
- get isActive() {
324
- return this.instances.size > 0;
325
- }
326
- }
327
-
328
- /**
329
- * Singleton instance of MMKVListener
330
- *
331
- * This ensures only one listener manager exists across the entire application.
332
- */
333
- export const mmkvListener = new MMKVListener();
334
-
335
- /**
336
- * Add an MMKV instance for monitoring
337
- *
338
- * @param instance - MMKV instance to monitor
339
- * @param instanceId - Unique identifier for this instance
340
- *
341
- * @example
342
- * ```typescript
343
- * import { MMKV } from 'react-native-mmkv';
344
- * import { addMMKVInstance } from '@buoy-gg/storage';
345
- *
346
- * const storage = new MMKV();
347
- * addMMKVInstance(storage, 'mmkv.default');
348
- * ```
349
- */
350
- export const addMMKVInstance = (instance, instanceId) => mmkvListener.addInstance(instance, instanceId);
351
-
352
- /**
353
- * Remove an MMKV instance from monitoring
354
- */
355
- export const removeMMKVInstance = instanceId => mmkvListener.removeInstance(instanceId);
356
-
357
- /**
358
- * Remove all monitored MMKV instances
359
- */
360
- export const removeAllMMKVInstances = () => mmkvListener.removeAllInstances();
361
-
362
- /**
363
- * Add an event listener for MMKV operations
364
- *
365
- * @param listener - Callback function to handle events
366
- * @returns Unsubscribe function to remove the listener
367
- */
368
- export const addMMKVListener = listener => mmkvListener.addListener(listener);
369
-
370
- /**
371
- * Remove all registered event listeners
372
- */
373
- export const removeAllMMKVListeners = () => mmkvListener.removeAllListeners();
374
-
375
- /**
376
- * Check if an MMKV instance is currently being monitored
377
- */
378
- export const isMMKVInstanceMonitored = instanceId => mmkvListener.hasInstance(instanceId);
379
-
380
- /**
381
- * Get list of all monitored MMKV instance IDs
382
- */
383
- export const getMonitoredMMKVInstances = () => mmkvListener.getMonitoredInstances();
384
-
385
- /**
386
- * Get the current number of monitored MMKV instances
387
- */
388
- export const getMMKVInstanceCount = () => mmkvListener.instanceCount;
389
-
390
- /**
391
- * Get the current number of registered event listeners
392
- */
393
- export const getMMKVListenerCount = () => mmkvListener.listenerCount;
394
-
395
- /**
396
- * Check if any MMKV instances are being monitored
397
- */
398
- export const isMMKVListening = () => mmkvListener.isActive;
399
-
400
- /**
401
- * Export the singleton instance for advanced usage
402
- */
403
- export default mmkvListener;
1
+ "use strict";import{detectMMKVType as l}from"./mmkvTypeDetection";class f{listeners=[];instances=new Map;ignoredKeys=new Set(["@react_buoy_storage_event_filters","@react_buoy_storage_key_filters","@react_buoy_storage_is_monitoring","REACT_QUERY_OFFLINE_CACHE"]);shouldIgnoreKey(e){if(this.ignoredKeys.has(e))return true;for(const t of this.ignoredKeys){if(e.startsWith(t))return true}return false}emit(e){if(this.listeners.length===0)return;this.listeners.forEach(t=>{try{t(e)}catch(r){}})}addInstance(e,t){if(this.instances.has(t)){return}let r;const o=new Map;try{for(const s of e.getAllKeys()??[]){if(this.shouldIgnoreKey(s))continue;o.set(s,l(e,s).value)}}catch{}if(typeof e.addOnValueChangedListener==="function"){try{r=e.addOnValueChangedListener(s=>{if(this.shouldIgnoreKey(s))return;const{value:a,type:i}=l(e,s);const u=o.get(s);const h=i==="unknown"||a===void 0;if(h){o.delete(s);const c={action:"delete",timestamp:new Date,instanceId:t,data:{key:s,prevValue:u,success:true}};this.emit(c)}else{o.set(s,a);const c=i==="string"?"set.string":i==="number"?"set.number":i==="boolean"?"set.boolean":i==="buffer"?"set.buffer":"set.string";const d={action:c,timestamp:new Date,instanceId:t,data:{key:s,value:a,prevValue:u,valueType:i,success:true}};this.emit(d)}})}catch(s){}}this.instances.set(t,{instance:e,instanceId:t,originalMethods:{},nativeListenerUnsubscribe:r,lastKnownValues:o})}removeInstance(e){const t=this.instances.get(e);if(!t){return}const{nativeListenerUnsubscribe:r}=t;try{if(typeof r==="function"){r()}else if(typeof r?.remove==="function"){r.remove()}}catch{}this.instances.delete(e)}removeAllInstances(){const e=Array.from(this.instances.keys());e.forEach(t=>this.removeInstance(t))}addListener(e){this.listeners.push(e);return()=>{const t=this.listeners.indexOf(e);if(t>-1){this.listeners.splice(t,1)}}}removeAllListeners(){this.listeners=[]}hasInstance(e){return this.instances.has(e)}getMonitoredInstances(){return Array.from(this.instances.keys())}get instanceCount(){return this.instances.size}get listenerCount(){return this.listeners.length}get isActive(){return this.instances.size>0}}export const mmkvListener=new f;export const addMMKVInstance=(n,e)=>mmkvListener.addInstance(n,e);export const removeMMKVInstance=n=>mmkvListener.removeInstance(n);export const removeAllMMKVInstances=()=>mmkvListener.removeAllInstances();export const addMMKVListener=n=>mmkvListener.addListener(n);export const removeAllMMKVListeners=()=>mmkvListener.removeAllListeners();export const isMMKVInstanceMonitored=n=>mmkvListener.hasInstance(n);export const getMonitoredMMKVInstances=()=>mmkvListener.getMonitoredInstances();export const getMMKVInstanceCount=()=>mmkvListener.instanceCount;export const getMMKVListenerCount=()=>mmkvListener.listenerCount;export const isMMKVListening=()=>mmkvListener.isActive;export default mmkvListener;