@buoy-gg/storage 1.7.2

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 (187) hide show
  1. package/README.md +607 -0
  2. package/lib/commonjs/index.js +34 -0
  3. package/lib/commonjs/package.json +1 -0
  4. package/lib/commonjs/preset.js +94 -0
  5. package/lib/commonjs/storage/components/DiffViewer/DiffOptionsPanel.js +356 -0
  6. package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +29 -0
  7. package/lib/commonjs/storage/components/DiffViewer/components/DiffSummary.js +121 -0
  8. package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +419 -0
  9. package/lib/commonjs/storage/components/DiffViewer/themes/diffThemes.js +122 -0
  10. package/lib/commonjs/storage/components/GameUIStorageBrowser.js +924 -0
  11. package/lib/commonjs/storage/components/GameUIStorageStats.js +746 -0
  12. package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +257 -0
  13. package/lib/commonjs/storage/components/MMKVInstanceSelector.js +418 -0
  14. package/lib/commonjs/storage/components/SelectionActionBar.js +224 -0
  15. package/lib/commonjs/storage/components/StorageActionButtons.js +239 -0
  16. package/lib/commonjs/storage/components/StorageActions.js +192 -0
  17. package/lib/commonjs/storage/components/StorageBrowserMode.js +31 -0
  18. package/lib/commonjs/storage/components/StorageEventDetailContent.js +1025 -0
  19. package/lib/commonjs/storage/components/StorageEventFilterView.js +141 -0
  20. package/lib/commonjs/storage/components/StorageEventListener.js +357 -0
  21. package/lib/commonjs/storage/components/StorageEventsSection.js +24 -0
  22. package/lib/commonjs/storage/components/StorageFilterCards.js +345 -0
  23. package/lib/commonjs/storage/components/StorageFilterViewV2.js +42 -0
  24. package/lib/commonjs/storage/components/StorageKeyCard.js +516 -0
  25. package/lib/commonjs/storage/components/StorageKeyRow.js +356 -0
  26. package/lib/commonjs/storage/components/StorageKeySection.js +105 -0
  27. package/lib/commonjs/storage/components/StorageKeyStats.js +344 -0
  28. package/lib/commonjs/storage/components/StorageModalWithTabs.js +871 -0
  29. package/lib/commonjs/storage/components/StorageSection.js +43 -0
  30. package/lib/commonjs/storage/hooks/useAsyncStorageKeys.js +126 -0
  31. package/lib/commonjs/storage/hooks/useMMKVInstances.js +221 -0
  32. package/lib/commonjs/storage/hooks/useMMKVKeys.js +362 -0
  33. package/lib/commonjs/storage/hooks/useTickEverySecond.js +21 -0
  34. package/lib/commonjs/storage/index.js +148 -0
  35. package/lib/commonjs/storage/types.js +5 -0
  36. package/lib/commonjs/storage/utils/AsyncStorageListener.js +510 -0
  37. package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +202 -0
  38. package/lib/commonjs/storage/utils/MMKVListener.js +380 -0
  39. package/lib/commonjs/storage/utils/clearAllStorage.js +47 -0
  40. package/lib/commonjs/storage/utils/index.js +180 -0
  41. package/lib/commonjs/storage/utils/lineDiff.js +363 -0
  42. package/lib/commonjs/storage/utils/mmkvAvailability.js +62 -0
  43. package/lib/commonjs/storage/utils/mmkvTypeDetection.js +139 -0
  44. package/lib/commonjs/storage/utils/objectDiff.js +157 -0
  45. package/lib/commonjs/storage/utils/safeAsyncStorage.js +140 -0
  46. package/lib/commonjs/storage/utils/storageActionHelpers.js +46 -0
  47. package/lib/commonjs/storage/utils/storageQueryUtils.js +35 -0
  48. package/lib/commonjs/storage/utils/valueType.js +18 -0
  49. package/lib/module/index.js +7 -0
  50. package/lib/module/preset.js +89 -0
  51. package/lib/module/storage/components/DiffViewer/DiffOptionsPanel.js +352 -0
  52. package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +25 -0
  53. package/lib/module/storage/components/DiffViewer/components/DiffSummary.js +117 -0
  54. package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +415 -0
  55. package/lib/module/storage/components/DiffViewer/themes/diffThemes.js +118 -0
  56. package/lib/module/storage/components/GameUIStorageBrowser.js +922 -0
  57. package/lib/module/storage/components/GameUIStorageStats.js +742 -0
  58. package/lib/module/storage/components/MMKVInstanceInfoPanel.js +253 -0
  59. package/lib/module/storage/components/MMKVInstanceSelector.js +414 -0
  60. package/lib/module/storage/components/SelectionActionBar.js +221 -0
  61. package/lib/module/storage/components/StorageActionButtons.js +236 -0
  62. package/lib/module/storage/components/StorageActions.js +189 -0
  63. package/lib/module/storage/components/StorageBrowserMode.js +27 -0
  64. package/lib/module/storage/components/StorageEventDetailContent.js +1020 -0
  65. package/lib/module/storage/components/StorageEventFilterView.js +137 -0
  66. package/lib/module/storage/components/StorageEventListener.js +354 -0
  67. package/lib/module/storage/components/StorageEventsSection.js +20 -0
  68. package/lib/module/storage/components/StorageFilterCards.js +341 -0
  69. package/lib/module/storage/components/StorageFilterViewV2.js +38 -0
  70. package/lib/module/storage/components/StorageKeyCard.js +513 -0
  71. package/lib/module/storage/components/StorageKeyRow.js +353 -0
  72. package/lib/module/storage/components/StorageKeySection.js +101 -0
  73. package/lib/module/storage/components/StorageKeyStats.js +340 -0
  74. package/lib/module/storage/components/StorageModalWithTabs.js +867 -0
  75. package/lib/module/storage/components/StorageSection.js +40 -0
  76. package/lib/module/storage/hooks/useAsyncStorageKeys.js +121 -0
  77. package/lib/module/storage/hooks/useMMKVInstances.js +216 -0
  78. package/lib/module/storage/hooks/useMMKVKeys.js +359 -0
  79. package/lib/module/storage/hooks/useTickEverySecond.js +18 -0
  80. package/lib/module/storage/index.js +25 -0
  81. package/lib/module/storage/types.js +3 -0
  82. package/lib/module/storage/utils/AsyncStorageListener.js +500 -0
  83. package/lib/module/storage/utils/MMKVInstanceRegistry.js +196 -0
  84. package/lib/module/storage/utils/MMKVListener.js +367 -0
  85. package/lib/module/storage/utils/clearAllStorage.js +42 -0
  86. package/lib/module/storage/utils/index.js +22 -0
  87. package/lib/module/storage/utils/lineDiff.js +359 -0
  88. package/lib/module/storage/utils/mmkvAvailability.js +56 -0
  89. package/lib/module/storage/utils/mmkvTypeDetection.js +133 -0
  90. package/lib/module/storage/utils/objectDiff.js +153 -0
  91. package/lib/module/storage/utils/safeAsyncStorage.js +134 -0
  92. package/lib/module/storage/utils/storageActionHelpers.js +42 -0
  93. package/lib/module/storage/utils/storageQueryUtils.js +30 -0
  94. package/lib/module/storage/utils/valueType.js +14 -0
  95. package/lib/typescript/index.d.ts +3 -0
  96. package/lib/typescript/index.d.ts.map +1 -0
  97. package/lib/typescript/preset.d.ts +90 -0
  98. package/lib/typescript/preset.d.ts.map +1 -0
  99. package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts +18 -0
  100. package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts.map +1 -0
  101. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts +7 -0
  102. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +1 -0
  103. package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts +12 -0
  104. package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts.map +1 -0
  105. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts +13 -0
  106. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +1 -0
  107. package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts +64 -0
  108. package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts.map +1 -0
  109. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts +16 -0
  110. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +1 -0
  111. package/lib/typescript/storage/components/GameUIStorageStats.d.ts +7 -0
  112. package/lib/typescript/storage/components/GameUIStorageStats.d.ts.map +1 -0
  113. package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts +42 -0
  114. package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts.map +1 -0
  115. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts +35 -0
  116. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +1 -0
  117. package/lib/typescript/storage/components/SelectionActionBar.d.ts +21 -0
  118. package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +1 -0
  119. package/lib/typescript/storage/components/StorageActionButtons.d.ts +21 -0
  120. package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +1 -0
  121. package/lib/typescript/storage/components/StorageActions.d.ts +10 -0
  122. package/lib/typescript/storage/components/StorageActions.d.ts.map +1 -0
  123. package/lib/typescript/storage/components/StorageBrowserMode.d.ts +18 -0
  124. package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +1 -0
  125. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts +40 -0
  126. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +1 -0
  127. package/lib/typescript/storage/components/StorageEventFilterView.d.ts +11 -0
  128. package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +1 -0
  129. package/lib/typescript/storage/components/StorageEventListener.d.ts +6 -0
  130. package/lib/typescript/storage/components/StorageEventListener.d.ts.map +1 -0
  131. package/lib/typescript/storage/components/StorageEventsSection.d.ts +7 -0
  132. package/lib/typescript/storage/components/StorageEventsSection.d.ts.map +1 -0
  133. package/lib/typescript/storage/components/StorageFilterCards.d.ts +36 -0
  134. package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +1 -0
  135. package/lib/typescript/storage/components/StorageFilterViewV2.d.ts +9 -0
  136. package/lib/typescript/storage/components/StorageFilterViewV2.d.ts.map +1 -0
  137. package/lib/typescript/storage/components/StorageKeyCard.d.ts +17 -0
  138. package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +1 -0
  139. package/lib/typescript/storage/components/StorageKeyRow.d.ts +15 -0
  140. package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +1 -0
  141. package/lib/typescript/storage/components/StorageKeySection.d.ts +25 -0
  142. package/lib/typescript/storage/components/StorageKeySection.d.ts.map +1 -0
  143. package/lib/typescript/storage/components/StorageKeyStats.d.ts +15 -0
  144. package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +1 -0
  145. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts +13 -0
  146. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +1 -0
  147. package/lib/typescript/storage/components/StorageSection.d.ts +10 -0
  148. package/lib/typescript/storage/components/StorageSection.d.ts.map +1 -0
  149. package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts +10 -0
  150. package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +1 -0
  151. package/lib/typescript/storage/hooks/useMMKVInstances.d.ts +114 -0
  152. package/lib/typescript/storage/hooks/useMMKVInstances.d.ts.map +1 -0
  153. package/lib/typescript/storage/hooks/useMMKVKeys.d.ts +94 -0
  154. package/lib/typescript/storage/hooks/useMMKVKeys.d.ts.map +1 -0
  155. package/lib/typescript/storage/hooks/useTickEverySecond.d.ts +6 -0
  156. package/lib/typescript/storage/hooks/useTickEverySecond.d.ts.map +1 -0
  157. package/lib/typescript/storage/index.d.ts +15 -0
  158. package/lib/typescript/storage/index.d.ts.map +1 -0
  159. package/lib/typescript/storage/types.d.ts +41 -0
  160. package/lib/typescript/storage/types.d.ts.map +1 -0
  161. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts +195 -0
  162. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +1 -0
  163. package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts +224 -0
  164. package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +1 -0
  165. package/lib/typescript/storage/utils/MMKVListener.d.ts +218 -0
  166. package/lib/typescript/storage/utils/MMKVListener.d.ts.map +1 -0
  167. package/lib/typescript/storage/utils/clearAllStorage.d.ts +11 -0
  168. package/lib/typescript/storage/utils/clearAllStorage.d.ts.map +1 -0
  169. package/lib/typescript/storage/utils/index.d.ts +8 -0
  170. package/lib/typescript/storage/utils/index.d.ts.map +1 -0
  171. package/lib/typescript/storage/utils/lineDiff.d.ts +34 -0
  172. package/lib/typescript/storage/utils/lineDiff.d.ts.map +1 -0
  173. package/lib/typescript/storage/utils/mmkvAvailability.d.ts +23 -0
  174. package/lib/typescript/storage/utils/mmkvAvailability.d.ts.map +1 -0
  175. package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts +71 -0
  176. package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts.map +1 -0
  177. package/lib/typescript/storage/utils/objectDiff.d.ts +35 -0
  178. package/lib/typescript/storage/utils/objectDiff.d.ts.map +1 -0
  179. package/lib/typescript/storage/utils/safeAsyncStorage.d.ts +56 -0
  180. package/lib/typescript/storage/utils/safeAsyncStorage.d.ts.map +1 -0
  181. package/lib/typescript/storage/utils/storageActionHelpers.d.ts +5 -0
  182. package/lib/typescript/storage/utils/storageActionHelpers.d.ts.map +1 -0
  183. package/lib/typescript/storage/utils/storageQueryUtils.d.ts +6 -0
  184. package/lib/typescript/storage/utils/storageQueryUtils.d.ts.map +1 -0
  185. package/lib/typescript/storage/utils/valueType.d.ts +3 -0
  186. package/lib/typescript/storage/utils/valueType.d.ts.map +1 -0
  187. package/package.json +68 -0
