@buoy-gg/storage 7.0.40 → 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 -86
- package/lib/commonjs/index.js +1 -346
- package/lib/commonjs/preset.js +1 -80
- 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 -1258
- package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -257
- package/lib/commonjs/storage/components/MMKVInstanceSelector.js +1 -418
- package/lib/commonjs/storage/components/SelectionActionBar.js +1 -207
- package/lib/commonjs/storage/components/StorageActionButtons.js +1 -241
- 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 -117
- package/lib/commonjs/storage/components/StorageEventDetailContent.js +1 -494
- package/lib/commonjs/storage/components/StorageEventFilterView.js +1 -159
- 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 -344
- 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 -143
- 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 -159
- 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 -478
- 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 -0
- 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 -0
- package/lib/commonjs/storage/utils/browserStorageLifecycle.web.js +1 -0
- 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 -0
- 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 -0
- package/lib/commonjs/storage/utils/storageLabels.web.js +1 -0
- 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 -112
- package/lib/module/preset.js +1 -76
- 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 -1256
- package/lib/module/storage/components/MMKVInstanceInfoPanel.js +1 -253
- package/lib/module/storage/components/MMKVInstanceSelector.js +1 -414
- package/lib/module/storage/components/SelectionActionBar.js +1 -204
- package/lib/module/storage/components/StorageActionButtons.js +1 -237
- 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 -112
- package/lib/module/storage/components/StorageEventDetailContent.js +1 -490
- package/lib/module/storage/components/StorageEventFilterView.js +1 -155
- 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 -341
- 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 -138
- 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 -156
- 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 -474
- 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 -0
- 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 -0
- package/lib/module/storage/utils/browserStorageLifecycle.web.js +1 -0
- 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 -0
- 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 -0
- package/lib/module/storage/utils/storageLabels.web.js +1 -0
- 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/typescript/index.d.ts +1 -0
- package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts +0 -8
- package/lib/typescript/storage/components/StorageEventCard.d.ts +0 -7
- package/lib/typescript/storage/components/StorageKeyRow.d.ts +2 -6
- package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts +0 -15
- package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts +2 -2
- package/lib/typescript/storage/sync/storageSyncAdapter.d.ts +7 -13
- package/lib/typescript/storage/utils/AsyncStorageListener.web.d.ts +24 -0
- package/lib/typescript/storage/utils/browserStorageLifecycle.d.ts +3 -0
- package/lib/typescript/storage/utils/browserStorageLifecycle.web.d.ts +2 -0
- package/lib/typescript/storage/utils/mmkvAvailability.web.d.ts +4 -0
- package/lib/typescript/storage/utils/storageLabels.d.ts +8 -0
- package/lib/typescript/storage/utils/storageLabels.web.d.ts +8 -0
- package/lib/web/index.mjs +4 -0
- package/package.json +40 -14
- package/lib/commonjs/storage/components/DiffViewer/DiffOptionsPanel.js +0 -356
- package/lib/commonjs/storage/components/DiffViewer/components/DiffSummary.js +0 -122
- package/lib/commonjs/storage/components/StorageKeyEditorScreen.js +0 -414
- package/lib/commonjs/storage/components/StorageScalarKeyEditor.js +0 -61
- package/lib/commonjs/storage/components/StorageValueEditModal.js +0 -24
- package/lib/commonjs/storage/hooks/useKeyEditor.js +0 -31
- package/lib/commonjs/storage/hooks/useTreeDraft.js +0 -25
- package/lib/module/storage/components/DiffViewer/DiffOptionsPanel.js +0 -352
- package/lib/module/storage/components/DiffViewer/components/DiffSummary.js +0 -118
- package/lib/module/storage/components/StorageKeyEditorScreen.js +0 -410
- package/lib/module/storage/components/StorageScalarKeyEditor.js +0 -57
- package/lib/module/storage/components/StorageValueEditModal.js +0 -20
- package/lib/module/storage/hooks/useKeyEditor.js +0 -27
- package/lib/module/storage/hooks/useTreeDraft.js +0 -21
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/preset.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts +0 -18
- package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +0 -1
- package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts +0 -12
- package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.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/StorageKeyEditorScreen.d.ts +0 -42
- package/lib/typescript/storage/components/StorageKeyEditorScreen.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/StorageScalarKeyEditor.d.ts +0 -24
- package/lib/typescript/storage/components/StorageScalarKeyEditor.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/components/StorageValueEditModal.d.ts +0 -14
- package/lib/typescript/storage/components/StorageValueEditModal.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +0 -1
- package/lib/typescript/storage/hooks/useKeyEditor.d.ts +0 -27
- package/lib/typescript/storage/hooks/useKeyEditor.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/hooks/useTreeDraft.d.ts +0 -16
- package/lib/typescript/storage/hooks/useTreeDraft.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/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/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/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/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,474 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
4
|
-
import { approxJsonSize, isDevToolsStorageKey, isOverWireBudget, isJsonSerializable } from "@buoy-gg/shared-ui";
|
|
5
|
-
import { readMany, writeMany, removeMany } from "../utils/asyncStorageCompat";
|
|
6
|
-
import { batchPairsOf, storageEventStore } from "../stores/storageEventStore";
|
|
7
|
-
import { clearAllAppStorage } from "../utils/clearAllStorage";
|
|
8
|
-
import { undoOperation, jumpToState, canUndo } from "../utils/storageTimeTravelUtils";
|
|
9
|
-
import { mmkvInstanceRegistry } from "../utils/MMKVInstanceRegistry";
|
|
10
|
-
import { detectMMKVType } from "../utils/mmkvTypeDetection";
|
|
11
|
-
import { secureStoreRegistry } from "../utils/SecureStoreRegistry";
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Sentinel used in WIRE-FORM snapshots in place of oversized values.
|
|
15
|
-
* Storage events, MMKV browse dumps, and SecureStore dumps all reuse this
|
|
16
|
-
* marker. Dashboards fetch the real payload via `getEventDetail` / `mmkv.get`
|
|
17
|
-
* / `secure.get`.
|
|
18
|
-
*/
|
|
19
|
-
export const VALUE_ON_DEVICE = Object.freeze({
|
|
20
|
-
__buoyValueOnDevice: true,
|
|
21
|
-
note: "Value stays on the device — fetched on demand via getEventDetail / mmkv.get / secure.get."
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
/** Max serialized bytes of one storage value on the list snapshot. */
|
|
25
|
-
export const SNAPSHOT_VALUE_INLINE_LIMIT = 16 * 1024;
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Total inline budget for one snapshot's event list, held under the emit
|
|
29
|
-
* layer's 2MB so a snapshot is never DROPPED (a drop leaves the whole panel
|
|
30
|
-
* stale). Per-value caps alone don't get there: the store keeps 500 events, so
|
|
31
|
-
* 500 writes of an individually-legal 9KB value still total ~4.7MB. Newest
|
|
32
|
-
* events keep their values inline; once the budget is spent, older ones
|
|
33
|
-
* degrade to metadata + fetch-on-demand.
|
|
34
|
-
*/
|
|
35
|
-
export const SNAPSHOT_EVENTS_BUDGET = 1.25 * 1024 * 1024;
|
|
36
|
-
const MAX_EVENT_DETAIL_BYTES = 8 * 1024 * 1024;
|
|
37
|
-
function toWireValue(value) {
|
|
38
|
-
if (value === undefined) return value;
|
|
39
|
-
return isOverWireBudget(value, SNAPSHOT_VALUE_INLINE_LIMIT) ? VALUE_ON_DEVICE : value;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/**
|
|
43
|
-
* Apply `map` to every payload field an event carries, preserving object
|
|
44
|
-
* identity when nothing changed (the desktop mirror feeds these into effect
|
|
45
|
-
* dependencies, so a fresh object per snapshot would re-run them).
|
|
46
|
-
*
|
|
47
|
-
* The cast is deliberate and load-bearing: the wire form intentionally puts a
|
|
48
|
-
* marker OBJECT where the domain type declares a string, because the real
|
|
49
|
-
* value stayed on the device. `StorageEvent` describes on-device truth; this
|
|
50
|
-
* is its wire projection.
|
|
51
|
-
*/
|
|
52
|
-
function mapEventValues(event, map) {
|
|
53
|
-
const data = event.data;
|
|
54
|
-
if (!data) return event;
|
|
55
|
-
const value = map(data.value);
|
|
56
|
-
const prevValue = map(data.prevValue);
|
|
57
|
-
const batch = batchPairsOf(event);
|
|
58
|
-
const pairs = map(batch.pairs);
|
|
59
|
-
const prevPairs = map(batch.prevPairs);
|
|
60
|
-
if (value === data.value && prevValue === data.prevValue && pairs === batch.pairs && prevPairs === batch.prevPairs) {
|
|
61
|
-
return event;
|
|
62
|
-
}
|
|
63
|
-
return {
|
|
64
|
-
...event,
|
|
65
|
-
data: {
|
|
66
|
-
...data,
|
|
67
|
-
value,
|
|
68
|
-
prevValue,
|
|
69
|
-
// Only AsyncStorage events have these; see batchPairsOf.
|
|
70
|
-
...(event.storageType === "async" ? {
|
|
71
|
-
pairs,
|
|
72
|
-
prevPairs
|
|
73
|
-
} : {})
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
function capDetailValue(value) {
|
|
78
|
-
if (value === undefined) return value;
|
|
79
|
-
if (!isOverWireBudget(value, MAX_EVENT_DETAIL_BYTES)) return value;
|
|
80
|
-
return isJsonSerializable(value) ? {
|
|
81
|
-
__buoyTruncated: true,
|
|
82
|
-
note: `Exceeds the ${MAX_EVENT_DETAIL_BYTES / (1024 * 1024)}MB detail limit — inspect it on-device.`
|
|
83
|
-
} : VALUE_ON_DEVICE;
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** One event's wire form plus its measured cost, so the budget pass is free. */
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Per-event wire cache. The store never mutates an event in place — `addEvent`
|
|
90
|
-
* prepends and `hydrateEvent` replaces — so keying on identity is correct and
|
|
91
|
-
* self-invalidating. Without it every value is re-measured on all ~5 snapshots
|
|
92
|
-
* per second for as long as it stays in the list, which for storage means
|
|
93
|
-
* re-walking megabytes of strings per tick.
|
|
94
|
-
*/
|
|
95
|
-
const wireCache = new WeakMap();
|
|
96
|
-
const strippedCache = new WeakMap();
|
|
97
|
-
function wireFor(event) {
|
|
98
|
-
const cached = wireCache.get(event);
|
|
99
|
-
if (cached) return cached;
|
|
100
|
-
let entry;
|
|
101
|
-
try {
|
|
102
|
-
const wire = mapEventValues(event, toWireValue);
|
|
103
|
-
entry = {
|
|
104
|
-
event: wire,
|
|
105
|
-
bytes: approxJsonSize(wire, SNAPSHOT_EVENTS_BUDGET).bytes
|
|
106
|
-
};
|
|
107
|
-
} catch {
|
|
108
|
-
// A hostile getter can blow up the walk itself. Degrading this ONE event
|
|
109
|
-
// beats letting getSnapshot throw and taking the whole panel with it.
|
|
110
|
-
const wire = mapEventValues(event, () => VALUE_ON_DEVICE);
|
|
111
|
-
entry = {
|
|
112
|
-
event: wire,
|
|
113
|
-
bytes: 1024
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
wireCache.set(event, entry);
|
|
117
|
-
return entry;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/** Metadata-only form for the tail of the list once the budget is spent. */
|
|
121
|
-
function strippedFor(event) {
|
|
122
|
-
const cached = strippedCache.get(event);
|
|
123
|
-
if (cached) return cached;
|
|
124
|
-
const wire = mapEventValues(event, v => v === undefined ? undefined : VALUE_ON_DEVICE);
|
|
125
|
-
const entry = {
|
|
126
|
-
event: wire,
|
|
127
|
-
bytes: approxJsonSize(wire, SNAPSHOT_EVENTS_BUDGET).bytes
|
|
128
|
-
};
|
|
129
|
-
strippedCache.set(event, entry);
|
|
130
|
-
return entry;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
* Spend the snapshot budget newest-first. The store keeps events newest-first,
|
|
135
|
-
* so the developer keeps full detail on what they are actually looking at and
|
|
136
|
-
* the tail degrades rather than the whole panel being dropped.
|
|
137
|
-
*/
|
|
138
|
-
function fitEventsToBudget(events) {
|
|
139
|
-
const out = new Array(events.length);
|
|
140
|
-
let spent = 0;
|
|
141
|
-
for (let i = 0; i < events.length; i++) {
|
|
142
|
-
const full = wireFor(events[i]);
|
|
143
|
-
if (spent + full.bytes <= SNAPSHOT_EVENTS_BUDGET) {
|
|
144
|
-
out[i] = full.event;
|
|
145
|
-
spent += full.bytes;
|
|
146
|
-
} else {
|
|
147
|
-
const lean = strippedFor(events[i]);
|
|
148
|
-
out[i] = lean.event;
|
|
149
|
-
spent += lean.bytes;
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return out;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
/** One MMKV entry in a `mmkv.snapshot` result. */
|
|
156
|
-
|
|
157
|
-
/** One MMKV instance in a `mmkv.snapshot` result. */
|
|
158
|
-
|
|
159
|
-
/** One registered key in a `secure.snapshot` result. */
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Resolve an MMKV instance for WRITING, refusing the ones the app registered
|
|
163
|
-
* read-only.
|
|
164
|
-
*
|
|
165
|
-
* The registry has always tracked `readOnly`, but nothing enforced it: any sync
|
|
166
|
-
* client — dashboard or MCP — could write to an instance the app explicitly
|
|
167
|
-
* declared immutable. That was harmless while the tool could only read; it
|
|
168
|
-
* stops being harmless the moment there's an edit UI pointed at it.
|
|
169
|
-
*/
|
|
170
|
-
function assertMMKVWritable(instanceId) {
|
|
171
|
-
const registered = mmkvInstanceRegistry.get(instanceId);
|
|
172
|
-
if (!registered) {
|
|
173
|
-
throw new Error(`No MMKV instance registered as "${instanceId}"`);
|
|
174
|
-
}
|
|
175
|
-
if (registered.instance?.isReadOnly) {
|
|
176
|
-
throw new Error(`MMKV instance "${instanceId}" is registered read-only`);
|
|
177
|
-
}
|
|
178
|
-
return registered.instance;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Sync adapter for the storage tool, consumed by @buoy-gg/external-sync's
|
|
183
|
-
* `useExternalSync` (structurally matches its ToolSyncAdapter interface so
|
|
184
|
-
* this package doesn't need a dependency on it).
|
|
185
|
-
*
|
|
186
|
-
* Subscribing starts the underlying capture lifecycle (including the initial
|
|
187
|
-
* key scan), so storage events are only recorded while a dashboard is
|
|
188
|
-
* watching.
|
|
189
|
-
*
|
|
190
|
-
* The `async.*` actions mirror the AsyncStorage API so the desktop dashboard
|
|
191
|
-
* can proxy its browse/edit mode against the device's real storage.
|
|
192
|
-
*
|
|
193
|
-
* v2: oversized / unserializable event values are replaced with
|
|
194
|
-
* VALUE_ON_DEVICE. Dashboards fetch them via `getEventDetail`.
|
|
195
|
-
*/
|
|
196
|
-
export const storageSyncAdapter = {
|
|
197
|
-
// v3: a total snapshot budget, so a burst of individually-legal values
|
|
198
|
-
// degrades the oldest events instead of the emit layer dropping the panel.
|
|
199
|
-
version: 3,
|
|
200
|
-
// Strip Buoy's OWN devtool keys (@react_buoy*, @buoy*, buoy-*, legacy) at the
|
|
201
|
-
// source so no sync client (desktop, MCP, raw socket) ever sees them as if
|
|
202
|
-
// they were app data — matching the tools' default key filters, but
|
|
203
|
-
// authoritative instead of UI-only.
|
|
204
|
-
getSnapshot: () => fitEventsToBudget(storageEventStore.getEvents().filter(e => {
|
|
205
|
-
const key = e.data?.key;
|
|
206
|
-
return !(typeof key === "string" && isDevToolsStorageKey(key));
|
|
207
|
-
})),
|
|
208
|
-
subscribe: onChange => storageEventStore.subscribeToEvents(onChange),
|
|
209
|
-
actions: {
|
|
210
|
-
clearEvents: () => {
|
|
211
|
-
storageEventStore.clearEvents();
|
|
212
|
-
},
|
|
213
|
-
/**
|
|
214
|
-
* On-demand detail: one event's real value/prevValue/pairs.
|
|
215
|
-
* The per-snapshot stream stays payload-light; this is the explicit,
|
|
216
|
-
* size-guarded channel for the detail pane (and for time-travel undo,
|
|
217
|
-
* which needs `prevValue`).
|
|
218
|
-
*/
|
|
219
|
-
getEventDetail: params => {
|
|
220
|
-
const {
|
|
221
|
-
id
|
|
222
|
-
} = params ?? {};
|
|
223
|
-
if (!id) return {
|
|
224
|
-
found: false,
|
|
225
|
-
reason: "missing id"
|
|
226
|
-
};
|
|
227
|
-
const event = storageEventStore.getEvents().find(e => e.id === id);
|
|
228
|
-
if (!event) return {
|
|
229
|
-
found: false,
|
|
230
|
-
reason: "unknown id"
|
|
231
|
-
};
|
|
232
|
-
const detailed = mapEventValues(event, capDetailValue);
|
|
233
|
-
return {
|
|
234
|
-
found: true,
|
|
235
|
-
id,
|
|
236
|
-
event: detailed
|
|
237
|
-
};
|
|
238
|
-
},
|
|
239
|
-
/** Clears all app storage keys, preserving dev tools settings. */
|
|
240
|
-
clearAppStorage: () => clearAllAppStorage(),
|
|
241
|
-
// ── Time travel (same code path as the modal's UNDO / JUMP buttons) ──
|
|
242
|
-
// The UI swallows failures silently; these THROW so a caller (desktop, MCP)
|
|
243
|
-
// gets the actual reason back instead of a no-op.
|
|
244
|
-
|
|
245
|
-
/** Undo one event, addressed by the `id` the store assigned it. */
|
|
246
|
-
"timeTravel.undo": async params => {
|
|
247
|
-
const id = params?.id;
|
|
248
|
-
if (!id) throw new Error("timeTravel.undo requires an event `id`");
|
|
249
|
-
const event = storageEventStore.getEvents().find(e => e.id === id);
|
|
250
|
-
if (!event) throw new Error(`No storage event with id "${id}"`);
|
|
251
|
-
if (event.storageType === "mmkv") {
|
|
252
|
-
throw new Error("Time travel supports AsyncStorage events only");
|
|
253
|
-
}
|
|
254
|
-
const asyncEvent = event;
|
|
255
|
-
if (!canUndo(asyncEvent)) {
|
|
256
|
-
throw new Error(`Event "${id}" (${asyncEvent.action}) has no previous value captured, so it cannot be undone`);
|
|
257
|
-
}
|
|
258
|
-
await undoOperation(asyncEvent);
|
|
259
|
-
return {
|
|
260
|
-
undone: true,
|
|
261
|
-
action: asyncEvent.action,
|
|
262
|
-
key: asyncEvent.data?.key
|
|
263
|
-
};
|
|
264
|
-
},
|
|
265
|
-
/**
|
|
266
|
-
* Jump storage back to the state as of one event. `scope: "key"` (default)
|
|
267
|
-
* replays only that key's history, matching the modal's JUMP button;
|
|
268
|
-
* `scope: "all"` replays every captured AsyncStorage event.
|
|
269
|
-
*/
|
|
270
|
-
"timeTravel.jump": async params => {
|
|
271
|
-
const {
|
|
272
|
-
id,
|
|
273
|
-
scope = "key"
|
|
274
|
-
} = params ?? {};
|
|
275
|
-
if (!id) throw new Error("timeTravel.jump requires an event `id`");
|
|
276
|
-
|
|
277
|
-
// Oldest-first, which is the order jumpToState replays in.
|
|
278
|
-
const all = storageEventStore.getEvents().filter(e => e.storageType !== "mmkv").slice().reverse();
|
|
279
|
-
const target = all.find(e => e.id === id);
|
|
280
|
-
if (!target) throw new Error(`No AsyncStorage event with id "${id}"`);
|
|
281
|
-
const timeline = scope === "all" ? all : all.filter(e => e.data?.key === target.data?.key);
|
|
282
|
-
const index = timeline.findIndex(e => e.id === id);
|
|
283
|
-
if (index === -1) throw new Error(`Event "${id}" is not in the timeline`);
|
|
284
|
-
await jumpToState(timeline, index);
|
|
285
|
-
return {
|
|
286
|
-
jumped: true,
|
|
287
|
-
scope,
|
|
288
|
-
replayed: index + 1,
|
|
289
|
-
of: timeline.length,
|
|
290
|
-
key: target.data?.key
|
|
291
|
-
};
|
|
292
|
-
},
|
|
293
|
-
// ── Remote AsyncStorage proxy (desktop browse/edit mode) ──
|
|
294
|
-
// Single-item methods share the same signature across async-storage v2/v3;
|
|
295
|
-
// batch methods go through the compat helpers (which translate to v3's
|
|
296
|
-
// getMany/setMany/removeMany) and keep the v2 tuple/pairs shape on the wire.
|
|
297
|
-
// Read paths filter out Buoy's own devtool keys so they're never exposed.
|
|
298
|
-
"async.getAllKeys": async () => (await AsyncStorage.getAllKeys()).filter(k => !isDevToolsStorageKey(k)),
|
|
299
|
-
"async.multiGet": async params => (await readMany(params.keys)).filter(([k]) => !isDevToolsStorageKey(k)),
|
|
300
|
-
"async.getItem": params => {
|
|
301
|
-
const {
|
|
302
|
-
key
|
|
303
|
-
} = params;
|
|
304
|
-
return isDevToolsStorageKey(key) ? Promise.resolve(null) : AsyncStorage.getItem(key);
|
|
305
|
-
},
|
|
306
|
-
"async.setItem": params => {
|
|
307
|
-
const {
|
|
308
|
-
key,
|
|
309
|
-
value
|
|
310
|
-
} = params;
|
|
311
|
-
return AsyncStorage.setItem(key, value);
|
|
312
|
-
},
|
|
313
|
-
"async.removeItem": params => AsyncStorage.removeItem(params.key),
|
|
314
|
-
"async.multiRemove": params => removeMany(params.keys),
|
|
315
|
-
"async.multiSet": params => writeMany(params.pairs),
|
|
316
|
-
"async.clear": () => AsyncStorage.clear(),
|
|
317
|
-
// ── Remote MMKV proxy (desktop browse mode + MCP) ──
|
|
318
|
-
// MMKV has no remote presence off-device; these read/write the registered
|
|
319
|
-
// instances so sync clients can browse them like AsyncStorage.
|
|
320
|
-
"mmkv.snapshot": () => mmkvInstanceRegistry.getAll().map(({
|
|
321
|
-
id,
|
|
322
|
-
instance,
|
|
323
|
-
encrypted,
|
|
324
|
-
readOnly
|
|
325
|
-
}) => {
|
|
326
|
-
let entries = [];
|
|
327
|
-
try {
|
|
328
|
-
entries = instance.getAllKeys().filter(key => !isDevToolsStorageKey(key)).map(key => {
|
|
329
|
-
const {
|
|
330
|
-
value,
|
|
331
|
-
type: valueType
|
|
332
|
-
} = detectMMKVType(instance, key);
|
|
333
|
-
return {
|
|
334
|
-
key,
|
|
335
|
-
value: toWireValue(value),
|
|
336
|
-
valueType
|
|
337
|
-
};
|
|
338
|
-
});
|
|
339
|
-
} catch {
|
|
340
|
-
// Instance unreadable — return it with no entries rather than failing
|
|
341
|
-
}
|
|
342
|
-
return {
|
|
343
|
-
id,
|
|
344
|
-
encrypted,
|
|
345
|
-
readOnly,
|
|
346
|
-
entries
|
|
347
|
-
};
|
|
348
|
-
}),
|
|
349
|
-
/**
|
|
350
|
-
* On-demand MMKV value. `mmkv.snapshot` omits oversized strings so a
|
|
351
|
-
* browse poll cannot blow the action-result budget; this is the
|
|
352
|
-
* size-guarded channel for one key.
|
|
353
|
-
*/
|
|
354
|
-
"mmkv.get": params => {
|
|
355
|
-
const {
|
|
356
|
-
instanceId,
|
|
357
|
-
key
|
|
358
|
-
} = params ?? {};
|
|
359
|
-
if (!instanceId || !key) {
|
|
360
|
-
return {
|
|
361
|
-
found: false,
|
|
362
|
-
reason: "missing instanceId/key"
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
const registered = mmkvInstanceRegistry.get(instanceId);
|
|
366
|
-
if (!registered) {
|
|
367
|
-
return {
|
|
368
|
-
found: false,
|
|
369
|
-
reason: "unknown instance"
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
const {
|
|
373
|
-
value,
|
|
374
|
-
type: valueType
|
|
375
|
-
} = detectMMKVType(registered.instance, key);
|
|
376
|
-
return {
|
|
377
|
-
found: true,
|
|
378
|
-
instanceId,
|
|
379
|
-
key,
|
|
380
|
-
value: capDetailValue(value),
|
|
381
|
-
valueType
|
|
382
|
-
};
|
|
383
|
-
},
|
|
384
|
-
"mmkv.set": params => {
|
|
385
|
-
const {
|
|
386
|
-
instanceId,
|
|
387
|
-
key,
|
|
388
|
-
value
|
|
389
|
-
} = params;
|
|
390
|
-
assertMMKVWritable(instanceId).set(key, value);
|
|
391
|
-
},
|
|
392
|
-
"mmkv.remove": params => {
|
|
393
|
-
const {
|
|
394
|
-
instanceId,
|
|
395
|
-
key
|
|
396
|
-
} = params;
|
|
397
|
-
const instance = assertMMKVWritable(instanceId);
|
|
398
|
-
// v4 renamed delete() to remove() — support both
|
|
399
|
-
if (instance.remove) instance.remove(key);else instance.delete?.(key);
|
|
400
|
-
},
|
|
401
|
-
// ── Remote SecureStore proxy ──
|
|
402
|
-
// Only registered keys are known (SecureStore has no enumeration API).
|
|
403
|
-
// Biometric-protected keys are never read — reads would fire an auth prompt.
|
|
404
|
-
"secure.keys": () => secureStoreRegistry.getAll().map(({
|
|
405
|
-
key,
|
|
406
|
-
options,
|
|
407
|
-
description
|
|
408
|
-
}) => ({
|
|
409
|
-
key,
|
|
410
|
-
description,
|
|
411
|
-
keychainService: options.keychainService,
|
|
412
|
-
requireAuthentication: options.requireAuthentication ?? false
|
|
413
|
-
})),
|
|
414
|
-
/**
|
|
415
|
-
* Every registered key WITH its value, in one round trip — the SecureStore
|
|
416
|
-
* counterpart to `mmkv.snapshot`. The dashboard polls this (the keychain
|
|
417
|
-
* has no change feed) and serves the browser from the result, instead of
|
|
418
|
-
* firing one `secure.get` per key per refresh.
|
|
419
|
-
*/
|
|
420
|
-
"secure.snapshot": async () => {
|
|
421
|
-
const module = secureStoreRegistry.getModule();
|
|
422
|
-
const entries = secureStoreRegistry.getAll();
|
|
423
|
-
const result = [];
|
|
424
|
-
for (const {
|
|
425
|
-
key,
|
|
426
|
-
options,
|
|
427
|
-
description
|
|
428
|
-
} of entries) {
|
|
429
|
-
let value = null;
|
|
430
|
-
// Biometric-protected keys are never read — that would fire an auth prompt.
|
|
431
|
-
if (module && !options.requireAuthentication) {
|
|
432
|
-
try {
|
|
433
|
-
value = await module.getItemAsync(key, options);
|
|
434
|
-
} catch {
|
|
435
|
-
// Unreadable (e.g. keychain state changed) — report as unset
|
|
436
|
-
}
|
|
437
|
-
}
|
|
438
|
-
result.push({
|
|
439
|
-
key,
|
|
440
|
-
description,
|
|
441
|
-
keychainService: options.keychainService,
|
|
442
|
-
requireAuthentication: options.requireAuthentication ?? false,
|
|
443
|
-
value: value == null ? value : toWireValue(value)
|
|
444
|
-
});
|
|
445
|
-
}
|
|
446
|
-
return result;
|
|
447
|
-
},
|
|
448
|
-
"secure.get": params => {
|
|
449
|
-
const {
|
|
450
|
-
key
|
|
451
|
-
} = params;
|
|
452
|
-
const entry = secureStoreRegistry.getAll().find(e => e.key === key);
|
|
453
|
-
const module = secureStoreRegistry.getModule();
|
|
454
|
-
if (!entry || !module || entry.options.requireAuthentication) {
|
|
455
|
-
return Promise.resolve(null);
|
|
456
|
-
}
|
|
457
|
-
return module.getItemAsync(key, entry.options);
|
|
458
|
-
},
|
|
459
|
-
/**
|
|
460
|
-
* Write a registered SecureStore key. Goes through the registry so the
|
|
461
|
-
* value is written with the SAME options it was registered with — writing
|
|
462
|
-
* with different `keychainService` options creates a second entry the app
|
|
463
|
-
* can't read. Biometric-protected keys throw rather than prompting.
|
|
464
|
-
*/
|
|
465
|
-
"secure.set": params => {
|
|
466
|
-
const {
|
|
467
|
-
key,
|
|
468
|
-
value
|
|
469
|
-
} = params;
|
|
470
|
-
return secureStoreRegistry.setValue(key, value);
|
|
471
|
-
},
|
|
472
|
-
"secure.delete": params => secureStoreRegistry.deleteValue(params.key)
|
|
473
|
-
}
|
|
474
|
-
};
|
|
1
|
+
"use strict";import l from"@react-native-async-storage/async-storage";import{approxJsonSize as p,isDevToolsStorageKey as y,isOverWireBudget as v,isJsonSerializable as T}from"@buoy-gg/shared-ui";import{readMany as b,writeMany as V,removeMany as I}from"../utils/asyncStorageCompat";import{batchPairsOf as M,storageEventStore as u}from"../stores/storageEventStore";import{clearAllAppStorage as _}from"../utils/clearAllStorage";import{undoOperation as q,jumpToState as K,canUndo as N}from"../utils/storageTimeTravelUtils";import{mmkvInstanceRegistry as f}from"../utils/MMKVInstanceRegistry";import{detectMMKVType as g}from"../utils/mmkvTypeDetection";import{secureStoreRegistry as c}from"../utils/SecureStoreRegistry";export const VALUE_ON_DEVICE=Object.freeze({__buoyValueOnDevice:true,note:"Value stays on the device \u2014 fetched on demand via getEventDetail / mmkv.get / secure.get."});export const SNAPSHOT_VALUE_INLINE_LIMIT=16*1024;export const SNAPSHOT_EVENTS_BUDGET=1.25*1024*1024;const h=8*1024*1024;function m(e){if(e===void 0)return e;return v(e,SNAPSHOT_VALUE_INLINE_LIMIT)?VALUE_ON_DEVICE:e}function d(e,t){const r=e.data;if(!r)return e;const n=t(r.value);const s=t(r.prevValue);const o=M(e);const i=t(o.pairs);const a=t(o.prevPairs);if(n===r.value&&s===r.prevValue&&i===o.pairs&&a===o.prevPairs){return e}return{...e,data:{...r,value:n,prevValue:s,...e.storageType==="async"?{pairs:i,prevPairs:a}:{}}}}function k(e){if(e===void 0)return e;if(!v(e,h))return e;return T(e)?{__buoyTruncated:true,note:`Exceeds the ${h/(1024*1024)}MB detail limit \u2014 inspect it on-device.`}:VALUE_ON_DEVICE}const E=new WeakMap;const w=new WeakMap;function x(e){const t=E.get(e);if(t)return t;let r;try{const n=d(e,m);r={event:n,bytes:p(n,SNAPSHOT_EVENTS_BUDGET).bytes}}catch{const n=d(e,()=>VALUE_ON_DEVICE);r={event:n,bytes:1024}}E.set(e,r);return r}function O(e){const t=w.get(e);if(t)return t;const r=d(e,s=>s===void 0?void 0:VALUE_ON_DEVICE);const n={event:r,bytes:p(r,SNAPSHOT_EVENTS_BUDGET).bytes};w.set(e,n);return n}function D(e){const t=new Array(e.length);let r=0;for(let n=0;n<e.length;n++){const s=x(e[n]);if(r+s.bytes<=SNAPSHOT_EVENTS_BUDGET){t[n]=s.event;r+=s.bytes}else{const o=O(e[n]);t[n]=o.event;r+=o.bytes}}return t}function A(e){const t=f.get(e);if(!t){throw new Error(`No MMKV instance registered as "${e}"`)}if(t.instance?.isReadOnly){throw new Error(`MMKV instance "${e}" is registered read-only`)}return t.instance}let S=[];export function setToolRequiredStorageKeys(e){S=e}export const storageSyncAdapter={version:3,getSnapshot:()=>D(u.getEvents().filter(e=>{const t=e.data?.key;return!(typeof t==="string"&&y(t))})),subscribe:e=>u.subscribeToEvents(e),actions:{clearEvents:()=>{u.clearEvents()},getRequiredKeys:()=>S,getEventDetail:e=>{const{id:t}=e??{};if(!t)return{found:false,reason:"missing id"};const r=u.getEvents().find(s=>s.id===t);if(!r)return{found:false,reason:"unknown id"};const n=d(r,k);return{found:true,id:t,event:n}},clearAppStorage:()=>_(),"timeTravel.undo":async e=>{const t=e?.id;if(!t)throw new Error("timeTravel.undo requires an event `id`");const r=u.getEvents().find(s=>s.id===t);if(!r)throw new Error(`No storage event with id "${t}"`);if(r.storageType==="mmkv"){throw new Error("Time travel supports AsyncStorage events only")}const n=r;if(!N(n)){throw new Error(`Event "${t}" (${n.action}) has no previous value captured, so it cannot be undone`)}await q(n);return{undone:true,action:n.action,key:n.data?.key}},"timeTravel.jump":async e=>{const{id:t,scope:r="key"}=e??{};if(!t)throw new Error("timeTravel.jump requires an event `id`");const n=u.getEvents().filter(a=>a.storageType!=="mmkv").slice().reverse();const s=n.find(a=>a.id===t);if(!s)throw new Error(`No AsyncStorage event with id "${t}"`);const o=r==="all"?n:n.filter(a=>a.data?.key===s.data?.key);const i=o.findIndex(a=>a.id===t);if(i===-1)throw new Error(`Event "${t}" is not in the timeline`);await K(o,i);return{jumped:true,scope:r,replayed:i+1,of:o.length,key:s.data?.key}},"async.getAllKeys":async()=>(await l.getAllKeys()).filter(e=>!y(e)),"async.multiGet":async e=>(await b(e.keys)).filter(([t])=>!y(t)),"async.getItem":e=>{const{key:t}=e;return y(t)?Promise.resolve(null):l.getItem(t)},"async.setItem":e=>{const{key:t,value:r}=e;return l.setItem(t,r)},"async.removeItem":e=>l.removeItem(e.key),"async.multiRemove":e=>I(e.keys),"async.multiSet":e=>V(e.pairs),"async.clear":()=>l.clear(),"mmkv.snapshot":()=>f.getAll().map(({id:e,instance:t,encrypted:r,readOnly:n})=>{let s=[];try{s=t.getAllKeys().filter(o=>!y(o)).map(o=>{const{value:i,type:a}=g(t,o);return{key:o,value:m(i),valueType:a}})}catch{}return{id:e,encrypted:r,readOnly:n,entries:s}}),"mmkv.get":e=>{const{instanceId:t,key:r}=e??{};if(!t||!r){return{found:false,reason:"missing instanceId/key"}}const n=f.get(t);if(!n){return{found:false,reason:"unknown instance"}}const{value:s,type:o}=g(n.instance,r);return{found:true,instanceId:t,key:r,value:k(s),valueType:o}},"mmkv.set":e=>{const{instanceId:t,key:r,value:n}=e;A(t).set(r,n)},"mmkv.remove":e=>{const{instanceId:t,key:r}=e;const n=A(t);if(n.remove)n.remove(r);else n.delete?.(r)},"secure.keys":()=>c.getAll().map(({key:e,options:t,description:r})=>({key:e,description:r,keychainService:t.keychainService,requireAuthentication:t.requireAuthentication??false})),"secure.snapshot":async()=>{const e=c.getModule();const t=c.getAll();const r=[];for(const{key:n,options:s,description:o}of t){let i=null;if(e&&!s.requireAuthentication){try{i=await e.getItemAsync(n,s)}catch{}}r.push({key:n,description:o,keychainService:s.keychainService,requireAuthentication:s.requireAuthentication??false,value:i==null?i:m(i)})}return r},"secure.get":e=>{const{key:t}=e;const r=c.getAll().find(s=>s.key===t);const n=c.getModule();if(!r||!n||r.options.requireAuthentication){return Promise.resolve(null)}return n.getItemAsync(t,r.options)},"secure.set":e=>{const{key:t,value:r}=e;return c.setValue(t,r)},"secure.delete":e=>c.deleteValue(e.key)}};
|