@buoy-gg/storage 7.0.41 → 7.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 +6 -10
- 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,380 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Time Machine snapshot provider for device storage (AsyncStorage + MMKV +
|
|
5
|
-
* SecureStore).
|
|
6
|
-
*
|
|
7
|
-
* Registered into @buoy-gg/shared-ui's stateSnapshotRegistry at module init;
|
|
8
|
-
* consumed by @buoy-gg/time-machine.
|
|
9
|
-
*
|
|
10
|
-
* Buoy's own keys (isDevToolsStorageKey — @react_buoy*, @buoy*, buoy-*,
|
|
11
|
-
* legacy patterns) are excluded on BOTH capture and restore, so a snapshot
|
|
12
|
-
* can never clobber dev-tool settings. Restore is a diff: app keys missing
|
|
13
|
-
* from the snapshot are deleted, snapshot entries are written back.
|
|
14
|
-
*
|
|
15
|
-
* Known-lossy by design (each surfaces a warning/skip):
|
|
16
|
-
* - MMKV ArrayBuffer values are never transported.
|
|
17
|
-
* - SecureStore biometric keys are never read or written (auth prompt).
|
|
18
|
-
* - SecureStore keys outside the registered descriptor list are invisible.
|
|
19
|
-
*/
|
|
20
|
-
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
21
|
-
import { classifyPreviewItem, createRestoreScope, emptyRestoreResult, failedRestore, isDevToolsStorageKey, registerStateSnapshotProvider, unionKeys, wontApply } from "@buoy-gg/shared-ui";
|
|
22
|
-
import { readMany, writeMany, removeMany } from "./asyncStorageCompat";
|
|
23
|
-
import { clearAllAppStorage } from "./clearAllStorage";
|
|
24
|
-
import { mmkvInstanceRegistry } from "./MMKVInstanceRegistry";
|
|
25
|
-
import { detectMMKVType } from "./mmkvTypeDetection";
|
|
26
|
-
import { secureStoreRegistry } from "./SecureStoreRegistry";
|
|
27
|
-
function deleteMMKVKey(instance, key) {
|
|
28
|
-
// v4 renamed delete() to remove() — support both
|
|
29
|
-
if (instance.remove) instance.remove(key);else instance.delete?.(key);
|
|
30
|
-
}
|
|
31
|
-
function status() {
|
|
32
|
-
return {
|
|
33
|
-
canCapture: true,
|
|
34
|
-
canRestore: true
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/** Shared by capture() and the live side of previewItems(). */
|
|
39
|
-
async function captureStorageData() {
|
|
40
|
-
const warnings = [];
|
|
41
|
-
const appKeys = (await AsyncStorage.getAllKeys()).filter(k => !isDevToolsStorageKey(k));
|
|
42
|
-
const asyncPairs = (await readMany(appKeys)).filter(pair => pair[1] !== null);
|
|
43
|
-
const mmkv = {};
|
|
44
|
-
for (const {
|
|
45
|
-
id,
|
|
46
|
-
instance
|
|
47
|
-
} of mmkvInstanceRegistry.getAll()) {
|
|
48
|
-
try {
|
|
49
|
-
mmkv[id] = instance.getAllKeys().filter(key => !isDevToolsStorageKey(key)).map(key => {
|
|
50
|
-
const {
|
|
51
|
-
value,
|
|
52
|
-
type: valueType
|
|
53
|
-
} = detectMMKVType(instance, key);
|
|
54
|
-
if (valueType === "buffer") {
|
|
55
|
-
warnings.push(`mmkv "${id}"/"${key}": ArrayBuffer value not capturable`);
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
key,
|
|
59
|
-
value,
|
|
60
|
-
valueType
|
|
61
|
-
};
|
|
62
|
-
});
|
|
63
|
-
} catch {
|
|
64
|
-
warnings.push(`mmkv "${id}": unreadable, captured without entries`);
|
|
65
|
-
mmkv[id] = [];
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
const secure = {};
|
|
69
|
-
const secureModule = secureStoreRegistry.getModule();
|
|
70
|
-
for (const {
|
|
71
|
-
key,
|
|
72
|
-
options
|
|
73
|
-
} of secureStoreRegistry.getAll()) {
|
|
74
|
-
if (options.requireAuthentication) {
|
|
75
|
-
warnings.push(`secure "${key}": biometric-protected, not capturable`);
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
let value = null;
|
|
79
|
-
if (secureModule) {
|
|
80
|
-
try {
|
|
81
|
-
value = await secureModule.getItemAsync(key, options);
|
|
82
|
-
} catch {
|
|
83
|
-
warnings.push(`secure "${key}": unreadable, captured as unset`);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
secure[key] = value;
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
data: {
|
|
90
|
-
async: asyncPairs,
|
|
91
|
-
mmkv,
|
|
92
|
-
secure
|
|
93
|
-
},
|
|
94
|
-
warnings
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
async function capture() {
|
|
98
|
-
const {
|
|
99
|
-
data,
|
|
100
|
-
warnings
|
|
101
|
-
} = await captureStorageData();
|
|
102
|
-
return {
|
|
103
|
-
data,
|
|
104
|
-
warnings
|
|
105
|
-
};
|
|
106
|
-
}
|
|
107
|
-
async function restore(data, options) {
|
|
108
|
-
const snapshot = data;
|
|
109
|
-
const scope = createRestoreScope(options);
|
|
110
|
-
/** True when this item may be touched (scope + exclusions agree). */
|
|
111
|
-
const touch = scope.touch;
|
|
112
|
-
const result = emptyRestoreResult();
|
|
113
|
-
if (!snapshot) {
|
|
114
|
-
return failedRestore("empty storage snapshot");
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ── AsyncStorage: delete app keys missing from the snapshot, write the rest ──
|
|
118
|
-
try {
|
|
119
|
-
const snapPairs = (snapshot.async ?? []).filter(([k]) => !isDevToolsStorageKey(k) && touch(`async:${k}`));
|
|
120
|
-
const snapKeys = new Set(snapPairs.map(([k]) => k));
|
|
121
|
-
const liveKeys = (await AsyncStorage.getAllKeys()).filter(k => !isDevToolsStorageKey(k));
|
|
122
|
-
const toRemove = liveKeys.filter(k => !snapKeys.has(k) && touch(`async:${k}`));
|
|
123
|
-
scope.countExcluded((snapshot.async ?? []).length - snapPairs.length);
|
|
124
|
-
if (toRemove.length > 0) await removeMany(toRemove);
|
|
125
|
-
if (snapPairs.length > 0) await writeMany(snapPairs);
|
|
126
|
-
result.applied += snapPairs.length + toRemove.length;
|
|
127
|
-
} catch (e) {
|
|
128
|
-
result.ok = false;
|
|
129
|
-
result.warnings.push(`asyncstorage restore failed: ${String(e)}`);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
// ── MMKV: per registered writable instance, diff against the snapshot ──
|
|
133
|
-
for (const [id, entries] of Object.entries(snapshot.mmkv ?? {})) {
|
|
134
|
-
const registered = mmkvInstanceRegistry.get(id);
|
|
135
|
-
if (!registered) {
|
|
136
|
-
result.skipped.push({
|
|
137
|
-
id: `mmkv:${id}`,
|
|
138
|
-
reason: "instance not registered"
|
|
139
|
-
});
|
|
140
|
-
continue;
|
|
141
|
-
}
|
|
142
|
-
if (registered.instance.isReadOnly) {
|
|
143
|
-
result.skipped.push({
|
|
144
|
-
id: `mmkv:${id}`,
|
|
145
|
-
reason: "instance registered read-only"
|
|
146
|
-
});
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
const {
|
|
150
|
-
instance
|
|
151
|
-
} = registered;
|
|
152
|
-
try {
|
|
153
|
-
const snapKeys = new Set(entries.map(e => e.key));
|
|
154
|
-
const liveKeys = instance.getAllKeys().filter(key => !isDevToolsStorageKey(key));
|
|
155
|
-
for (const key of liveKeys) {
|
|
156
|
-
if (!scope.allows(`mmkv:${id}/${key}`)) continue;
|
|
157
|
-
if (!snapKeys.has(key)) {
|
|
158
|
-
deleteMMKVKey(instance, key);
|
|
159
|
-
result.applied += 1;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
for (const entry of entries) {
|
|
163
|
-
if (isDevToolsStorageKey(entry.key)) continue;
|
|
164
|
-
if (!touch(`mmkv:${id}/${entry.key}`)) continue;
|
|
165
|
-
if (entry.valueType === "buffer") {
|
|
166
|
-
result.skipped.push({
|
|
167
|
-
id: `mmkv:${id}/${entry.key}`,
|
|
168
|
-
reason: "ArrayBuffer values cannot be restored"
|
|
169
|
-
});
|
|
170
|
-
continue;
|
|
171
|
-
}
|
|
172
|
-
instance.set(entry.key, entry.value);
|
|
173
|
-
result.applied += 1;
|
|
174
|
-
}
|
|
175
|
-
} catch (e) {
|
|
176
|
-
result.ok = false;
|
|
177
|
-
result.warnings.push(`mmkv "${id}" restore failed: ${String(e)}`);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
// ── SecureStore: diff over the registered, non-biometric descriptor list ──
|
|
182
|
-
const secureSnap = snapshot.secure ?? {};
|
|
183
|
-
for (const {
|
|
184
|
-
key,
|
|
185
|
-
options
|
|
186
|
-
} of secureStoreRegistry.getAll()) {
|
|
187
|
-
if (!scope.allows(`secure:${key}`)) continue;
|
|
188
|
-
if (options.requireAuthentication) {
|
|
189
|
-
if (key in secureSnap) {
|
|
190
|
-
result.skipped.push({
|
|
191
|
-
id: `secure:${key}`,
|
|
192
|
-
reason: "biometric-protected keys are never written"
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
continue;
|
|
196
|
-
}
|
|
197
|
-
try {
|
|
198
|
-
if (key in secureSnap) {
|
|
199
|
-
const value = secureSnap[key];
|
|
200
|
-
if (value === null) await secureStoreRegistry.deleteValue(key);else await secureStoreRegistry.setValue(key, value);
|
|
201
|
-
} else {
|
|
202
|
-
// Registered key with no snapshot entry — snapshot predates it; unset.
|
|
203
|
-
await secureStoreRegistry.deleteValue(key);
|
|
204
|
-
}
|
|
205
|
-
result.applied += 1;
|
|
206
|
-
} catch (e) {
|
|
207
|
-
result.ok = false;
|
|
208
|
-
result.warnings.push(`secure "${key}" restore failed: ${String(e)}`);
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
for (const key of Object.keys(secureSnap)) {
|
|
212
|
-
if (!touch(`secure:${key}`)) continue;
|
|
213
|
-
if (!secureStoreRegistry.getAll().some(e => e.key === key)) {
|
|
214
|
-
result.skipped.push({
|
|
215
|
-
id: `secure:${key}`,
|
|
216
|
-
reason: "key no longer registered with registerSecureStoreKeys"
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
const excludedWarning = scope.excludedWarning("item(s)");
|
|
221
|
-
if (excludedWarning) result.warnings.push(excludedWarning);
|
|
222
|
-
return result;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/** Wipe to fresh-install state (Buoy keys preserved). Used by baseline restore. */
|
|
226
|
-
async function clear() {
|
|
227
|
-
const result = emptyRestoreResult();
|
|
228
|
-
try {
|
|
229
|
-
await clearAllAppStorage();
|
|
230
|
-
result.applied += 1;
|
|
231
|
-
} catch (e) {
|
|
232
|
-
result.ok = false;
|
|
233
|
-
result.warnings.push(`asyncstorage clear failed: ${String(e)}`);
|
|
234
|
-
}
|
|
235
|
-
for (const {
|
|
236
|
-
id,
|
|
237
|
-
instance
|
|
238
|
-
} of mmkvInstanceRegistry.getAll()) {
|
|
239
|
-
if (instance.isReadOnly) {
|
|
240
|
-
result.skipped.push({
|
|
241
|
-
id: `mmkv:${id}`,
|
|
242
|
-
reason: "instance registered read-only"
|
|
243
|
-
});
|
|
244
|
-
continue;
|
|
245
|
-
}
|
|
246
|
-
try {
|
|
247
|
-
for (const key of instance.getAllKeys().filter(k => !isDevToolsStorageKey(k))) {
|
|
248
|
-
deleteMMKVKey(instance, key);
|
|
249
|
-
result.applied += 1;
|
|
250
|
-
}
|
|
251
|
-
} catch (e) {
|
|
252
|
-
result.ok = false;
|
|
253
|
-
result.warnings.push(`mmkv "${id}" clear failed: ${String(e)}`);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
for (const {
|
|
257
|
-
key,
|
|
258
|
-
options
|
|
259
|
-
} of secureStoreRegistry.getAll()) {
|
|
260
|
-
if (options.requireAuthentication) {
|
|
261
|
-
result.skipped.push({
|
|
262
|
-
id: `secure:${key}`,
|
|
263
|
-
reason: "biometric-protected keys are never written"
|
|
264
|
-
});
|
|
265
|
-
continue;
|
|
266
|
-
}
|
|
267
|
-
try {
|
|
268
|
-
await secureStoreRegistry.deleteValue(key);
|
|
269
|
-
result.applied += 1;
|
|
270
|
-
} catch (e) {
|
|
271
|
-
result.ok = false;
|
|
272
|
-
result.warnings.push(`secure "${key}" clear failed: ${String(e)}`);
|
|
273
|
-
}
|
|
274
|
-
}
|
|
275
|
-
return result;
|
|
276
|
-
}
|
|
277
|
-
const ITEM_RENDER_CHAR_LIMIT = 256 * 1024;
|
|
278
|
-
|
|
279
|
-
/**
|
|
280
|
-
* Storage values are strings (or MMKV primitives): identity equality and a
|
|
281
|
-
* character-length size gate are the right tests, not a deep walk.
|
|
282
|
-
*/
|
|
283
|
-
function classifyValue(key, label, oldValue, newValue, inOld, inNew) {
|
|
284
|
-
return classifyPreviewItem({
|
|
285
|
-
key,
|
|
286
|
-
label,
|
|
287
|
-
oldValue,
|
|
288
|
-
newValue,
|
|
289
|
-
inOld,
|
|
290
|
-
inNew
|
|
291
|
-
}, {
|
|
292
|
-
equal: Object.is,
|
|
293
|
-
tooLarge: value => typeof value === "string" && value.length > ITEM_RENDER_CHAR_LIMIT,
|
|
294
|
-
tooLargeReason: "value too large to render a diff — restore still applies it"
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
/** Per-key restore preview across all three backends. */
|
|
299
|
-
async function previewItems(target, base) {
|
|
300
|
-
const targetData = target ?? {
|
|
301
|
-
async: [],
|
|
302
|
-
mmkv: {},
|
|
303
|
-
secure: {}
|
|
304
|
-
};
|
|
305
|
-
const liveMode = base === undefined;
|
|
306
|
-
const baseData = liveMode ? (await captureStorageData()).data : base ?? {
|
|
307
|
-
async: [],
|
|
308
|
-
mmkv: {},
|
|
309
|
-
secure: {}
|
|
310
|
-
};
|
|
311
|
-
const items = [];
|
|
312
|
-
const notes = [];
|
|
313
|
-
|
|
314
|
-
// ── AsyncStorage ──
|
|
315
|
-
const oldAsync = new Map(baseData.async ?? []);
|
|
316
|
-
const newAsync = new Map(targetData.async ?? []);
|
|
317
|
-
for (const key of unionKeys(oldAsync, newAsync)) {
|
|
318
|
-
if (isDevToolsStorageKey(key)) continue;
|
|
319
|
-
items.push(classifyValue(`async:${key}`, key, oldAsync.get(key), newAsync.get(key), oldAsync.has(key), newAsync.has(key)));
|
|
320
|
-
}
|
|
321
|
-
|
|
322
|
-
// ── MMKV ──
|
|
323
|
-
for (const id of unionKeys(baseData.mmkv, targetData.mmkv)) {
|
|
324
|
-
const registered = liveMode ? mmkvInstanceRegistry.get(id) : null;
|
|
325
|
-
const instanceUnavailable = liveMode && !registered;
|
|
326
|
-
const readOnly = liveMode && registered?.instance.isReadOnly === true;
|
|
327
|
-
const oldEntries = new Map((baseData.mmkv?.[id] ?? []).map(e => [e.key, e]));
|
|
328
|
-
const newEntries = new Map((targetData.mmkv?.[id] ?? []).map(e => [e.key, e]));
|
|
329
|
-
for (const key of unionKeys(oldEntries, newEntries)) {
|
|
330
|
-
if (isDevToolsStorageKey(key)) continue;
|
|
331
|
-
const itemKey = `mmkv:${id}/${key}`;
|
|
332
|
-
const label = `${id} · ${key}`;
|
|
333
|
-
const oldE = oldEntries.get(key);
|
|
334
|
-
const newE = newEntries.get(key);
|
|
335
|
-
let item = classifyValue(itemKey, label, oldE?.value, newE?.value, oldEntries.has(key), newEntries.has(key));
|
|
336
|
-
if (instanceUnavailable) {
|
|
337
|
-
item = wontApply(item, "MMKV instance not registered");
|
|
338
|
-
} else if (readOnly) {
|
|
339
|
-
item = wontApply(item, "MMKV instance registered read-only");
|
|
340
|
-
} else if (newE?.valueType === "buffer" || oldE?.valueType === "buffer") {
|
|
341
|
-
item = wontApply(item, "ArrayBuffer values cannot be restored");
|
|
342
|
-
}
|
|
343
|
-
items.push(item);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// ── SecureStore ──
|
|
348
|
-
const oldSecure = baseData.secure ?? {};
|
|
349
|
-
const newSecure = targetData.secure ?? {};
|
|
350
|
-
const registeredSecure = liveMode ? new Map(secureStoreRegistry.getAll().map(e => [e.key, e])) : null;
|
|
351
|
-
for (const key of unionKeys(oldSecure, newSecure)) {
|
|
352
|
-
let item = classifyValue(`secure:${key}`, key, oldSecure[key], newSecure[key], key in oldSecure, key in newSecure);
|
|
353
|
-
if (liveMode) {
|
|
354
|
-
const entry = registeredSecure?.get(key);
|
|
355
|
-
if (!entry) {
|
|
356
|
-
item = wontApply(item, "key no longer registered with registerSecureStoreKeys");
|
|
357
|
-
} else if (entry.options.requireAuthentication) {
|
|
358
|
-
item = wontApply(item, "biometric-protected keys are never written");
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
items.push(item);
|
|
362
|
-
}
|
|
363
|
-
// No blanket "N biometric-protected keys" note: a biometric key a restore
|
|
364
|
-
// would actually touch already gets its own won't-apply row carrying that
|
|
365
|
-
// exact reason, so the note only ever restated it for keys nothing was
|
|
366
|
-
// going to do anything with.
|
|
367
|
-
return {
|
|
368
|
-
items,
|
|
369
|
-
notes
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
registerStateSnapshotProvider({
|
|
373
|
-
id: "storage",
|
|
374
|
-
label: "Storage",
|
|
375
|
-
status,
|
|
376
|
-
capture,
|
|
377
|
-
restore,
|
|
378
|
-
clear,
|
|
379
|
-
previewItems
|
|
380
|
-
});
|
|
1
|
+
"use strict";import R from"@react-native-async-storage/async-storage";import{classifyPreviewItem as D,createRestoreScope as P,emptyRestoreResult as V,failedRestore as j,isDevToolsStorageKey as h,registerStateSnapshotProvider as x,unionKeys as w,wontApply as v}from"@buoy-gg/shared-ui";import{readMany as B,writeMany as L,removeMany as _}from"./asyncStorageCompat";import{clearAllAppStorage as C}from"./clearAllStorage";import{mmkvInstanceRegistry as $}from"./MMKVInstanceRegistry";import{detectMMKVType as W}from"./mmkvTypeDetection";import{secureStoreRegistry as m}from"./SecureStoreRegistry";function E(n,a){if(n.remove)n.remove(a);else n.delete?.(a)}function H(){return{canCapture:true,canRestore:true}}async function T(){const n=[];const a=(await R.getAllKeys()).filter(o=>!h(o));const i=(await B(a)).filter(o=>o[1]!==null);const r={};for(const{id:o,instance:y}of $.getAll()){try{r[o]=y.getAllKeys().filter(e=>!h(e)).map(e=>{const{value:f,type:l}=W(y,e);if(l==="buffer"){n.push(`mmkv "${o}"/"${e}": ArrayBuffer value not capturable`)}return{key:e,value:f,valueType:l}})}catch{n.push(`mmkv "${o}": unreadable, captured without entries`);r[o]=[]}}const u={};const s=m.getModule();for(const{key:o,options:y}of m.getAll()){if(y.requireAuthentication){n.push(`secure "${o}": biometric-protected, not capturable`);continue}let e=null;if(s){try{e=await s.getItemAsync(o,y)}catch{n.push(`secure "${o}": unreadable, captured as unset`)}}u[o]=e}return{data:{async:i,mmkv:r,secure:u},warnings:n}}async function N(){const{data:n,warnings:a}=await T();return{data:n,warnings:a}}async function U(n,a){const i=n;const r=P(a);const u=r.touch;const s=V();if(!i){return j("empty storage snapshot")}try{const e=(i.async??[]).filter(([t])=>!h(t)&&u(`async:${t}`));const f=new Set(e.map(([t])=>t));const l=(await R.getAllKeys()).filter(t=>!h(t));const g=l.filter(t=>!f.has(t)&&u(`async:${t}`));r.countExcluded((i.async??[]).length-e.length);if(g.length>0)await _(g);if(e.length>0)await L(e);s.applied+=e.length+g.length}catch(e){s.ok=false;s.warnings.push(`asyncstorage restore failed: ${String(e)}`)}for(const[e,f]of Object.entries(i.mmkv??{})){const l=$.get(e);if(!l){s.skipped.push({id:`mmkv:${e}`,reason:"instance not registered"});continue}if(l.instance.isReadOnly){s.skipped.push({id:`mmkv:${e}`,reason:"instance registered read-only"});continue}const{instance:g}=l;try{const t=new Set(f.map(c=>c.key));const d=g.getAllKeys().filter(c=>!h(c));for(const c of d){if(!r.allows(`mmkv:${e}/${c}`))continue;if(!t.has(c)){E(g,c);s.applied+=1}}for(const c of f){if(h(c.key))continue;if(!u(`mmkv:${e}/${c.key}`))continue;if(c.valueType==="buffer"){s.skipped.push({id:`mmkv:${e}/${c.key}`,reason:"ArrayBuffer values cannot be restored"});continue}g.set(c.key,c.value);s.applied+=1}}catch(t){s.ok=false;s.warnings.push(`mmkv "${e}" restore failed: ${String(t)}`)}}const o=i.secure??{};for(const{key:e,options:f}of m.getAll()){if(!r.allows(`secure:${e}`))continue;if(f.requireAuthentication){if(e in o){s.skipped.push({id:`secure:${e}`,reason:"biometric-protected keys are never written"})}continue}try{if(e in o){const l=o[e];if(l===null)await m.deleteValue(e);else await m.setValue(e,l)}else{await m.deleteValue(e)}s.applied+=1}catch(l){s.ok=false;s.warnings.push(`secure "${e}" restore failed: ${String(l)}`)}}for(const e of Object.keys(o)){if(!u(`secure:${e}`))continue;if(!m.getAll().some(f=>f.key===e)){s.skipped.push({id:`secure:${e}`,reason:"key no longer registered with registerSecureStoreKeys"})}}const y=r.excludedWarning("item(s)");if(y)s.warnings.push(y);return s}async function z(){const n=V();try{await C();n.applied+=1}catch(a){n.ok=false;n.warnings.push(`asyncstorage clear failed: ${String(a)}`)}for(const{id:a,instance:i}of $.getAll()){if(i.isReadOnly){n.skipped.push({id:`mmkv:${a}`,reason:"instance registered read-only"});continue}try{for(const r of i.getAllKeys().filter(u=>!h(u))){E(i,r);n.applied+=1}}catch(r){n.ok=false;n.warnings.push(`mmkv "${a}" clear failed: ${String(r)}`)}}for(const{key:a,options:i}of m.getAll()){if(i.requireAuthentication){n.skipped.push({id:`secure:${a}`,reason:"biometric-protected keys are never written"});continue}try{await m.deleteValue(a);n.applied+=1}catch(r){n.ok=false;n.warnings.push(`secure "${a}" clear failed: ${String(r)}`)}}return n}const F=256*1024;function M(n,a,i,r,u,s){return D({key:n,label:a,oldValue:i,newValue:r,inOld:u,inNew:s},{equal:Object.is,tooLarge:o=>typeof o==="string"&&o.length>F,tooLargeReason:"value too large to render a diff \u2014 restore still applies it"})}async function G(n,a){const i=n??{async:[],mmkv:{},secure:{}};const r=a===void 0;const u=r?(await T()).data:a??{async:[],mmkv:{},secure:{}};const s=[];const o=[];const y=new Map(u.async??[]);const e=new Map(i.async??[]);for(const t of w(y,e)){if(h(t))continue;s.push(M(`async:${t}`,t,y.get(t),e.get(t),y.has(t),e.has(t)))}for(const t of w(u.mmkv,i.mmkv)){const d=r?$.get(t):null;const c=r&&!d;const I=r&&d?.instance.isReadOnly===true;const A=new Map((u.mmkv?.[t]??[]).map(p=>[p.key,p]));const S=new Map((i.mmkv?.[t]??[]).map(p=>[p.key,p]));for(const p of w(A,S)){if(h(p))continue;const O=`mmkv:${t}/${p}`;const q=`${t} \xB7 ${p}`;const b=A.get(p);const K=S.get(p);let k=M(O,q,b?.value,K?.value,A.has(p),S.has(p));if(c){k=v(k,"MMKV instance not registered")}else if(I){k=v(k,"MMKV instance registered read-only")}else if(K?.valueType==="buffer"||b?.valueType==="buffer"){k=v(k,"ArrayBuffer values cannot be restored")}s.push(k)}}const f=u.secure??{};const l=i.secure??{};const g=r?new Map(m.getAll().map(t=>[t.key,t])):null;for(const t of w(f,l)){let d=M(`secure:${t}`,t,f[t],l[t],t in f,t in l);if(r){const c=g?.get(t);if(!c){d=v(d,"key no longer registered with registerSecureStoreKeys")}else if(c.options.requireAuthentication){d=v(d,"biometric-protected keys are never written")}}s.push(d)}return{items:s,notes:o}}x({id:"storage",label:"Storage",status:H,capture:N,restore:U,clear:z,previewItems:G});
|
|
@@ -1,42 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Translates storage action types to human-readable labels
|
|
5
|
-
*/
|
|
6
|
-
export function translateStorageAction(action) {
|
|
7
|
-
switch (action) {
|
|
8
|
-
// AsyncStorage actions
|
|
9
|
-
case "setItem":
|
|
10
|
-
return "SET";
|
|
11
|
-
case "removeItem":
|
|
12
|
-
return "REMOVE";
|
|
13
|
-
case "mergeItem":
|
|
14
|
-
return "MERGE";
|
|
15
|
-
case "clear":
|
|
16
|
-
return "CLEAR";
|
|
17
|
-
case "multiSet":
|
|
18
|
-
return "MULTI SET";
|
|
19
|
-
case "multiRemove":
|
|
20
|
-
return "MULTI REMOVE";
|
|
21
|
-
case "multiMerge":
|
|
22
|
-
return "MULTI MERGE";
|
|
23
|
-
|
|
24
|
-
// MMKV actions - simplified to match AsyncStorage
|
|
25
|
-
case "set.string":
|
|
26
|
-
case "set.number":
|
|
27
|
-
case "set.boolean":
|
|
28
|
-
case "set.buffer":
|
|
29
|
-
return "SET";
|
|
30
|
-
case "delete":
|
|
31
|
-
return "REMOVE";
|
|
32
|
-
case "clearAll":
|
|
33
|
-
return "CLEAR";
|
|
34
|
-
case "get.string":
|
|
35
|
-
case "get.number":
|
|
36
|
-
case "get.boolean":
|
|
37
|
-
case "get.buffer":
|
|
38
|
-
return "GET";
|
|
39
|
-
default:
|
|
40
|
-
return "UNKNOWN ACTION";
|
|
41
|
-
}
|
|
42
|
-
}
|
|
1
|
+
"use strict";export function translateStorageAction(e){switch(e){case"setItem":return"SET";case"removeItem":return"REMOVE";case"mergeItem":return"MERGE";case"clear":return"CLEAR";case"multiSet":return"MULTI SET";case"multiRemove":return"MULTI REMOVE";case"multiMerge":return"MULTI MERGE";case"set.string":case"set.number":case"set.boolean":case"set.buffer":return"SET";case"delete":return"REMOVE";case"clearAll":return"CLEAR";case"get.string":case"get.number":case"get.boolean":case"get.buffer":return"GET";default:return"UNKNOWN ACTION"}}
|
|
@@ -1,44 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* A "the underlying storage changed, re-read it" signal for the storage
|
|
5
|
-
* browser.
|
|
6
|
-
*
|
|
7
|
-
* On device the browser refreshes itself from the AsyncStorage/MMKV listeners,
|
|
8
|
-
* but those never fire in remote-mirror mode (the desktop dashboard suppresses
|
|
9
|
-
* local capture and receives the device's events as snapshots instead). Without
|
|
10
|
-
* this seam the browse tab is a one-shot read at mount — values stay frozen
|
|
11
|
-
* until the panel remounts, which is exactly the "shows old data until I switch
|
|
12
|
-
* tools and come back" behaviour.
|
|
13
|
-
*
|
|
14
|
-
* The dashboard calls {@link requestStorageBrowserRefresh} whenever a fresh
|
|
15
|
-
* device snapshot lands; the browser re-reads all three backends (debounced).
|
|
16
|
-
* It is a no-op when nothing is listening.
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const listeners = new Set();
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Subscribe to external refresh requests. Returns an unsubscribe function.
|
|
23
|
-
* @internal — used by the storage browser.
|
|
24
|
-
*/
|
|
25
|
-
export function onStorageBrowserRefresh(listener) {
|
|
26
|
-
listeners.add(listener);
|
|
27
|
-
return () => {
|
|
28
|
-
listeners.delete(listener);
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Ask any mounted storage browser to re-read AsyncStorage, MMKV and
|
|
34
|
-
* SecureStore. Safe to call at any rate — the browser debounces.
|
|
35
|
-
*/
|
|
36
|
-
export function requestStorageBrowserRefresh() {
|
|
37
|
-
listeners.forEach(listener => {
|
|
38
|
-
try {
|
|
39
|
-
listener();
|
|
40
|
-
} catch {
|
|
41
|
-
// Listener errors are not ours
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
}
|
|
1
|
+
"use strict";const r=new Set;export function onStorageBrowserRefresh(e){r.add(e);return()=>{r.delete(e)}}export function requestStorageBrowserRefresh(){r.forEach(e=>{try{e()}catch{}})}
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
export const storageLabels = {
|
|
4
|
-
async: 'Async',
|
|
5
|
-
asyncFull: 'AsyncStorage',
|
|
6
|
-
mmkv: 'MMKV',
|
|
7
|
-
secure: 'Secure',
|
|
8
|
-
hasSecure: true
|
|
9
|
-
};
|
|
1
|
+
"use strict";export const storageLabels={async:"Async",asyncFull:"AsyncStorage",mmkv:"MMKV",secure:"Secure",hasSecure:true};
|
|
@@ -1,9 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
export const storageLabels = {
|
|
4
|
-
async: 'Local',
|
|
5
|
-
asyncFull: 'localStorage',
|
|
6
|
-
mmkv: 'Session',
|
|
7
|
-
secure: 'Secure',
|
|
8
|
-
hasSecure: false
|
|
9
|
-
};
|
|
1
|
+
"use strict";export const storageLabels={async:"Local",asyncFull:"localStorage",mmkv:"Session",secure:"Secure",hasSecure:false};
|
|
@@ -1,46 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* The five operations a storage event can be, and how to recognise one.
|
|
5
|
-
*
|
|
6
|
-
* AsyncStorage and MMKV each have their own action union, and neither maps
|
|
7
|
-
* cleanly onto what a reader wants to see — `multiRemove`, `removeItem` and
|
|
8
|
-
* `delete` are one idea wearing three names. These collapse both onto a single
|
|
9
|
-
* vocabulary so every surface labels, filters and colours events the same way.
|
|
10
|
-
*
|
|
11
|
-
* This is semantics, not presentation: it lives in `utils` rather than beside
|
|
12
|
-
* any one view, so a view can be deleted without taking the vocabulary with it.
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
import { macOSColors } from "@buoy-gg/shared-ui";
|
|
16
|
-
export const STORAGE_OPS = ["SET", "GET", "MERGE", "DELETE", "CLEAR"];
|
|
17
|
-
const OP_DOT = {
|
|
18
|
-
SET: macOSColors.semantic.info,
|
|
19
|
-
GET: macOSColors.text.muted,
|
|
20
|
-
MERGE: macOSColors.semantic.debug,
|
|
21
|
-
DELETE: macOSColors.semantic.error,
|
|
22
|
-
CLEAR: macOSColors.semantic.warning
|
|
23
|
-
};
|
|
24
|
-
export function storageOpDot(op) {
|
|
25
|
-
return OP_DOT[op];
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** Both backends' action unions, collapsed onto the five display operations. */
|
|
29
|
-
export function storageOpOf(event) {
|
|
30
|
-
const action = event.action;
|
|
31
|
-
if (action === "clear" || action === "clearAll") return "CLEAR";
|
|
32
|
-
if (action.startsWith("get.")) return "GET";
|
|
33
|
-
if (action === "removeItem" || action === "multiRemove" || action === "delete") return "DELETE";
|
|
34
|
-
if (action === "mergeItem" || action === "multiMerge") return "MERGE";
|
|
35
|
-
return "SET";
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
/**
|
|
39
|
-
* The store synthesises one event per existing key when it first subscribes, so
|
|
40
|
-
* the list isn't empty on open. Those are a SNAPSHOT, not a write: the key
|
|
41
|
-
* already held that value, so there is no "before" to diff against and showing
|
|
42
|
-
* one would invent a change that never happened.
|
|
43
|
-
*/
|
|
44
|
-
export function isInitialScan(event) {
|
|
45
|
-
return Boolean(event.data?.initialScan);
|
|
46
|
-
}
|
|
1
|
+
"use strict";import{macOSColors as r}from"@buoy-gg/shared-ui";export const STORAGE_OPS=["SET","GET","MERGE","DELETE","CLEAR"];const n={SET:r.semantic.info,GET:r.text.muted,MERGE:r.semantic.debug,DELETE:r.semantic.error,CLEAR:r.semantic.warning};export function storageOpDot(e){return n[e]}export function storageOpOf(e){const t=e.action;if(t==="clear"||t==="clearAll")return"CLEAR";if(t.startsWith("get."))return"GET";if(t==="removeItem"||t==="multiRemove"||t==="delete")return"DELETE";if(t==="mergeItem"||t==="multiMerge")return"MERGE";return"SET"}export function isInitialScan(e){return Boolean(e.data?.initialScan)}
|
|
@@ -1,30 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { gameUIColors } from "@buoy-gg/shared-ui";
|
|
4
|
-
/** Human readable label for a storage type id. */
|
|
5
|
-
export function getStorageTypeLabel(storageType) {
|
|
6
|
-
switch (storageType) {
|
|
7
|
-
case "mmkv":
|
|
8
|
-
return "MMKV";
|
|
9
|
-
case "async":
|
|
10
|
-
return "Async";
|
|
11
|
-
case "secure":
|
|
12
|
-
return "Secure";
|
|
13
|
-
default:
|
|
14
|
-
return storageType;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/** Preferred color token for rendering a given storage type. */
|
|
19
|
-
export function getStorageTypeHexColor(storageType) {
|
|
20
|
-
switch (storageType) {
|
|
21
|
-
case "mmkv":
|
|
22
|
-
return gameUIColors.info;
|
|
23
|
-
case "async":
|
|
24
|
-
return gameUIColors.warning;
|
|
25
|
-
case "secure":
|
|
26
|
-
return gameUIColors.success;
|
|
27
|
-
default:
|
|
28
|
-
return gameUIColors.muted;
|
|
29
|
-
}
|
|
30
|
-
}
|
|
1
|
+
"use strict";import{gameUIColors as r}from"@buoy-gg/shared-ui";export function getStorageTypeLabel(e){switch(e){case"mmkv":return"MMKV";case"async":return"Async";case"secure":return"Secure";default:return e}}export function getStorageTypeHexColor(e){switch(e){case"mmkv":return r.info;case"async":return r.warning;case"secure":return r.success;default:return r.muted}}
|