@@ -0,0 +1,510 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.stopListening = exports.startListening = exports.removeAllListeners = exports.isListening = exports.getListenerCount = exports.default = exports.addListener = void 0;
7
+ var _asyncStorage = _interopRequireDefault(require("@react-native-async-storage/async-storage"));
8
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
9
+ // AsyncStorage method signatures - matching the actual AsyncStorage API
10
+
11
+ // Event types for AsyncStorage operations
12
+
13
+ /**
14
+ * Singleton class for intercepting and monitoring AsyncStorage operations
15
+ *
16
+ * This class uses method swizzling to intercept all AsyncStorage operations
17
+ * (setItem, removeItem, mergeItem, clear, multiSet, multiRemove, multiMerge)
18
+ * and emits events to registered listeners. It maintains the original functionality
19
+ * while providing observability for debugging and development tools.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * // Start listening to all AsyncStorage operations
24
+ * startListening();
25
+ *
26
+ * // Add a listener for storage events
27
+ * const unsubscribe = addListener((event) => {
28
+ * console.log(`${event.action}:`, event.data);
29
+ * });
30
+ *
31
+ * // Clean up
32
+ * unsubscribe();
33
+ * stopListening();
34
+ * ```
35
+ *
36
+ * @performance Uses method interception rather than polling for zero-overhead when inactive
37
+ * @performance Includes key filtering to prevent dev tools from triggering self-events
38
+ */
39
+ class AsyncStorageListener {
40
+ listeners = [];
41
+ isListening = false;
42
+ isInitialized = false;
43
+
44
+ // Keys to ignore for dev tools to prevent self-triggering
45
+ // Only ignore specific keys that would cause infinite loops in the storage browser
46
+ ignoredKeys = new Set(["@react_buoy_storage_event_filters",
47
+ // Storage events filter settings
48
+ "@react_buoy_storage_key_filters",
49
+ // Storage browser key filters
50
+ "@react_buoy_storage_is_monitoring",
51
+ // Storage monitoring toggle
52
+ "REACT_QUERY_OFFLINE_CACHE" // React Query cache
53
+ ]);
54
+
55
+ // Store original methods
56
+ originalSetItem = null;
57
+ originalRemoveItem = null;
58
+ originalMergeItem = null;
59
+ originalClear = null;
60
+ originalMultiSet = null;
61
+ originalMultiRemove = null;
62
+ originalMultiMerge = null;
63
+
64
+ /**
65
+ * Determines if a storage key should be ignored to prevent infinite loops
66
+ *
67
+ * Dev tools often store their own state in AsyncStorage, which would trigger
68
+ * events and cause infinite loops or unnecessary noise.
69
+ *
70
+ * @param key - The storage key to check
71
+ * @returns True if the key should be ignored, false otherwise
72
+ */
73
+ shouldIgnoreKey(key) {
74
+ // Check exact matches
75
+ if (this.ignoredKeys.has(key)) return true;
76
+
77
+ // Check prefix matches
78
+ for (const ignoredKey of this.ignoredKeys) {
79
+ if (key.startsWith(ignoredKey)) return true;
80
+ }
81
+ return false;
82
+ }
83
+
84
+ /**
85
+ * Initialize the listener by loading AsyncStorage and storing original methods
86
+ *
87
+ * This method performs safety checks to ensure we don't double-initialize
88
+ * and verifies that AsyncStorage methods haven't already been swizzled.
89
+ *
90
+ * @returns Promise<boolean> - True if initialization succeeded, false otherwise
91
+ *
92
+ * @throws Will log errors if AsyncStorage is already swizzled by another instance
93
+ */
94
+ async initialize() {
95
+ if (this.isInitialized) {
96
+ // Already initialized - skipping
97
+ return true;
98
+ }
99
+
100
+ // Check if methods are already swizzled by checking the function name
101
+ if (_asyncStorage.default.setItem.name === "swizzled_setItem") {
102
+ // Don't store swizzled methods as originals
103
+ return false;
104
+ }
105
+
106
+ // Store original methods (these should be the real AsyncStorage methods)
107
+ this.originalSetItem = _asyncStorage.default.setItem.bind(_asyncStorage.default);
108
+ this.originalRemoveItem = _asyncStorage.default.removeItem.bind(_asyncStorage.default);
109
+ this.originalMergeItem = _asyncStorage.default.mergeItem.bind(_asyncStorage.default);
110
+ this.originalClear = _asyncStorage.default.clear.bind(_asyncStorage.default);
111
+ this.originalMultiSet = _asyncStorage.default.multiSet.bind(_asyncStorage.default);
112
+ this.originalMultiRemove = _asyncStorage.default.multiRemove.bind(_asyncStorage.default);
113
+ this.originalMultiMerge = _asyncStorage.default.multiMerge ? _asyncStorage.default.multiMerge.bind(_asyncStorage.default) : null;
114
+
115
+ // Original methods stored successfully
116
+ this.isInitialized = true;
117
+ return true;
118
+ }
119
+
120
+ /**
121
+ * Restore original AsyncStorage methods to their unmodified state
122
+ *
123
+ * This method undoes the method swizzling by restoring the original
124
+ * AsyncStorage methods that were saved during initialization.
125
+ */
126
+ restoreOriginalMethods() {
127
+ if (!_asyncStorage.default || !this.originalSetItem) {
128
+ return;
129
+ }
130
+ _asyncStorage.default.setItem = this.originalSetItem;
131
+ if (this.originalRemoveItem) {
132
+ _asyncStorage.default.removeItem = this.originalRemoveItem;
133
+ }
134
+ if (this.originalMergeItem) {
135
+ _asyncStorage.default.mergeItem = this.originalMergeItem;
136
+ }
137
+ if (this.originalClear) {
138
+ _asyncStorage.default.clear = this.originalClear;
139
+ }
140
+ if (this.originalMultiSet) {
141
+ _asyncStorage.default.multiSet = this.originalMultiSet;
142
+ }
143
+ if (this.originalMultiRemove) {
144
+ _asyncStorage.default.multiRemove = this.originalMultiRemove;
145
+ }
146
+ if (this.originalMultiMerge) {
147
+ _asyncStorage.default.multiMerge = this.originalMultiMerge;
148
+ }
149
+ }
150
+
151
+ /**
152
+ * Emit an AsyncStorage event to all registered listeners
153
+ *
154
+ * @param event - The AsyncStorage event to emit
155
+ *
156
+ * @performance Skips processing when no listeners are registered
157
+ */
158
+ emit(event) {
159
+ // Skip emitting if there are no listeners
160
+ if (this.listeners.length === 0) {
161
+ return;
162
+ }
163
+ this.listeners.forEach(listener => {
164
+ try {
165
+ listener(event);
166
+ } catch (error) {
167
+ // Error in event listener - continuing with others
168
+ }
169
+ });
170
+ }
171
+
172
+ /**
173
+ * Start intercepting AsyncStorage operations by swizzling methods
174
+ *
175
+ * This method replaces all AsyncStorage methods with wrapped versions
176
+ * that emit events while preserving the original functionality.
177
+ *
178
+ * @throws Will log errors if initialization fails or methods are already swizzled
179
+ *
180
+ * @performance Uses method swizzling for minimal runtime overhead
181
+ * @performance Includes safety checks to prevent double-initialization
182
+ */
183
+ async startListening() {
184
+ if (this.isListening) {
185
+ return;
186
+ }
187
+ const initialized = await this.initialize();
188
+ if (!initialized) {
189
+ return;
190
+ }
191
+
192
+ // Check if methods are already swizzled (this can happen if initialize was called twice somehow)
193
+ if (_asyncStorage.default && _asyncStorage.default.setItem.name === "swizzled_setItem") {
194
+ this.restoreOriginalMethods();
195
+ }
196
+
197
+ // Starting to listen for AsyncStorage operations
198
+
199
+ // Swizzle setItem
200
+ const swizzled_setItem = async (key, value) => {
201
+ // Only emit event if key is not ignored
202
+ if (!this.shouldIgnoreKey(key)) {
203
+ this.emit({
204
+ action: "setItem",
205
+ timestamp: new Date(),
206
+ data: {
207
+ key,
208
+ value
209
+ }
210
+ });
211
+ }
212
+ return this.originalSetItem ? this.originalSetItem(key, value) : Promise.resolve();
213
+ };
214
+ Object.defineProperty(swizzled_setItem, "name", {
215
+ value: "swizzled_setItem"
216
+ });
217
+ if (_asyncStorage.default) {
218
+ _asyncStorage.default.setItem = swizzled_setItem;
219
+ }
220
+
221
+ // Swizzle removeItem
222
+ if (_asyncStorage.default) {
223
+ _asyncStorage.default.removeItem = async key => {
224
+ // Intercepted removeItem
225
+
226
+ // Only emit event if key is not ignored
227
+ if (!this.shouldIgnoreKey(key)) {
228
+ this.emit({
229
+ action: "removeItem",
230
+ timestamp: new Date(),
231
+ data: {
232
+ key
233
+ }
234
+ });
235
+ } else {
236
+ // Ignoring removeItem for ignored key
237
+ }
238
+ return this.originalRemoveItem ? this.originalRemoveItem(key) : Promise.resolve();
239
+ };
240
+ }
241
+
242
+ // Swizzle mergeItem
243
+ if (_asyncStorage.default) {
244
+ _asyncStorage.default.mergeItem = async (key, value) => {
245
+ // Intercepted mergeItem operation
246
+
247
+ // Only emit event if key is not ignored
248
+ if (!this.shouldIgnoreKey(key)) {
249
+ this.emit({
250
+ action: "mergeItem",
251
+ timestamp: new Date(),
252
+ data: {
253
+ key,
254
+ value
255
+ }
256
+ });
257
+ } else {
258
+ // Ignoring mergeItem for ignored key
259
+ }
260
+ return this.originalMergeItem ? this.originalMergeItem(key, value) : Promise.resolve();
261
+ };
262
+ }
263
+
264
+ // Swizzle clear
265
+ if (_asyncStorage.default) {
266
+ _asyncStorage.default.clear = async () => {
267
+ // Intercepted clear operation
268
+ this.emit({
269
+ action: "clear",
270
+ timestamp: new Date()
271
+ });
272
+ return this.originalClear ? this.originalClear() : Promise.resolve();
273
+ };
274
+ }
275
+
276
+ // Swizzle multiSet
277
+ if (_asyncStorage.default) {
278
+ _asyncStorage.default.multiSet = async keyValuePairs => {
279
+ // Intercepted multiSet operation with multiple pairs
280
+
281
+ // Filter out ignored keys
282
+ const filteredPairs = keyValuePairs.filter(([key]) => !this.shouldIgnoreKey(key));
283
+ if (filteredPairs.length > 0) {
284
+ this.emit({
285
+ action: "multiSet",
286
+ timestamp: new Date(),
287
+ data: {
288
+ pairs: filteredPairs
289
+ }
290
+ });
291
+ } else {
292
+ // All keys in multiSet are ignored
293
+ }
294
+ return this.originalMultiSet ? this.originalMultiSet(keyValuePairs) : Promise.resolve();
295
+ };
296
+ }
297
+
298
+ // Swizzle multiRemove
299
+ if (_asyncStorage.default) {
300
+ _asyncStorage.default.multiRemove = async keys => {
301
+ // Intercepted multiRemove operation with multiple keys
302
+
303
+ // Filter out ignored keys
304
+ const filteredKeys = keys.filter(key => !this.shouldIgnoreKey(key));
305
+ if (filteredKeys.length > 0) {
306
+ this.emit({
307
+ action: "multiRemove",
308
+ timestamp: new Date(),
309
+ data: {
310
+ keys: filteredKeys
311
+ }
312
+ });
313
+ } else {
314
+ // All keys in multiRemove are ignored
315
+ }
316
+ return this.originalMultiRemove ? this.originalMultiRemove(keys) : Promise.resolve();
317
+ };
318
+ }
319
+
320
+ // Swizzle multiMerge if available
321
+ if (this.originalMultiMerge && _asyncStorage.default) {
322
+ _asyncStorage.default.multiMerge = async keyValuePairs => {
323
+ // Intercepted multiMerge operation with multiple pairs
324
+
325
+ // Filter out ignored keys
326
+ const filteredPairs = keyValuePairs.filter(([key]) => !this.shouldIgnoreKey(key));
327
+ if (filteredPairs.length > 0) {
328
+ this.emit({
329
+ action: "multiMerge",
330
+ timestamp: new Date(),
331
+ data: {
332
+ pairs: filteredPairs
333
+ }
334
+ });
335
+ } else {
336
+ // All keys in multiMerge are ignored
337
+ }
338
+ return this.originalMultiMerge ? this.originalMultiMerge(keyValuePairs) : Promise.resolve();
339
+ };
340
+ }
341
+ this.isListening = true;
342
+ // Started listening successfully
343
+ }
344
+
345
+ /**
346
+ * Stop listening and restore original AsyncStorage methods
347
+ *
348
+ * This method undoes all method swizzling and restores AsyncStorage
349
+ * to its original state.
350
+ */
351
+ stopListening() {
352
+ if (!this.isListening) {
353
+ return;
354
+ }
355
+ if (!_asyncStorage.default) {
356
+ return;
357
+ }
358
+
359
+ // Stopping listener and restoring original methods
360
+
361
+ // Restore original methods
362
+ if (this.originalSetItem) {
363
+ _asyncStorage.default.setItem = this.originalSetItem;
364
+ }
365
+ if (this.originalRemoveItem) {
366
+ _asyncStorage.default.removeItem = this.originalRemoveItem;
367
+ }
368
+ if (this.originalMergeItem) {
369
+ _asyncStorage.default.mergeItem = this.originalMergeItem;
370
+ }
371
+ if (this.originalClear) {
372
+ _asyncStorage.default.clear = this.originalClear;
373
+ }
374
+ if (this.originalMultiSet) {
375
+ _asyncStorage.default.multiSet = this.originalMultiSet;
376
+ }
377
+ if (this.originalMultiRemove) {
378
+ _asyncStorage.default.multiRemove = this.originalMultiRemove;
379
+ }
380
+ if (this.originalMultiMerge) {
381
+ _asyncStorage.default.multiMerge = this.originalMultiMerge;
382
+ }
383
+ this.isListening = false;
384
+ // Stopped listening successfully
385
+ }
386
+
387
+ /**
388
+ * Add a listener for AsyncStorage events
389
+ *
390
+ * @param listener - Callback function to handle AsyncStorage events
391
+ * @returns Unsubscribe function to remove the listener
392
+ *
393
+ * @example
394
+ * ```typescript
395
+ * const unsubscribe = asyncStorageListener.addListener((event) => {
396
+ * console.log('Storage operation:', event.action, event.data);
397
+ * });
398
+ *
399
+ * // Later, remove the listener
400
+ * unsubscribe();
401
+ * ```
402
+ */
403
+ addListener(listener) {
404
+ this.listeners.push(listener);
405
+
406
+ // Return unsubscribe function
407
+ return () => {
408
+ const index = this.listeners.indexOf(listener);
409
+ if (index > -1) {
410
+ this.listeners.splice(index, 1);
411
+ }
412
+ };
413
+ }
414
+
415
+ /**
416
+ * Remove all registered event listeners
417
+ *
418
+ * Clears the internal listeners array, stopping all event notifications.
419
+ */
420
+ removeAllListeners() {
421
+ this.listeners = [];
422
+ // Removed all listeners
423
+ }
424
+
425
+ /**
426
+ * Check if the listener is currently active and intercepting operations
427
+ *
428
+ * @returns True if currently listening to AsyncStorage operations
429
+ */
430
+ get isActive() {
431
+ return this.isListening;
432
+ }
433
+
434
+ /**
435
+ * Get the number of currently registered event listeners
436
+ *
437
+ * @returns Number of active listeners
438
+ */
439
+ get listenerCount() {
440
+ return this.listeners.length;
441
+ }
442
+ }
443
+
444
+ /**
445
+ * Singleton instance of AsyncStorageListener
446
+ *
447
+ * This ensures only one listener instance exists across the entire application,
448
+ * preventing conflicts and duplicate event handling.
449
+ */
450
+ const asyncStorageListener = new AsyncStorageListener();
451
+
452
+ /**
453
+ * Start listening to AsyncStorage operations
454
+ *
455
+ * @returns Promise that resolves when listening starts successfully
456
+ */
457
+ const startListening = () => asyncStorageListener.startListening();
458
+
459
+ /**
460
+ * Stop listening to AsyncStorage operations
461
+ */
462
+ exports.startListening = startListening;
463
+ const stopListening = () => asyncStorageListener.stopListening();
464
+
465
+ /**
466
+ * Add an event listener for AsyncStorage operations
467
+ *
468
+ * @param listener - Callback function to handle events
469
+ * @returns Unsubscribe function to remove the listener
470
+ */
471
+ exports.stopListening = stopListening;
472
+ const addListener = listener => asyncStorageListener.addListener(listener);
473
+
474
+ /**
475
+ * Remove all registered event listeners
476
+ */
477
+ exports.addListener = addListener;
478
+ const removeAllListeners = () => asyncStorageListener.removeAllListeners();
479
+
480
+ /**
481
+ * Check if currently listening to AsyncStorage operations
482
+ *
483
+ * @returns True if actively intercepting AsyncStorage methods
484
+ */
485
+ exports.removeAllListeners = removeAllListeners;
486
+ const isListening = () => asyncStorageListener.isActive;
487
+
488
+ /**
489
+ * Get the current number of registered event listeners
490
+ *
491
+ * @returns Number of active listeners
492
+ */
493
+ exports.isListening = isListening;
494
+ const getListenerCount = () => asyncStorageListener.listenerCount;
495
+
496
+ /**
497
+ * Export the singleton instance for advanced usage
498
+ *
499
+ * @example
500
+ * ```typescript
501
+ * import asyncStorageListener from './AsyncStorageListener';
502
+ *
503
+ * // Access advanced methods directly
504
+ * if (asyncStorageListener.isActive) {
505
+ * console.log(`${asyncStorageListener.listenerCount} listeners active`);
506
+ * }
507
+ * ```
508
+ */
509
+ exports.getListenerCount = getListenerCount;
510
+ var _default = exports.default = asyncStorageListener;
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.mmkvInstanceRegistry = void 0;
7
+ exports.registerMMKVInstance = registerMMKVInstance;
8
+ exports.unregisterMMKVInstance = unregisterMMKVInstance;
9
+ /**
10
+ * MMKV Instance Registry
11
+ *
12
+ * Centralized registry for tracking all MMKV instances in the application.
13
+ * Provides a singleton pattern to manage multiple MMKV instances and their metadata.
14
+ *
15
+ * @module MMKVInstanceRegistry
16
+ * @since 1.0.0
17
+ */
18
+
19
+ /**
20
+ * Type-safe representation of an MMKV instance.
21
+ * Uses conditional typing to avoid hard dependency on react-native-mmkv.
22
+ *
23
+ * @public
24
+ */
25
+
26
+ /**
27
+ * Metadata about a registered MMKV instance
28
+ *
29
+ * @public
30
+ */
31
+
32
+ /**
33
+ * Configuration options for registering an MMKV instance
34
+ *
35
+ * @public
36
+ */
37
+
38
+ class MMKVInstanceRegistry {
39
+ instances = new Map();
40
+
41
+ /**
42
+ * Register an MMKV instance for monitoring
43
+ *
44
+ * @param id - Unique identifier for this instance
45
+ * @param instance - The MMKV instance to register
46
+ * @param config - Optional configuration (e.g., encrypted flag)
47
+ */
48
+ register(id, instance, config) {
49
+ const instanceInfo = {
50
+ id,
51
+ instance,
52
+ encrypted: config?.encrypted ?? false,
53
+ readOnly: instance.isReadOnly ?? false
54
+ };
55
+ this.instances.set(id, instanceInfo);
56
+ }
57
+
58
+ /**
59
+ * Unregister an MMKV instance
60
+ */
61
+ unregister(id) {
62
+ this.instances.delete(id);
63
+ }
64
+
65
+ /**
66
+ * Get a specific instance by ID
67
+ */
68
+ get(id) {
69
+ return this.instances.get(id);
70
+ }
71
+
72
+ /**
73
+ * Get all registered instances
74
+ */
75
+ getAll() {
76
+ return Array.from(this.instances.values());
77
+ }
78
+
79
+ /**
80
+ * Check if an instance is registered
81
+ */
82
+ has(id) {
83
+ return this.instances.has(id);
84
+ }
85
+
86
+ /**
87
+ * Get count of registered instances
88
+ */
89
+ count() {
90
+ return this.instances.size;
91
+ }
92
+ }
93
+
94
+ // Singleton instance
95
+ const mmkvInstanceRegistry = exports.mmkvInstanceRegistry = new MMKVInstanceRegistry();
96
+
97
+ /**
98
+ * Register an MMKV instance with React Buoy DevTools for monitoring and debugging.
99
+ *
100
+ * **⚠️ REQUIRED**: Manual registration is required for `react-native-mmkv` v4.
101
+ * Auto-detection is not possible due to Metro bundler and ES6 module limitations.
102
+ *
103
+ * Call this function immediately after creating each MMKV instance you want to monitor.
104
+ * The DevTools will then be able to:
105
+ * - Display all keys and values
106
+ * - Show real-time updates when data changes
107
+ * - Allow editing values directly from the DevTools
108
+ * - Track storage size and performance
109
+ *
110
+ * @param id - Unique identifier for this MMKV instance. Should match the `id` you used when creating the instance.
111
+ * @param instance - The MMKV instance returned from `createMMKV()`
112
+ * @param config - Optional configuration
113
+ * @param config.encrypted - Set to `true` if this instance uses encryption (has an `encryptionKey`)
114
+ *
115
+ * @example
116
+ * **Basic usage:**
117
+ * ```typescript
118
+ * import { createMMKV } from 'react-native-mmkv';
119
+ * import { registerMMKVInstance } from '@buoy-gg/storage';
120
+ *
121
+ * // Create and register default instance
122
+ * export const storage = createMMKV({ id: 'mmkv.default' });
123
+ * registerMMKVInstance('mmkv.default', storage);
124
+ * ```
125
+ *
126
+ * @example
127
+ * **With encryption:**
128
+ * ```typescript
129
+ * import { createMMKV } from 'react-native-mmkv';
130
+ * import { registerMMKVInstance } from '@buoy-gg/storage';
131
+ *
132
+ * // Create encrypted instance
133
+ * export const secureStorage = createMMKV({
134
+ * id: 'secure-storage',
135
+ * encryptionKey: 'my-encryption-key'
136
+ * });
137
+ *
138
+ * // Register with encrypted flag
139
+ * registerMMKVInstance('secure-storage', secureStorage, { encrypted: true });
140
+ * ```
141
+ *
142
+ * @example
143
+ * **Multiple instances:**
144
+ * ```typescript
145
+ * import { createMMKV } from 'react-native-mmkv';
146
+ * import { registerMMKVInstance } from '@buoy-gg/storage';
147
+ *
148
+ * // User preferences
149
+ * export const userPrefs = createMMKV({ id: 'user-prefs' });
150
+ * registerMMKVInstance('user-prefs', userPrefs);
151
+ *
152
+ * // Cache
153
+ * export const cache = createMMKV({ id: 'cache' });
154
+ * registerMMKVInstance('cache', cache);
155
+ *
156
+ * // Auth (encrypted)
157
+ * export const auth = createMMKV({ id: 'auth', encryptionKey: 'key' });
158
+ * registerMMKVInstance('auth', auth, { encrypted: true });
159
+ * ```
160
+ *
161
+ * @public
162
+ * @since 1.0.0
163
+ */
164
+ function registerMMKVInstance(id, instance, config) {
165
+ // Register in registry
166
+ mmkvInstanceRegistry.register(id, instance, config);
167
+
168
+ // Add listener for real-time monitoring (CRITICAL: enables event emission)
169
+ // v4: Use ONLY native listener (addOnValueChangedListener), skip method wrapping
170
+ // Import mmkvListener dynamically to avoid circular dependency
171
+ const {
172
+ mmkvListener
173
+ } = require('./MMKVListener');
174
+ mmkvListener.addInstance(instance, id);
175
+ }
176
+
177
+ /**
178
+ * Unregister an MMKV instance from DevTools monitoring.
179
+ *
180
+ * This stops the DevTools from tracking changes to this instance.
181
+ * Typically not needed unless you're dynamically creating/destroying instances.
182
+ *
183
+ * @param id - The instance ID to unregister
184
+ *
185
+ * @example
186
+ * ```typescript
187
+ * unregisterMMKVInstance('cache');
188
+ * ```
189
+ *
190
+ * @public
191
+ * @since 1.0.0
192
+ */
193
+ function unregisterMMKVInstance(id) {
194
+ // Remove listener first
195
+ const {
196
+ mmkvListener
197
+ } = require('./MMKVListener');
198
+ mmkvListener.removeInstance(id);
199
+
200
+ // Then remove from registry
201
+ mmkvInstanceRegistry.unregister(id);
202
+ }