@buoy-gg/storage 7.0.41 → 7.0.43

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