@buoy-gg/storage 7.0.41 → 7.0.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -90
- package/lib/commonjs/index.js +1 -353
- package/lib/commonjs/preset.js +1 -85
- package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +1 -36
- package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +1 -12
- package/lib/commonjs/storage/components/DiffViewer/themes/diffThemes.js +1 -24
- package/lib/commonjs/storage/components/GameUIStorageBrowser.js +3 -1259
- package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -257
- package/lib/commonjs/storage/components/MMKVInstanceSelector.js +1 -419
- package/lib/commonjs/storage/components/SelectionActionBar.js +1 -207
- package/lib/commonjs/storage/components/StorageActionButtons.js +1 -242
- package/lib/commonjs/storage/components/StorageBrowserMode.js +1 -61
- package/lib/commonjs/storage/components/StorageEventActionButton.js +1 -121
- package/lib/commonjs/storage/components/StorageEventCard.js +1 -118
- package/lib/commonjs/storage/components/StorageEventDetailContent.js +1 -494
- package/lib/commonjs/storage/components/StorageEventFilterView.js +1 -160
- package/lib/commonjs/storage/components/StorageEventsSection.js +1 -24
- package/lib/commonjs/storage/components/StorageFilterCards.js +1 -231
- package/lib/commonjs/storage/components/StorageKeyCard.js +1 -520
- package/lib/commonjs/storage/components/StorageKeyDetailScreen.js +1 -579
- package/lib/commonjs/storage/components/StorageKeyRow.js +1 -559
- package/lib/commonjs/storage/components/StorageKeySection.js +1 -160
- package/lib/commonjs/storage/components/StorageKeyStats.js +1 -345
- package/lib/commonjs/storage/components/StorageModalWithTabs.js +1 -954
- package/lib/commonjs/storage/components/StorageSaveNotice.js +1 -171
- package/lib/commonjs/storage/components/StorageSection.js +1 -43
- package/lib/commonjs/storage/components/StorageTypeFilterBar.js +1 -144
- package/lib/commonjs/storage/hooks/useAsyncStorageKeys.js +1 -141
- package/lib/commonjs/storage/hooks/useMMKVInstances.js +1 -210
- package/lib/commonjs/storage/hooks/useMMKVKeys.js +1 -376
- package/lib/commonjs/storage/hooks/useSecureStoreKeys.js +1 -202
- package/lib/commonjs/storage/hooks/useStorageEvents.js +1 -61
- package/lib/commonjs/storage/stores/storageEventStore.js +1 -312
- package/lib/commonjs/storage/sync/storageSyncAdapter.js +1 -492
- package/lib/commonjs/storage/types.js +1 -5
- package/lib/commonjs/storage/utils/AsyncStorageListener.js +1 -691
- package/lib/commonjs/storage/utils/AsyncStorageListener.web.js +1 -89
- package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +1 -203
- package/lib/commonjs/storage/utils/MMKVListener.js +1 -416
- package/lib/commonjs/storage/utils/SecureStoreRegistry.js +1 -200
- package/lib/commonjs/storage/utils/asyncStorageCompat.js +1 -89
- package/lib/commonjs/storage/utils/browserStorageLifecycle.js +1 -10
- package/lib/commonjs/storage/utils/browserStorageLifecycle.web.js +1 -70
- package/lib/commonjs/storage/utils/clearAllStorage.js +1 -48
- package/lib/commonjs/storage/utils/deleteStorageKeys.js +1 -82
- package/lib/commonjs/storage/utils/lineDiff.js +1 -30
- package/lib/commonjs/storage/utils/mmkvAvailability.js +1 -62
- package/lib/commonjs/storage/utils/mmkvAvailability.web.js +1 -21
- package/lib/commonjs/storage/utils/mmkvTypeDetection.js +1 -154
- package/lib/commonjs/storage/utils/requiredStorageKeyScope.js +1 -17
- package/lib/commonjs/storage/utils/setStorageValue.js +1 -218
- package/lib/commonjs/storage/utils/snapshotProvider.js +1 -382
- package/lib/commonjs/storage/utils/storageActionHelpers.js +1 -46
- package/lib/commonjs/storage/utils/storageBrowserRefresh.js +1 -49
- package/lib/commonjs/storage/utils/storageLabels.js +1 -13
- package/lib/commonjs/storage/utils/storageLabels.web.js +1 -13
- package/lib/commonjs/storage/utils/storageOps.js +1 -53
- package/lib/commonjs/storage/utils/storageQueryUtils.js +1 -35
- package/lib/commonjs/storage/utils/storageTimeTravelUtils.js +1 -288
- package/lib/commonjs/storage/utils/valueType.js +1 -83
- package/lib/module/index.js +1 -114
- package/lib/module/preset.js +1 -82
- package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +1 -32
- package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +1 -9
- package/lib/module/storage/components/DiffViewer/themes/diffThemes.js +1 -10
- package/lib/module/storage/components/GameUIStorageBrowser.js +3 -1257
- package/lib/module/storage/components/MMKVInstanceInfoPanel.js +1 -253
- package/lib/module/storage/components/MMKVInstanceSelector.js +1 -415
- package/lib/module/storage/components/SelectionActionBar.js +1 -204
- package/lib/module/storage/components/StorageActionButtons.js +1 -238
- package/lib/module/storage/components/StorageBrowserMode.js +1 -57
- package/lib/module/storage/components/StorageEventActionButton.js +1 -118
- package/lib/module/storage/components/StorageEventCard.js +1 -113
- package/lib/module/storage/components/StorageEventDetailContent.js +1 -490
- package/lib/module/storage/components/StorageEventFilterView.js +1 -156
- package/lib/module/storage/components/StorageEventsSection.js +1 -20
- package/lib/module/storage/components/StorageFilterCards.js +1 -227
- package/lib/module/storage/components/StorageKeyCard.js +1 -517
- package/lib/module/storage/components/StorageKeyDetailScreen.js +1 -577
- package/lib/module/storage/components/StorageKeyRow.js +1 -554
- package/lib/module/storage/components/StorageKeySection.js +1 -155
- package/lib/module/storage/components/StorageKeyStats.js +1 -342
- package/lib/module/storage/components/StorageModalWithTabs.js +1 -949
- package/lib/module/storage/components/StorageSaveNotice.js +1 -168
- package/lib/module/storage/components/StorageSection.js +1 -40
- package/lib/module/storage/components/StorageTypeFilterBar.js +1 -139
- package/lib/module/storage/hooks/useAsyncStorageKeys.js +1 -136
- package/lib/module/storage/hooks/useMMKVInstances.js +1 -204
- package/lib/module/storage/hooks/useMMKVKeys.js +1 -371
- package/lib/module/storage/hooks/useSecureStoreKeys.js +1 -199
- package/lib/module/storage/hooks/useStorageEvents.js +1 -58
- package/lib/module/storage/stores/storageEventStore.js +1 -301
- package/lib/module/storage/sync/storageSyncAdapter.js +1 -486
- package/lib/module/storage/types.js +1 -3
- package/lib/module/storage/utils/AsyncStorageListener.js +1 -679
- package/lib/module/storage/utils/AsyncStorageListener.web.js +1 -76
- package/lib/module/storage/utils/MMKVInstanceRegistry.js +1 -197
- package/lib/module/storage/utils/MMKVListener.js +1 -403
- package/lib/module/storage/utils/SecureStoreRegistry.js +1 -194
- package/lib/module/storage/utils/asyncStorageCompat.js +1 -81
- package/lib/module/storage/utils/browserStorageLifecycle.js +1 -6
- package/lib/module/storage/utils/browserStorageLifecycle.web.js +1 -66
- package/lib/module/storage/utils/clearAllStorage.js +1 -43
- package/lib/module/storage/utils/deleteStorageKeys.js +1 -78
- package/lib/module/storage/utils/lineDiff.js +1 -12
- package/lib/module/storage/utils/mmkvAvailability.js +1 -56
- package/lib/module/storage/utils/mmkvAvailability.web.js +1 -15
- package/lib/module/storage/utils/mmkvTypeDetection.js +1 -148
- package/lib/module/storage/utils/requiredStorageKeyScope.js +1 -13
- package/lib/module/storage/utils/setStorageValue.js +1 -209
- package/lib/module/storage/utils/snapshotProvider.js +1 -380
- package/lib/module/storage/utils/storageActionHelpers.js +1 -42
- package/lib/module/storage/utils/storageBrowserRefresh.js +1 -44
- package/lib/module/storage/utils/storageLabels.js +1 -9
- package/lib/module/storage/utils/storageLabels.web.js +1 -9
- package/lib/module/storage/utils/storageOps.js +1 -46
- package/lib/module/storage/utils/storageQueryUtils.js +1 -30
- package/lib/module/storage/utils/storageTimeTravelUtils.js +1 -281
- package/lib/module/storage/utils/valueType.js +1 -76
- package/lib/web/index.mjs +2 -3
- package/package.json +5 -5
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts.map +0 -1
- package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +0 -1
- package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts.map +0 -1
- package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +0 -1
- package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventActionButton.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventCard.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageEventsSection.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeyDetailScreen.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeySection.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageSaveNotice.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageSection.d.ts.map +0 -1
- package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useMMKVInstances.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useMMKVKeys.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useStorageEvents.d.ts.map +0 -1
- package/lib/typescript/storage/stores/storageEventStore.d.ts.map +0 -1
- package/lib/typescript/storage/sync/storageSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/storage/types.d.ts.map +0 -1
- package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +0 -1
- package/lib/typescript/storage/utils/AsyncStorageListener.web.d.ts.map +0 -1
- package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +0 -1
- package/lib/typescript/storage/utils/MMKVListener.d.ts.map +0 -1
- package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts.map +0 -1
- package/lib/typescript/storage/utils/asyncStorageCompat.d.ts.map +0 -1
- package/lib/typescript/storage/utils/browserStorageLifecycle.d.ts.map +0 -1
- package/lib/typescript/storage/utils/browserStorageLifecycle.web.d.ts.map +0 -1
- package/lib/typescript/storage/utils/clearAllStorage.d.ts.map +0 -1
- package/lib/typescript/storage/utils/deleteStorageKeys.d.ts.map +0 -1
- package/lib/typescript/storage/utils/lineDiff.d.ts.map +0 -1
- package/lib/typescript/storage/utils/mmkvAvailability.d.ts.map +0 -1
- package/lib/typescript/storage/utils/mmkvAvailability.web.d.ts.map +0 -1
- package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts.map +0 -1
- package/lib/typescript/storage/utils/requiredStorageKeyScope.d.ts.map +0 -1
- package/lib/typescript/storage/utils/setStorageValue.d.ts.map +0 -1
- package/lib/typescript/storage/utils/snapshotProvider.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageActionHelpers.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageLabels.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageLabels.web.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageOps.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageQueryUtils.d.ts.map +0 -1
- package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts.map +0 -1
- package/lib/typescript/storage/utils/valueType.d.ts.map +0 -1
|
@@ -1,691 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.stopListening = exports.startListening = exports.resumeCapture = exports.removeAllListeners = exports.pauseCapture = exports.isPaused = exports.isListening = exports.getListenerCount = exports.default = exports.addListener = void 0;
|
|
7
|
-
var _asyncStorageCompat = require("./asyncStorageCompat");
|
|
8
|
-
// AsyncStorage method signatures - matching the actual AsyncStorage API
|
|
9
|
-
|
|
10
|
-
// v3-only batch methods (replace multiSet/multiRemove)
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* The pristine (un-swizzled) AsyncStorage methods, stashed on globalThis under a
|
|
14
|
-
* cross-realm Symbol.
|
|
15
|
-
*
|
|
16
|
-
* Why this exists: the listener below is a module-scope singleton. Metro Fast
|
|
17
|
-
* Refresh re-evaluates the module and builds a NEW instance whose `original*`
|
|
18
|
-
* fields are all null — but `AsyncStorage.setItem` still points at the OLD
|
|
19
|
-
* instance's `swizzled_setItem`. Without a stash, `initialize()` sees the
|
|
20
|
-
* existing swizzle, has no way to recover the real methods, and bails; the
|
|
21
|
-
* listener then never attaches, so storage events stop for the rest of the
|
|
22
|
-
* session (writes still work, they just go unrecorded). Keeping the originals
|
|
23
|
-
* off the instance lets a fresh instance re-attach cleanly.
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
const ORIGINALS_KEY = Symbol.for("@buoy-gg/storage.asyncStorageOriginals");
|
|
27
|
-
function readStashedOriginals() {
|
|
28
|
-
return globalThis[ORIGINALS_KEY] ?? null;
|
|
29
|
-
}
|
|
30
|
-
function stashOriginals(originals) {
|
|
31
|
-
globalThis[ORIGINALS_KEY] = originals;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
// Event types for AsyncStorage operations
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Singleton class for intercepting and monitoring AsyncStorage operations
|
|
38
|
-
*
|
|
39
|
-
* This class uses method swizzling to intercept all AsyncStorage operations
|
|
40
|
-
* (setItem, removeItem, mergeItem, clear, multiSet, multiRemove, multiMerge)
|
|
41
|
-
* and emits events to registered listeners. It maintains the original functionality
|
|
42
|
-
* while providing observability for debugging and development tools.
|
|
43
|
-
*
|
|
44
|
-
* Supports both async-storage v2 (multiGet/multiSet/multiRemove/mergeItem) and
|
|
45
|
-
* v3 (getMany/setMany/removeMany, no merge). On v3 the renamed batch methods are
|
|
46
|
-
* swizzled and normalized back to the same v2-shaped events, so the rest of the
|
|
47
|
-
* tool — event store, time-travel, desktop sync — is version-agnostic. v3 dropped
|
|
48
|
-
* the merge API entirely, so no merge events can occur there.
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* ```typescript
|
|
52
|
-
* // Start listening to all AsyncStorage operations
|
|
53
|
-
* startListening();
|
|
54
|
-
*
|
|
55
|
-
* // Add a listener for storage events
|
|
56
|
-
* const unsubscribe = addListener((event) => {
|
|
57
|
-
* console.log(`${event.action}:`, event.data);
|
|
58
|
-
* });
|
|
59
|
-
*
|
|
60
|
-
* // Clean up
|
|
61
|
-
* unsubscribe();
|
|
62
|
-
* stopListening();
|
|
63
|
-
* ```
|
|
64
|
-
*
|
|
65
|
-
* @performance Uses method interception rather than polling for zero-overhead when inactive
|
|
66
|
-
* @performance Includes key filtering to prevent dev tools from triggering self-events
|
|
67
|
-
*/
|
|
68
|
-
class AsyncStorageListener {
|
|
69
|
-
listeners = [];
|
|
70
|
-
isListening = false;
|
|
71
|
-
isInitialized = false;
|
|
72
|
-
isPaused = false;
|
|
73
|
-
|
|
74
|
-
// Keys to ignore for dev tools to prevent self-triggering
|
|
75
|
-
// Only ignore specific keys that would cause infinite loops in the storage browser
|
|
76
|
-
ignoredKeys = new Set(["@react_buoy_storage_event_filters",
|
|
77
|
-
// Storage events filter settings
|
|
78
|
-
"@react_buoy_storage_key_filters",
|
|
79
|
-
// Storage browser key filters
|
|
80
|
-
"@react_buoy_storage_is_monitoring",
|
|
81
|
-
// Storage monitoring toggle
|
|
82
|
-
"REACT_QUERY_OFFLINE_CACHE" // React Query cache
|
|
83
|
-
]);
|
|
84
|
-
|
|
85
|
-
// Store original methods
|
|
86
|
-
originalSetItem = null;
|
|
87
|
-
originalRemoveItem = null;
|
|
88
|
-
originalMergeItem = null;
|
|
89
|
-
originalClear = null;
|
|
90
|
-
// v2 batch originals
|
|
91
|
-
originalMultiSet = null;
|
|
92
|
-
originalMultiRemove = null;
|
|
93
|
-
originalMultiMerge = null;
|
|
94
|
-
// v3 batch originals
|
|
95
|
-
originalSetMany = null;
|
|
96
|
-
originalRemoveMany = null;
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Determines if a storage key should be ignored to prevent infinite loops
|
|
100
|
-
*
|
|
101
|
-
* Dev tools often store their own state in AsyncStorage, which would trigger
|
|
102
|
-
* events and cause infinite loops or unnecessary noise.
|
|
103
|
-
*
|
|
104
|
-
* @param key - The storage key to check
|
|
105
|
-
* @returns True if the key should be ignored, false otherwise
|
|
106
|
-
*/
|
|
107
|
-
shouldIgnoreKey(key) {
|
|
108
|
-
// Check exact matches
|
|
109
|
-
if (this.ignoredKeys.has(key)) return true;
|
|
110
|
-
|
|
111
|
-
// Check prefix matches
|
|
112
|
-
for (const ignoredKey of this.ignoredKeys) {
|
|
113
|
-
if (key.startsWith(ignoredKey)) return true;
|
|
114
|
-
}
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/**
|
|
119
|
-
* Copy a set of pristine methods onto this instance's `original*` fields.
|
|
120
|
-
*
|
|
121
|
-
* Used both when capturing them for the first time and when adopting the
|
|
122
|
-
* global stash after a Fast Refresh, so `restoreOriginalMethods()` and the
|
|
123
|
-
* swizzles always have real methods to call through to.
|
|
124
|
-
*/
|
|
125
|
-
adoptOriginals(originals) {
|
|
126
|
-
this.originalSetItem = originals.setItem;
|
|
127
|
-
this.originalRemoveItem = originals.removeItem;
|
|
128
|
-
this.originalClear = originals.clear;
|
|
129
|
-
this.originalMergeItem = originals.mergeItem;
|
|
130
|
-
this.originalMultiSet = originals.multiSet;
|
|
131
|
-
this.originalMultiRemove = originals.multiRemove;
|
|
132
|
-
this.originalMultiMerge = originals.multiMerge;
|
|
133
|
-
this.originalSetMany = originals.setMany;
|
|
134
|
-
this.originalRemoveMany = originals.removeMany;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
/**
|
|
138
|
-
* Initialize the listener by loading AsyncStorage and storing original methods
|
|
139
|
-
*
|
|
140
|
-
* This method performs safety checks to ensure we don't double-initialize
|
|
141
|
-
* and verifies that AsyncStorage methods haven't already been swizzled.
|
|
142
|
-
*
|
|
143
|
-
* @returns Promise<boolean> - True if initialization succeeded, false otherwise
|
|
144
|
-
*
|
|
145
|
-
* @throws Will log errors if AsyncStorage is already swizzled by another instance
|
|
146
|
-
*/
|
|
147
|
-
async initialize() {
|
|
148
|
-
if (this.isInitialized) {
|
|
149
|
-
// Already initialized - skipping
|
|
150
|
-
return true;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
// Already swizzled — by a previous instance of this class that Fast Refresh
|
|
154
|
-
// replaced, or by a duplicate copy of the package. Adopt the stashed
|
|
155
|
-
// originals so this instance can restore + re-swizzle. Bailing here is what
|
|
156
|
-
// used to kill storage events until a full app reload.
|
|
157
|
-
if (_asyncStorageCompat.asyncStorage.setItem.name === "swizzled_setItem") {
|
|
158
|
-
const stashed = readStashedOriginals();
|
|
159
|
-
if (!stashed) {
|
|
160
|
-
// Swizzled by something we didn't install and whose originals we never
|
|
161
|
-
// captured — taking the current methods as "originals" would bake the
|
|
162
|
-
// foreign swizzle in permanently, so stay out of the way.
|
|
163
|
-
return false;
|
|
164
|
-
}
|
|
165
|
-
this.adoptOriginals(stashed);
|
|
166
|
-
this.isInitialized = true;
|
|
167
|
-
return true;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Store original methods (these should be the real AsyncStorage methods).
|
|
171
|
-
// Single-item + clear are identical across v2/v3.
|
|
172
|
-
const originals = {
|
|
173
|
-
setItem: _asyncStorageCompat.asyncStorage.setItem.bind(_asyncStorageCompat.asyncStorage),
|
|
174
|
-
removeItem: _asyncStorageCompat.asyncStorage.removeItem.bind(_asyncStorageCompat.asyncStorage),
|
|
175
|
-
clear: _asyncStorageCompat.asyncStorage.clear.bind(_asyncStorageCompat.asyncStorage),
|
|
176
|
-
mergeItem: null,
|
|
177
|
-
multiSet: null,
|
|
178
|
-
multiRemove: null,
|
|
179
|
-
multiMerge: null,
|
|
180
|
-
setMany: null,
|
|
181
|
-
removeMany: null
|
|
182
|
-
};
|
|
183
|
-
if (_asyncStorageCompat.asyncStorageCaps.hasLegacyMultiApi) {
|
|
184
|
-
// v2: multiSet/multiRemove + merge API
|
|
185
|
-
originals.multiSet = _asyncStorageCompat.asyncStorage.multiSet.bind(_asyncStorageCompat.asyncStorage);
|
|
186
|
-
originals.multiRemove = _asyncStorageCompat.asyncStorage.multiRemove.bind(_asyncStorageCompat.asyncStorage);
|
|
187
|
-
originals.mergeItem = _asyncStorageCompat.asyncStorage.mergeItem.bind(_asyncStorageCompat.asyncStorage);
|
|
188
|
-
originals.multiMerge = _asyncStorageCompat.asyncStorage.multiMerge ? _asyncStorageCompat.asyncStorage.multiMerge.bind(_asyncStorageCompat.asyncStorage) : null;
|
|
189
|
-
} else {
|
|
190
|
-
// v3: setMany/removeMany; merge API was removed (nothing to capture)
|
|
191
|
-
originals.setMany = _asyncStorageCompat.asyncStorage.setMany.bind(_asyncStorageCompat.asyncStorage);
|
|
192
|
-
originals.removeMany = _asyncStorageCompat.asyncStorage.removeMany.bind(_asyncStorageCompat.asyncStorage);
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Keep them reachable across a module re-evaluation, then adopt.
|
|
196
|
-
stashOriginals(originals);
|
|
197
|
-
this.adoptOriginals(originals);
|
|
198
|
-
|
|
199
|
-
// Original methods stored successfully
|
|
200
|
-
this.isInitialized = true;
|
|
201
|
-
return true;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
/**
|
|
205
|
-
* Restore original AsyncStorage methods to their unmodified state
|
|
206
|
-
*
|
|
207
|
-
* This method undoes the method swizzling by restoring the original
|
|
208
|
-
* AsyncStorage methods that were saved during initialization.
|
|
209
|
-
*/
|
|
210
|
-
restoreOriginalMethods() {
|
|
211
|
-
if (!_asyncStorageCompat.asyncStorage || !this.originalSetItem) {
|
|
212
|
-
return;
|
|
213
|
-
}
|
|
214
|
-
_asyncStorageCompat.asyncStorage.setItem = this.originalSetItem;
|
|
215
|
-
if (this.originalRemoveItem) {
|
|
216
|
-
_asyncStorageCompat.asyncStorage.removeItem = this.originalRemoveItem;
|
|
217
|
-
}
|
|
218
|
-
if (this.originalClear) {
|
|
219
|
-
_asyncStorageCompat.asyncStorage.clear = this.originalClear;
|
|
220
|
-
}
|
|
221
|
-
// v2 batch + merge
|
|
222
|
-
if (this.originalMergeItem) {
|
|
223
|
-
_asyncStorageCompat.asyncStorage.mergeItem = this.originalMergeItem;
|
|
224
|
-
}
|
|
225
|
-
if (this.originalMultiSet) {
|
|
226
|
-
_asyncStorageCompat.asyncStorage.multiSet = this.originalMultiSet;
|
|
227
|
-
}
|
|
228
|
-
if (this.originalMultiRemove) {
|
|
229
|
-
_asyncStorageCompat.asyncStorage.multiRemove = this.originalMultiRemove;
|
|
230
|
-
}
|
|
231
|
-
if (this.originalMultiMerge) {
|
|
232
|
-
_asyncStorageCompat.asyncStorage.multiMerge = this.originalMultiMerge;
|
|
233
|
-
}
|
|
234
|
-
// v3 batch
|
|
235
|
-
if (this.originalSetMany) {
|
|
236
|
-
_asyncStorageCompat.asyncStorage.setMany = this.originalSetMany;
|
|
237
|
-
}
|
|
238
|
-
if (this.originalRemoveMany) {
|
|
239
|
-
_asyncStorageCompat.asyncStorage.removeMany = this.originalRemoveMany;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/**
|
|
244
|
-
* Emit an AsyncStorage event to all registered listeners
|
|
245
|
-
*
|
|
246
|
-
* @param event - The AsyncStorage event to emit
|
|
247
|
-
*
|
|
248
|
-
* @performance Skips processing when no listeners are registered or when paused
|
|
249
|
-
*/
|
|
250
|
-
emit(event) {
|
|
251
|
-
// Skip emitting if paused (used during time-travel operations)
|
|
252
|
-
if (this.isPaused) {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// Skip emitting if there are no listeners
|
|
257
|
-
if (this.listeners.length === 0) {
|
|
258
|
-
return;
|
|
259
|
-
}
|
|
260
|
-
this.listeners.forEach(listener => {
|
|
261
|
-
try {
|
|
262
|
-
listener(event);
|
|
263
|
-
} catch (error) {
|
|
264
|
-
// Error in event listener - continuing with others
|
|
265
|
-
}
|
|
266
|
-
});
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
/**
|
|
270
|
-
* Shared core for batch writes (v2 multiSet/multiMerge, v3 setMany).
|
|
271
|
-
*
|
|
272
|
-
* Captures previous values for the affected keys, runs the original native
|
|
273
|
-
* operation, and emits a normalized event. `action` distinguishes a plain set
|
|
274
|
-
* from a merge so time-travel can replay them differently.
|
|
275
|
-
*/
|
|
276
|
-
async handleBatchSet(pairs, runOriginal, action = "multiSet") {
|
|
277
|
-
// Filter out ignored keys
|
|
278
|
-
const filteredPairs = pairs.filter(([key]) => !this.shouldIgnoreKey(key));
|
|
279
|
-
if (filteredPairs.length === 0) {
|
|
280
|
-
return runOriginal();
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// Capture previous values for all keys being written
|
|
284
|
-
const keysToSet = filteredPairs.map(([key]) => key);
|
|
285
|
-
let prevPairs = [];
|
|
286
|
-
try {
|
|
287
|
-
prevPairs = await (0, _asyncStorageCompat.readMany)(keysToSet);
|
|
288
|
-
} catch {
|
|
289
|
-
// Failed to capture previous values
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Execute the operation
|
|
293
|
-
const result = await runOriginal();
|
|
294
|
-
|
|
295
|
-
// Emit event with previous values
|
|
296
|
-
this.emit({
|
|
297
|
-
action,
|
|
298
|
-
timestamp: new Date(),
|
|
299
|
-
data: {
|
|
300
|
-
pairs: filteredPairs,
|
|
301
|
-
prevPairs
|
|
302
|
-
}
|
|
303
|
-
});
|
|
304
|
-
return result;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Shared core for batch removals (v2 multiRemove, v3 removeMany).
|
|
309
|
-
*/
|
|
310
|
-
async handleBatchRemove(keys, runOriginal) {
|
|
311
|
-
// Filter out ignored keys
|
|
312
|
-
const filteredKeys = keys.filter(key => !this.shouldIgnoreKey(key));
|
|
313
|
-
if (filteredKeys.length === 0) {
|
|
314
|
-
return runOriginal();
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Capture previous values for all keys being removed
|
|
318
|
-
let prevPairs = [];
|
|
319
|
-
try {
|
|
320
|
-
prevPairs = await (0, _asyncStorageCompat.readMany)(filteredKeys);
|
|
321
|
-
} catch {
|
|
322
|
-
// Failed to capture previous values
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
// Execute the operation
|
|
326
|
-
const result = await runOriginal();
|
|
327
|
-
|
|
328
|
-
// Emit event with previous values
|
|
329
|
-
this.emit({
|
|
330
|
-
action: "multiRemove",
|
|
331
|
-
timestamp: new Date(),
|
|
332
|
-
data: {
|
|
333
|
-
keys: filteredKeys,
|
|
334
|
-
prevPairs
|
|
335
|
-
}
|
|
336
|
-
});
|
|
337
|
-
return result;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
/**
|
|
341
|
-
* Start intercepting AsyncStorage operations by swizzling methods
|
|
342
|
-
*
|
|
343
|
-
* This method replaces all AsyncStorage methods with wrapped versions
|
|
344
|
-
* that emit events while preserving the original functionality.
|
|
345
|
-
*
|
|
346
|
-
* @throws Will log errors if initialization fails or methods are already swizzled
|
|
347
|
-
*
|
|
348
|
-
* @performance Uses method swizzling for minimal runtime overhead
|
|
349
|
-
* @performance Includes safety checks to prevent double-initialization
|
|
350
|
-
*/
|
|
351
|
-
async startListening() {
|
|
352
|
-
if (this.isListening) {
|
|
353
|
-
return;
|
|
354
|
-
}
|
|
355
|
-
const initialized = await this.initialize();
|
|
356
|
-
if (!initialized) {
|
|
357
|
-
return;
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// Check if methods are already swizzled (this can happen if initialize was called twice somehow)
|
|
361
|
-
if (_asyncStorageCompat.asyncStorage && _asyncStorageCompat.asyncStorage.setItem.name === "swizzled_setItem") {
|
|
362
|
-
this.restoreOriginalMethods();
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
// Starting to listen for AsyncStorage operations
|
|
366
|
-
|
|
367
|
-
// Swizzle setItem
|
|
368
|
-
const swizzled_setItem = async (key, value) => {
|
|
369
|
-
// Only capture and emit if key is not ignored
|
|
370
|
-
if (!this.shouldIgnoreKey(key)) {
|
|
371
|
-
// Capture previous value before the operation
|
|
372
|
-
const prevValue = this.originalSetItem ? await _asyncStorageCompat.asyncStorage.getItem(key) : null;
|
|
373
|
-
|
|
374
|
-
// Execute the operation
|
|
375
|
-
const result = this.originalSetItem ? await this.originalSetItem(key, value) : undefined;
|
|
376
|
-
|
|
377
|
-
// Emit event with previous value
|
|
378
|
-
this.emit({
|
|
379
|
-
action: "setItem",
|
|
380
|
-
timestamp: new Date(),
|
|
381
|
-
data: {
|
|
382
|
-
key,
|
|
383
|
-
value,
|
|
384
|
-
prevValue
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
return result;
|
|
388
|
-
}
|
|
389
|
-
return this.originalSetItem ? this.originalSetItem(key, value) : Promise.resolve();
|
|
390
|
-
};
|
|
391
|
-
Object.defineProperty(swizzled_setItem, "name", {
|
|
392
|
-
value: "swizzled_setItem"
|
|
393
|
-
});
|
|
394
|
-
if (_asyncStorageCompat.asyncStorage) {
|
|
395
|
-
_asyncStorageCompat.asyncStorage.setItem = swizzled_setItem;
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
// Swizzle removeItem
|
|
399
|
-
if (_asyncStorageCompat.asyncStorage) {
|
|
400
|
-
_asyncStorageCompat.asyncStorage.removeItem = async key => {
|
|
401
|
-
// Only capture and emit if key is not ignored
|
|
402
|
-
if (!this.shouldIgnoreKey(key)) {
|
|
403
|
-
// Capture previous value before the operation
|
|
404
|
-
const prevValue = this.originalRemoveItem ? await _asyncStorageCompat.asyncStorage.getItem(key) : null;
|
|
405
|
-
|
|
406
|
-
// Execute the operation
|
|
407
|
-
const result = this.originalRemoveItem ? await this.originalRemoveItem(key) : undefined;
|
|
408
|
-
|
|
409
|
-
// Emit event with previous value
|
|
410
|
-
this.emit({
|
|
411
|
-
action: "removeItem",
|
|
412
|
-
timestamp: new Date(),
|
|
413
|
-
data: {
|
|
414
|
-
key,
|
|
415
|
-
prevValue
|
|
416
|
-
}
|
|
417
|
-
});
|
|
418
|
-
return result;
|
|
419
|
-
}
|
|
420
|
-
return this.originalRemoveItem ? this.originalRemoveItem(key) : Promise.resolve();
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
// Swizzle mergeItem (v2 only — v3 removed the merge API)
|
|
425
|
-
if (_asyncStorageCompat.asyncStorageCaps.hasMergeApi && _asyncStorageCompat.asyncStorage) {
|
|
426
|
-
_asyncStorageCompat.asyncStorage.mergeItem = async (key, value) => {
|
|
427
|
-
// Only capture and emit if key is not ignored
|
|
428
|
-
if (!this.shouldIgnoreKey(key)) {
|
|
429
|
-
// Capture previous value before the operation
|
|
430
|
-
const prevValue = this.originalMergeItem ? await _asyncStorageCompat.asyncStorage.getItem(key) : null;
|
|
431
|
-
|
|
432
|
-
// Execute the operation
|
|
433
|
-
const result = this.originalMergeItem ? await this.originalMergeItem(key, value) : undefined;
|
|
434
|
-
|
|
435
|
-
// Emit event with previous value
|
|
436
|
-
this.emit({
|
|
437
|
-
action: "mergeItem",
|
|
438
|
-
timestamp: new Date(),
|
|
439
|
-
data: {
|
|
440
|
-
key,
|
|
441
|
-
value,
|
|
442
|
-
prevValue
|
|
443
|
-
}
|
|
444
|
-
});
|
|
445
|
-
return result;
|
|
446
|
-
}
|
|
447
|
-
return this.originalMergeItem ? this.originalMergeItem(key, value) : Promise.resolve();
|
|
448
|
-
};
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
// Swizzle clear
|
|
452
|
-
if (_asyncStorageCompat.asyncStorage) {
|
|
453
|
-
_asyncStorageCompat.asyncStorage.clear = async () => {
|
|
454
|
-
// Capture all key-value pairs before clearing
|
|
455
|
-
let prevPairs = [];
|
|
456
|
-
try {
|
|
457
|
-
const allKeys = await _asyncStorageCompat.asyncStorage.getAllKeys();
|
|
458
|
-
// Filter out ignored keys
|
|
459
|
-
const keysToCapture = allKeys.filter(key => !this.shouldIgnoreKey(key));
|
|
460
|
-
if (keysToCapture.length > 0) {
|
|
461
|
-
prevPairs = await (0, _asyncStorageCompat.readMany)(keysToCapture);
|
|
462
|
-
}
|
|
463
|
-
} catch {
|
|
464
|
-
// Failed to capture previous state
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
// Execute the operation
|
|
468
|
-
const result = this.originalClear ? await this.originalClear() : undefined;
|
|
469
|
-
|
|
470
|
-
// Emit event with previous pairs
|
|
471
|
-
this.emit({
|
|
472
|
-
action: "clear",
|
|
473
|
-
timestamp: new Date(),
|
|
474
|
-
data: {
|
|
475
|
-
prevPairs
|
|
476
|
-
}
|
|
477
|
-
});
|
|
478
|
-
return result;
|
|
479
|
-
};
|
|
480
|
-
}
|
|
481
|
-
|
|
482
|
-
// Swizzle the batch methods for whichever API the installed version exposes.
|
|
483
|
-
if (_asyncStorageCompat.asyncStorageCaps.hasLegacyMultiApi && _asyncStorageCompat.asyncStorage) {
|
|
484
|
-
// ── v2: multiSet / multiRemove / multiMerge ──
|
|
485
|
-
_asyncStorageCompat.asyncStorage.multiSet = keyValuePairs => this.handleBatchSet(keyValuePairs, () => this.originalMultiSet ? this.originalMultiSet(keyValuePairs) : Promise.resolve());
|
|
486
|
-
_asyncStorageCompat.asyncStorage.multiRemove = keys => this.handleBatchRemove(keys, () => this.originalMultiRemove ? this.originalMultiRemove(keys) : Promise.resolve());
|
|
487
|
-
if (this.originalMultiMerge) {
|
|
488
|
-
_asyncStorageCompat.asyncStorage.multiMerge = keyValuePairs => this.handleBatchSet(keyValuePairs, () => this.originalMultiMerge ? this.originalMultiMerge(keyValuePairs) : Promise.resolve(), "multiMerge");
|
|
489
|
-
}
|
|
490
|
-
} else if (_asyncStorageCompat.asyncStorage) {
|
|
491
|
-
// ── v3: setMany / removeMany (normalized back to multiSet/multiRemove events) ──
|
|
492
|
-
_asyncStorageCompat.asyncStorage.setMany = entries => this.handleBatchSet(Object.entries(entries), () => this.originalSetMany ? this.originalSetMany(entries) : Promise.resolve());
|
|
493
|
-
_asyncStorageCompat.asyncStorage.removeMany = keys => this.handleBatchRemove(keys, () => this.originalRemoveMany ? this.originalRemoveMany(keys) : Promise.resolve());
|
|
494
|
-
}
|
|
495
|
-
this.isListening = true;
|
|
496
|
-
// Started listening successfully
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/**
|
|
500
|
-
* Stop listening and restore original AsyncStorage methods
|
|
501
|
-
*
|
|
502
|
-
* This method undoes all method swizzling and restores AsyncStorage
|
|
503
|
-
* to its original state.
|
|
504
|
-
*/
|
|
505
|
-
stopListening() {
|
|
506
|
-
if (!this.isListening) {
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
if (!_asyncStorageCompat.asyncStorage) {
|
|
510
|
-
return;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// Stopping listener and restoring original methods
|
|
514
|
-
this.restoreOriginalMethods();
|
|
515
|
-
this.isListening = false;
|
|
516
|
-
// Stopped listening successfully
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
/**
|
|
520
|
-
* Add a listener for AsyncStorage events
|
|
521
|
-
*
|
|
522
|
-
* @param listener - Callback function to handle AsyncStorage events
|
|
523
|
-
* @returns Unsubscribe function to remove the listener
|
|
524
|
-
*
|
|
525
|
-
* @example
|
|
526
|
-
* ```typescript
|
|
527
|
-
* const unsubscribe = asyncStorageListener.addListener((event) => {
|
|
528
|
-
* console.log('Storage operation:', event.action, event.data);
|
|
529
|
-
* });
|
|
530
|
-
*
|
|
531
|
-
* // Later, remove the listener
|
|
532
|
-
* unsubscribe();
|
|
533
|
-
* ```
|
|
534
|
-
*/
|
|
535
|
-
addListener(listener) {
|
|
536
|
-
this.listeners.push(listener);
|
|
537
|
-
|
|
538
|
-
// Return unsubscribe function
|
|
539
|
-
return () => {
|
|
540
|
-
const index = this.listeners.indexOf(listener);
|
|
541
|
-
if (index > -1) {
|
|
542
|
-
this.listeners.splice(index, 1);
|
|
543
|
-
}
|
|
544
|
-
};
|
|
545
|
-
}
|
|
546
|
-
|
|
547
|
-
/**
|
|
548
|
-
* Remove all registered event listeners
|
|
549
|
-
*
|
|
550
|
-
* Clears the internal listeners array, stopping all event notifications.
|
|
551
|
-
*/
|
|
552
|
-
removeAllListeners() {
|
|
553
|
-
this.listeners = [];
|
|
554
|
-
// Removed all listeners
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
/**
|
|
558
|
-
* Check if the listener is currently active and intercepting operations
|
|
559
|
-
*
|
|
560
|
-
* @returns True if currently listening to AsyncStorage operations
|
|
561
|
-
*/
|
|
562
|
-
get isActive() {
|
|
563
|
-
return this.isListening;
|
|
564
|
-
}
|
|
565
|
-
|
|
566
|
-
/**
|
|
567
|
-
* Get the number of currently registered event listeners
|
|
568
|
-
*
|
|
569
|
-
* @returns Number of active listeners
|
|
570
|
-
*/
|
|
571
|
-
get listenerCount() {
|
|
572
|
-
return this.listeners.length;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
/**
|
|
576
|
-
* Pause event emission (used during time-travel operations)
|
|
577
|
-
*
|
|
578
|
-
* When paused, storage operations still execute but events are not emitted.
|
|
579
|
-
* This prevents circular event triggering during replay/jump operations.
|
|
580
|
-
*/
|
|
581
|
-
pause() {
|
|
582
|
-
this.isPaused = true;
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
/**
|
|
586
|
-
* Resume event emission after pausing
|
|
587
|
-
*/
|
|
588
|
-
resume() {
|
|
589
|
-
this.isPaused = false;
|
|
590
|
-
}
|
|
591
|
-
|
|
592
|
-
/**
|
|
593
|
-
* Check if event emission is currently paused
|
|
594
|
-
*
|
|
595
|
-
* @returns True if paused, false otherwise
|
|
596
|
-
*/
|
|
597
|
-
get paused() {
|
|
598
|
-
return this.isPaused;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
/**
|
|
603
|
-
* Singleton instance of AsyncStorageListener
|
|
604
|
-
*
|
|
605
|
-
* This ensures only one listener instance exists across the entire application,
|
|
606
|
-
* preventing conflicts and duplicate event handling.
|
|
607
|
-
*/
|
|
608
|
-
const asyncStorageListener = new AsyncStorageListener();
|
|
609
|
-
|
|
610
|
-
/**
|
|
611
|
-
* Start listening to AsyncStorage operations
|
|
612
|
-
*
|
|
613
|
-
* @returns Promise that resolves when listening starts successfully
|
|
614
|
-
*/
|
|
615
|
-
const startListening = () => asyncStorageListener.startListening();
|
|
616
|
-
|
|
617
|
-
/**
|
|
618
|
-
* Stop listening to AsyncStorage operations
|
|
619
|
-
*/
|
|
620
|
-
exports.startListening = startListening;
|
|
621
|
-
const stopListening = () => asyncStorageListener.stopListening();
|
|
622
|
-
|
|
623
|
-
/**
|
|
624
|
-
* Add an event listener for AsyncStorage operations
|
|
625
|
-
*
|
|
626
|
-
* @param listener - Callback function to handle events
|
|
627
|
-
* @returns Unsubscribe function to remove the listener
|
|
628
|
-
*/
|
|
629
|
-
exports.stopListening = stopListening;
|
|
630
|
-
const addListener = listener => asyncStorageListener.addListener(listener);
|
|
631
|
-
|
|
632
|
-
/**
|
|
633
|
-
* Remove all registered event listeners
|
|
634
|
-
*/
|
|
635
|
-
exports.addListener = addListener;
|
|
636
|
-
const removeAllListeners = () => asyncStorageListener.removeAllListeners();
|
|
637
|
-
|
|
638
|
-
/**
|
|
639
|
-
* Check if currently listening to AsyncStorage operations
|
|
640
|
-
*
|
|
641
|
-
* @returns True if actively intercepting AsyncStorage methods
|
|
642
|
-
*/
|
|
643
|
-
exports.removeAllListeners = removeAllListeners;
|
|
644
|
-
const isListening = () => asyncStorageListener.isActive;
|
|
645
|
-
|
|
646
|
-
/**
|
|
647
|
-
* Get the current number of registered event listeners
|
|
648
|
-
*
|
|
649
|
-
* @returns Number of active listeners
|
|
650
|
-
*/
|
|
651
|
-
exports.isListening = isListening;
|
|
652
|
-
const getListenerCount = () => asyncStorageListener.listenerCount;
|
|
653
|
-
|
|
654
|
-
/**
|
|
655
|
-
* Pause event emission (used during time-travel operations)
|
|
656
|
-
*
|
|
657
|
-
* When paused, storage operations still execute but events are not emitted.
|
|
658
|
-
* This prevents circular event triggering during replay/jump operations.
|
|
659
|
-
*/
|
|
660
|
-
exports.getListenerCount = getListenerCount;
|
|
661
|
-
const pauseCapture = () => asyncStorageListener.pause();
|
|
662
|
-
|
|
663
|
-
/**
|
|
664
|
-
* Resume event emission after pausing
|
|
665
|
-
*/
|
|
666
|
-
exports.pauseCapture = pauseCapture;
|
|
667
|
-
const resumeCapture = () => asyncStorageListener.resume();
|
|
668
|
-
|
|
669
|
-
/**
|
|
670
|
-
* Check if event emission is currently paused
|
|
671
|
-
*
|
|
672
|
-
* @returns True if paused, false otherwise
|
|
673
|
-
*/
|
|
674
|
-
exports.resumeCapture = resumeCapture;
|
|
675
|
-
const isPaused = () => asyncStorageListener.paused;
|
|
676
|
-
|
|
677
|
-
/**
|
|
678
|
-
* Export the singleton instance for advanced usage
|
|
679
|
-
*
|
|
680
|
-
* @example
|
|
681
|
-
* ```typescript
|
|
682
|
-
* import asyncStorageListener from './AsyncStorageListener';
|
|
683
|
-
*
|
|
684
|
-
* // Access advanced methods directly
|
|
685
|
-
* if (asyncStorageListener.isActive) {
|
|
686
|
-
* console.log(`${asyncStorageListener.listenerCount} listeners active`);
|
|
687
|
-
* }
|
|
688
|
-
* ```
|
|
689
|
-
*/
|
|
690
|
-
exports.isPaused = isPaused;
|
|
691
|
-
var _default = exports.default = asyncStorageListener;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.stopListening=exports.startListening=exports.resumeCapture=exports.removeAllListeners=exports.pauseCapture=exports.isPaused=exports.isListening=exports.getListenerCount=exports.default=exports.addListener=void 0;var _asyncStorageCompat=require("./asyncStorageCompat");const ORIGINALS_KEY=Symbol.for("@buoy-gg/storage.asyncStorageOriginals");function readStashedOriginals(){return globalThis[ORIGINALS_KEY]??null}function stashOriginals(n){globalThis[ORIGINALS_KEY]=n}class AsyncStorageListener{listeners=[];isListening=false;isInitialized=false;isPaused=false;ignoredKeys=new Set(["@react_buoy_storage_event_filters","@react_buoy_storage_key_filters","@react_buoy_storage_is_monitoring","REACT_QUERY_OFFLINE_CACHE"]);originalSetItem=null;originalRemoveItem=null;originalMergeItem=null;originalClear=null;originalMultiSet=null;originalMultiRemove=null;originalMultiMerge=null;originalSetMany=null;originalRemoveMany=null;shouldIgnoreKey(t){if(this.ignoredKeys.has(t))return true;for(const i of this.ignoredKeys){if(t.startsWith(i))return true}return false}adoptOriginals(t){this.originalSetItem=t.setItem;this.originalRemoveItem=t.removeItem;this.originalClear=t.clear;this.originalMergeItem=t.mergeItem;this.originalMultiSet=t.multiSet;this.originalMultiRemove=t.multiRemove;this.originalMultiMerge=t.multiMerge;this.originalSetMany=t.setMany;this.originalRemoveMany=t.removeMany}async initialize(){if(this.isInitialized){return true}if(_asyncStorageCompat.asyncStorage.setItem.name==="swizzled_setItem"){const i=readStashedOriginals();if(!i){return false}this.adoptOriginals(i);this.isInitialized=true;return true}const t={setItem:_asyncStorageCompat.asyncStorage.setItem.bind(_asyncStorageCompat.asyncStorage),removeItem:_asyncStorageCompat.asyncStorage.removeItem.bind(_asyncStorageCompat.asyncStorage),clear:_asyncStorageCompat.asyncStorage.clear.bind(_asyncStorageCompat.asyncStorage),mergeItem:null,multiSet:null,multiRemove:null,multiMerge:null,setMany:null,removeMany:null};if(_asyncStorageCompat.asyncStorageCaps.hasLegacyMultiApi){t.multiSet=_asyncStorageCompat.asyncStorage.multiSet.bind(_asyncStorageCompat.asyncStorage);t.multiRemove=_asyncStorageCompat.asyncStorage.multiRemove.bind(_asyncStorageCompat.asyncStorage);t.mergeItem=_asyncStorageCompat.asyncStorage.mergeItem.bind(_asyncStorageCompat.asyncStorage);t.multiMerge=_asyncStorageCompat.asyncStorage.multiMerge?_asyncStorageCompat.asyncStorage.multiMerge.bind(_asyncStorageCompat.asyncStorage):null}else{t.setMany=_asyncStorageCompat.asyncStorage.setMany.bind(_asyncStorageCompat.asyncStorage);t.removeMany=_asyncStorageCompat.asyncStorage.removeMany.bind(_asyncStorageCompat.asyncStorage)}stashOriginals(t);this.adoptOriginals(t);this.isInitialized=true;return true}restoreOriginalMethods(){if(!_asyncStorageCompat.asyncStorage||!this.originalSetItem){return}_asyncStorageCompat.asyncStorage.setItem=this.originalSetItem;if(this.originalRemoveItem){_asyncStorageCompat.asyncStorage.removeItem=this.originalRemoveItem}if(this.originalClear){_asyncStorageCompat.asyncStorage.clear=this.originalClear}if(this.originalMergeItem){_asyncStorageCompat.asyncStorage.mergeItem=this.originalMergeItem}if(this.originalMultiSet){_asyncStorageCompat.asyncStorage.multiSet=this.originalMultiSet}if(this.originalMultiRemove){_asyncStorageCompat.asyncStorage.multiRemove=this.originalMultiRemove}if(this.originalMultiMerge){_asyncStorageCompat.asyncStorage.multiMerge=this.originalMultiMerge}if(this.originalSetMany){_asyncStorageCompat.asyncStorage.setMany=this.originalSetMany}if(this.originalRemoveMany){_asyncStorageCompat.asyncStorage.removeMany=this.originalRemoveMany}}emit(t){if(this.isPaused){return}if(this.listeners.length===0){return}this.listeners.forEach(i=>{try{i(t)}catch(e){}})}async handleBatchSet(t,i,e="multiSet"){const s=t.filter(([l])=>!this.shouldIgnoreKey(l));if(s.length===0){return i()}const r=s.map(([l])=>l);let a=[];try{a=await(0,_asyncStorageCompat.readMany)(r)}catch{}const o=await i();this.emit({action:e,timestamp:new Date,data:{pairs:s,prevPairs:a}});return o}async handleBatchRemove(t,i){const e=t.filter(a=>!this.shouldIgnoreKey(a));if(e.length===0){return i()}let s=[];try{s=await(0,_asyncStorageCompat.readMany)(e)}catch{}const r=await i();this.emit({action:"multiRemove",timestamp:new Date,data:{keys:e,prevPairs:s}});return r}async startListening(){if(this.isListening){return}const t=await this.initialize();if(!t){return}if(_asyncStorageCompat.asyncStorage&&_asyncStorageCompat.asyncStorage.setItem.name==="swizzled_setItem"){this.restoreOriginalMethods()}const i=async(e,s)=>{if(!this.shouldIgnoreKey(e)){const r=this.originalSetItem?await _asyncStorageCompat.asyncStorage.getItem(e):null;const a=this.originalSetItem?await this.originalSetItem(e,s):void 0;this.emit({action:"setItem",timestamp:new Date,data:{key:e,value:s,prevValue:r}});return a}return this.originalSetItem?this.originalSetItem(e,s):Promise.resolve()};Object.defineProperty(i,"name",{value:"swizzled_setItem"});if(_asyncStorageCompat.asyncStorage){_asyncStorageCompat.asyncStorage.setItem=i}if(_asyncStorageCompat.asyncStorage){_asyncStorageCompat.asyncStorage.removeItem=async e=>{if(!this.shouldIgnoreKey(e)){const s=this.originalRemoveItem?await _asyncStorageCompat.asyncStorage.getItem(e):null;const r=this.originalRemoveItem?await this.originalRemoveItem(e):void 0;this.emit({action:"removeItem",timestamp:new Date,data:{key:e,prevValue:s}});return r}return this.originalRemoveItem?this.originalRemoveItem(e):Promise.resolve()}}if(_asyncStorageCompat.asyncStorageCaps.hasMergeApi&&_asyncStorageCompat.asyncStorage){_asyncStorageCompat.asyncStorage.mergeItem=async(e,s)=>{if(!this.shouldIgnoreKey(e)){const r=this.originalMergeItem?await _asyncStorageCompat.asyncStorage.getItem(e):null;const a=this.originalMergeItem?await this.originalMergeItem(e,s):void 0;this.emit({action:"mergeItem",timestamp:new Date,data:{key:e,value:s,prevValue:r}});return a}return this.originalMergeItem?this.originalMergeItem(e,s):Promise.resolve()}}if(_asyncStorageCompat.asyncStorage){_asyncStorageCompat.asyncStorage.clear=async()=>{let e=[];try{const r=await _asyncStorageCompat.asyncStorage.getAllKeys();const a=r.filter(o=>!this.shouldIgnoreKey(o));if(a.length>0){e=await(0,_asyncStorageCompat.readMany)(a)}}catch{}const s=this.originalClear?await this.originalClear():void 0;this.emit({action:"clear",timestamp:new Date,data:{prevPairs:e}});return s}}if(_asyncStorageCompat.asyncStorageCaps.hasLegacyMultiApi&&_asyncStorageCompat.asyncStorage){_asyncStorageCompat.asyncStorage.multiSet=e=>this.handleBatchSet(e,()=>this.originalMultiSet?this.originalMultiSet(e):Promise.resolve());_asyncStorageCompat.asyncStorage.multiRemove=e=>this.handleBatchRemove(e,()=>this.originalMultiRemove?this.originalMultiRemove(e):Promise.resolve());if(this.originalMultiMerge){_asyncStorageCompat.asyncStorage.multiMerge=e=>this.handleBatchSet(e,()=>this.originalMultiMerge?this.originalMultiMerge(e):Promise.resolve(),"multiMerge")}}else if(_asyncStorageCompat.asyncStorage){_asyncStorageCompat.asyncStorage.setMany=e=>this.handleBatchSet(Object.entries(e),()=>this.originalSetMany?this.originalSetMany(e):Promise.resolve());_asyncStorageCompat.asyncStorage.removeMany=e=>this.handleBatchRemove(e,()=>this.originalRemoveMany?this.originalRemoveMany(e):Promise.resolve())}this.isListening=true}stopListening(){if(!this.isListening){return}if(!_asyncStorageCompat.asyncStorage){return}this.restoreOriginalMethods();this.isListening=false}addListener(t){this.listeners.push(t);return()=>{const i=this.listeners.indexOf(t);if(i>-1){this.listeners.splice(i,1)}}}removeAllListeners(){this.listeners=[]}get isActive(){return this.isListening}get listenerCount(){return this.listeners.length}pause(){this.isPaused=true}resume(){this.isPaused=false}get paused(){return this.isPaused}}const asyncStorageListener=new AsyncStorageListener;const startListening=()=>asyncStorageListener.startListening();exports.startListening=startListening;const stopListening=()=>asyncStorageListener.stopListening();exports.stopListening=stopListening;const addListener=n=>asyncStorageListener.addListener(n);exports.addListener=addListener;const removeAllListeners=()=>asyncStorageListener.removeAllListeners();exports.removeAllListeners=removeAllListeners;const isListening=()=>asyncStorageListener.isActive;exports.isListening=isListening;const getListenerCount=()=>asyncStorageListener.listenerCount;exports.getListenerCount=getListenerCount;const pauseCapture=()=>asyncStorageListener.pause();exports.pauseCapture=pauseCapture;const resumeCapture=()=>asyncStorageListener.resume();exports.resumeCapture=resumeCapture;const isPaused=()=>asyncStorageListener.paused;exports.isPaused=isPaused;var _default=exports.default=asyncStorageListener;
|