@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.
Files changed (215) hide show
  1. package/README.md +11 -86
  2. package/lib/commonjs/index.js +1 -346
  3. package/lib/commonjs/preset.js +1 -80
  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 -1258
  8. package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -257
  9. package/lib/commonjs/storage/components/MMKVInstanceSelector.js +1 -418
  10. package/lib/commonjs/storage/components/SelectionActionBar.js +1 -207
  11. package/lib/commonjs/storage/components/StorageActionButtons.js +1 -241
  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 -117
  15. package/lib/commonjs/storage/components/StorageEventDetailContent.js +1 -494
  16. package/lib/commonjs/storage/components/StorageEventFilterView.js +1 -159
  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 -344
  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 -143
  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 -159
  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 -478
  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 -0
  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 -0
  43. package/lib/commonjs/storage/utils/browserStorageLifecycle.web.js +1 -0
  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 -0
  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 -0
  56. package/lib/commonjs/storage/utils/storageLabels.web.js +1 -0
  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 -112
  62. package/lib/module/preset.js +1 -76
  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 -1256
  67. package/lib/module/storage/components/MMKVInstanceInfoPanel.js +1 -253
  68. package/lib/module/storage/components/MMKVInstanceSelector.js +1 -414
  69. package/lib/module/storage/components/SelectionActionBar.js +1 -204
  70. package/lib/module/storage/components/StorageActionButtons.js +1 -237
  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 -112
  74. package/lib/module/storage/components/StorageEventDetailContent.js +1 -490
  75. package/lib/module/storage/components/StorageEventFilterView.js +1 -155
  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 -341
  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 -138
  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 -156
  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 -474
  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 -0
  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 -0
  102. package/lib/module/storage/utils/browserStorageLifecycle.web.js +1 -0
  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 -0
  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 -0
  115. package/lib/module/storage/utils/storageLabels.web.js +1 -0
  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/typescript/index.d.ts +1 -0
  121. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts +0 -8
  122. package/lib/typescript/storage/components/StorageEventCard.d.ts +0 -7
  123. package/lib/typescript/storage/components/StorageKeyRow.d.ts +2 -6
  124. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts +0 -15
  125. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts +2 -2
  126. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts +7 -13
  127. package/lib/typescript/storage/utils/AsyncStorageListener.web.d.ts +24 -0
  128. package/lib/typescript/storage/utils/browserStorageLifecycle.d.ts +3 -0
  129. package/lib/typescript/storage/utils/browserStorageLifecycle.web.d.ts +2 -0
  130. package/lib/typescript/storage/utils/mmkvAvailability.web.d.ts +4 -0
  131. package/lib/typescript/storage/utils/storageLabels.d.ts +8 -0
  132. package/lib/typescript/storage/utils/storageLabels.web.d.ts +8 -0
  133. package/lib/web/index.mjs +4 -0
  134. package/package.json +40 -14
  135. package/lib/commonjs/storage/components/DiffViewer/DiffOptionsPanel.js +0 -356
  136. package/lib/commonjs/storage/components/DiffViewer/components/DiffSummary.js +0 -122
  137. package/lib/commonjs/storage/components/StorageKeyEditorScreen.js +0 -414
  138. package/lib/commonjs/storage/components/StorageScalarKeyEditor.js +0 -61
  139. package/lib/commonjs/storage/components/StorageValueEditModal.js +0 -24
  140. package/lib/commonjs/storage/hooks/useKeyEditor.js +0 -31
  141. package/lib/commonjs/storage/hooks/useTreeDraft.js +0 -25
  142. package/lib/module/storage/components/DiffViewer/DiffOptionsPanel.js +0 -352
  143. package/lib/module/storage/components/DiffViewer/components/DiffSummary.js +0 -118
  144. package/lib/module/storage/components/StorageKeyEditorScreen.js +0 -410
  145. package/lib/module/storage/components/StorageScalarKeyEditor.js +0 -57
  146. package/lib/module/storage/components/StorageValueEditModal.js +0 -20
  147. package/lib/module/storage/hooks/useKeyEditor.js +0 -27
  148. package/lib/module/storage/hooks/useTreeDraft.js +0 -21
  149. package/lib/typescript/index.d.ts.map +0 -1
  150. package/lib/typescript/preset.d.ts.map +0 -1
  151. package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts +0 -18
  152. package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts.map +0 -1
  153. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +0 -1
  154. package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts +0 -12
  155. package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts.map +0 -1
  156. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +0 -1
  157. package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts.map +0 -1
  158. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +0 -1
  159. package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts.map +0 -1
  160. package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +0 -1
  161. package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +0 -1
  162. package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +0 -1
  163. package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +0 -1
  164. package/lib/typescript/storage/components/StorageEventActionButton.d.ts.map +0 -1
  165. package/lib/typescript/storage/components/StorageEventCard.d.ts.map +0 -1
  166. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +0 -1
  167. package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +0 -1
  168. package/lib/typescript/storage/components/StorageEventsSection.d.ts.map +0 -1
  169. package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +0 -1
  170. package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +0 -1
  171. package/lib/typescript/storage/components/StorageKeyDetailScreen.d.ts.map +0 -1
  172. package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts +0 -42
  173. package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts.map +0 -1
  174. package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +0 -1
  175. package/lib/typescript/storage/components/StorageKeySection.d.ts.map +0 -1
  176. package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +0 -1
  177. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +0 -1
  178. package/lib/typescript/storage/components/StorageSaveNotice.d.ts.map +0 -1
  179. package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts +0 -24
  180. package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts.map +0 -1
  181. package/lib/typescript/storage/components/StorageSection.d.ts.map +0 -1
  182. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts.map +0 -1
  183. package/lib/typescript/storage/components/StorageValueEditModal.d.ts +0 -14
  184. package/lib/typescript/storage/components/StorageValueEditModal.d.ts.map +0 -1
  185. package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +0 -1
  186. package/lib/typescript/storage/hooks/useKeyEditor.d.ts +0 -27
  187. package/lib/typescript/storage/hooks/useKeyEditor.d.ts.map +0 -1
  188. package/lib/typescript/storage/hooks/useMMKVInstances.d.ts.map +0 -1
  189. package/lib/typescript/storage/hooks/useMMKVKeys.d.ts.map +0 -1
  190. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts.map +0 -1
  191. package/lib/typescript/storage/hooks/useStorageEvents.d.ts.map +0 -1
  192. package/lib/typescript/storage/hooks/useTreeDraft.d.ts +0 -16
  193. package/lib/typescript/storage/hooks/useTreeDraft.d.ts.map +0 -1
  194. package/lib/typescript/storage/stores/storageEventStore.d.ts.map +0 -1
  195. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts.map +0 -1
  196. package/lib/typescript/storage/types.d.ts.map +0 -1
  197. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +0 -1
  198. package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +0 -1
  199. package/lib/typescript/storage/utils/MMKVListener.d.ts.map +0 -1
  200. package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts.map +0 -1
  201. package/lib/typescript/storage/utils/asyncStorageCompat.d.ts.map +0 -1
  202. package/lib/typescript/storage/utils/clearAllStorage.d.ts.map +0 -1
  203. package/lib/typescript/storage/utils/deleteStorageKeys.d.ts.map +0 -1
  204. package/lib/typescript/storage/utils/lineDiff.d.ts.map +0 -1
  205. package/lib/typescript/storage/utils/mmkvAvailability.d.ts.map +0 -1
  206. package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts.map +0 -1
  207. package/lib/typescript/storage/utils/requiredStorageKeyScope.d.ts.map +0 -1
  208. package/lib/typescript/storage/utils/setStorageValue.d.ts.map +0 -1
  209. package/lib/typescript/storage/utils/snapshotProvider.d.ts.map +0 -1
  210. package/lib/typescript/storage/utils/storageActionHelpers.d.ts.map +0 -1
  211. package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts.map +0 -1
  212. package/lib/typescript/storage/utils/storageOps.d.ts.map +0 -1
  213. package/lib/typescript/storage/utils/storageQueryUtils.d.ts.map +0 -1
  214. package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts.map +0 -1
  215. package/lib/typescript/storage/utils/valueType.d.ts.map +0 -1
@@ -0,0 +1 @@
1
+ "use strict";export const storageLabels={async:"Async",asyncFull:"AsyncStorage",mmkv:"MMKV",secure:"Secure",hasSecure:true};
@@ -0,0 +1 @@
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}}
@@ -1,281 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Storage Time-Travel Utilities
5
- *
6
- * Provides jump and undo functionality for AsyncStorage operations.
7
- */
8
-
9
- import { isDevToolsStorageKey } from "@buoy-gg/shared-ui";
10
- import AsyncStorage from "@react-native-async-storage/async-storage";
11
- import { writeMany, removeMany } from "./asyncStorageCompat";
12
- function isOmittedStorageValue(value) {
13
- return !!value && typeof value === "object" && value.__buoyValueOnDevice === true;
14
- }
15
-
16
- /**
17
- * Undo a single storage operation
18
- *
19
- * Restores the previous value(s) before the operation occurred.
20
- *
21
- * The restore is deliberately NOT capture-paused. Pausing it meant the write
22
- * landed but emitted no event, so the modal's event list and current-value
23
- * panel never changed — UNDO looked like a dead button even though it had
24
- * worked. Letting the restore emit normally makes it visible and keeps the
25
- * history honest about what the storage actually did. There is no feedback
26
- * loop: a write emits an event, and an event never triggers a write.
27
- *
28
- * @param event - The storage event to undo
29
- */
30
- export async function undoOperation(event) {
31
- const {
32
- action,
33
- data
34
- } = event;
35
- if (isOmittedStorageValue(data?.prevValue) || isOmittedStorageValue(data?.prevPairs)) {
36
- throw new Error("Cannot undo: previous value is still on the device — fetch getEventDetail first");
37
- }
38
- {
39
- switch (action) {
40
- case "setItem":
41
- case "mergeItem":
42
- if (data?.key) {
43
- if (data.prevValue === null || data.prevValue === undefined) {
44
- // Key didn't exist before, remove it
45
- await AsyncStorage.removeItem(data.key);
46
- } else {
47
- // Restore previous value
48
- await AsyncStorage.setItem(data.key, data.prevValue);
49
- }
50
- }
51
- break;
52
- case "removeItem":
53
- if (data?.key && data.prevValue !== null && data.prevValue !== undefined) {
54
- // Restore the removed value
55
- await AsyncStorage.setItem(data.key, data.prevValue);
56
- }
57
- break;
58
- case "multiSet":
59
- case "multiMerge":
60
- if (data?.prevPairs && data.prevPairs.length > 0) {
61
- // Restore all previous values
62
- for (const [key, value] of data.prevPairs) {
63
- if (value === null) {
64
- await AsyncStorage.removeItem(key);
65
- } else {
66
- await AsyncStorage.setItem(key, value);
67
- }
68
- }
69
- }
70
- break;
71
- case "multiRemove":
72
- if (data?.prevPairs && data.prevPairs.length > 0) {
73
- // Restore all removed values
74
- for (const [key, value] of data.prevPairs) {
75
- if (value !== null) {
76
- await AsyncStorage.setItem(key, value);
77
- }
78
- }
79
- }
80
- break;
81
- case "clear":
82
- if (data?.prevPairs && data.prevPairs.length > 0) {
83
- // Restore all cleared key-value pairs
84
- const pairsToRestore = data.prevPairs.filter(([, value]) => value !== null);
85
- if (pairsToRestore.length > 0) {
86
- await writeMany(pairsToRestore);
87
- }
88
- }
89
- break;
90
- default:
91
- throw new Error(`Cannot undo unknown action type: ${action}`);
92
- }
93
- }
94
- }
95
-
96
- /**
97
- * Jump to a specific point in storage history
98
- *
99
- * Reconstructs the state as of `targetEventIndex` by replaying `events` up to
100
- * that point, then reconciling ONLY the keys that timeline governs.
101
- *
102
- * This used to begin with `AsyncStorage.clear()`, which was badly out of
103
- * proportion: the modal's JUMP button passes one key's history, so clearing
104
- * wiped every unrelated app key — and Buoy's own `@react_buoy*` settings with
105
- * them — to restore a single value. Now a jump touches exactly the keys that
106
- * appear in the events it was given, and never Buoy's own keys. Like
107
- * [undoOperation], the writes emit normally so the change is visible.
108
- *
109
- * @param events - All events in chronological order (oldest first)
110
- * @param targetEventIndex - The index of the event to jump to (0-based)
111
- */
112
- export async function jumpToState(events, targetEventIndex) {
113
- if (targetEventIndex < 0 || targetEventIndex >= events.length) {
114
- throw new Error(`Invalid event index: ${targetEventIndex}`);
115
- }
116
- for (const event of events) {
117
- const data = event.data;
118
- if (isOmittedStorageValue(data?.value) || isOmittedStorageValue(data?.prevValue) || isOmittedStorageValue(data?.pairs) || isOmittedStorageValue(data?.prevPairs)) {
119
- throw new Error("Cannot jump: some event values are still on the device — fetch getEventDetail first");
120
- }
121
- }
122
-
123
- // Build up the state by applying each event up to and including the target.
124
- // We use the final values from each event, not the operations themselves.
125
- const stateMap = new Map();
126
- for (let i = 0; i <= targetEventIndex; i++) {
127
- applyEventToStateMap(events[i], stateMap);
128
- }
129
-
130
- // Every key the WHOLE timeline touches — including events after the target,
131
- // so a key created later is removed rather than left behind.
132
- const governedKeys = new Set();
133
- for (const event of events) {
134
- collectEventKeys(event, governedKeys);
135
- }
136
- const pairsToSet = [];
137
- const keysToRemove = [];
138
- for (const key of governedKeys) {
139
- // Buoy's own settings are never app state to travel through.
140
- if (isDevToolsStorageKey(key)) continue;
141
- const value = stateMap.get(key);
142
- if (value === undefined || value === null) {
143
- keysToRemove.push(key);
144
- } else {
145
- pairsToSet.push([key, value]);
146
- }
147
- }
148
- if (keysToRemove.length > 0) {
149
- await removeMany(keysToRemove);
150
- }
151
- if (pairsToSet.length > 0) {
152
- await writeMany(pairsToSet);
153
- }
154
- }
155
-
156
- /**
157
- * Collect every key an event refers to, across all action shapes — including
158
- * `prevPairs`, so keys a `clear` removed are still governed by the timeline.
159
- */
160
- function collectEventKeys(event, into) {
161
- const {
162
- data
163
- } = event;
164
- if (!data) return;
165
- if (data.key) into.add(data.key);
166
- if (data.keys) for (const key of data.keys) into.add(key);
167
- if (data.pairs) for (const [key] of data.pairs) into.add(key);
168
- if (data.prevPairs) for (const [key] of data.prevPairs) into.add(key);
169
- }
170
-
171
- /**
172
- * Helper to apply an event's effects to a state map
173
- */
174
- function applyEventToStateMap(event, stateMap) {
175
- const {
176
- action,
177
- data
178
- } = event;
179
- switch (action) {
180
- case "setItem":
181
- if (data?.key && data?.value !== undefined) {
182
- stateMap.set(data.key, data.value);
183
- }
184
- break;
185
- case "removeItem":
186
- if (data?.key) {
187
- stateMap.set(data.key, null);
188
- }
189
- break;
190
- case "mergeItem":
191
- if (data?.key && data?.value !== undefined) {
192
- const existing = stateMap.get(data.key);
193
- if (existing) {
194
- try {
195
- // Merge JSON objects
196
- const existingObj = JSON.parse(existing);
197
- const newObj = JSON.parse(data.value);
198
- const merged = {
199
- ...existingObj,
200
- ...newObj
201
- };
202
- stateMap.set(data.key, JSON.stringify(merged));
203
- } catch {
204
- // If not valid JSON, just overwrite
205
- stateMap.set(data.key, data.value);
206
- }
207
- } else {
208
- stateMap.set(data.key, data.value);
209
- }
210
- }
211
- break;
212
- case "multiSet":
213
- if (data?.pairs) {
214
- for (const [key, value] of data.pairs) {
215
- stateMap.set(key, value);
216
- }
217
- }
218
- break;
219
- case "multiRemove":
220
- if (data?.keys) {
221
- for (const key of data.keys) {
222
- stateMap.set(key, null);
223
- }
224
- }
225
- break;
226
- case "multiMerge":
227
- if (data?.pairs) {
228
- for (const [key, value] of data.pairs) {
229
- const existing = stateMap.get(key);
230
- if (existing) {
231
- try {
232
- const existingObj = JSON.parse(existing);
233
- const newObj = JSON.parse(value);
234
- const merged = {
235
- ...existingObj,
236
- ...newObj
237
- };
238
- stateMap.set(key, JSON.stringify(merged));
239
- } catch {
240
- stateMap.set(key, value);
241
- }
242
- } else {
243
- stateMap.set(key, value);
244
- }
245
- }
246
- }
247
- break;
248
- case "clear":
249
- // Clear the entire state map
250
- stateMap.clear();
251
- break;
252
- }
253
- }
254
-
255
- /**
256
- * Check if an operation can be undone
257
- *
258
- * Some operations may not have the previous value captured.
259
- */
260
- export function canUndo(event) {
261
- const {
262
- action,
263
- data
264
- } = event;
265
- switch (action) {
266
- case "setItem":
267
- case "mergeItem":
268
- case "removeItem":
269
- // Can undo if we have the key — but not while prevValue is still a
270
- // wire-form on-device marker (restoring that would write garbage).
271
- return !!data?.key && !isOmittedStorageValue(data.prevValue);
272
- case "multiSet":
273
- case "multiRemove":
274
- case "multiMerge":
275
- case "clear":
276
- // Can undo if we have previous pairs
277
- return !!data?.prevPairs && data.prevPairs.length > 0 && !isOmittedStorageValue(data.prevPairs);
278
- default:
279
- return false;
280
- }
281
- }
1
+ "use strict";import{isDevToolsStorageKey as m}from"@buoy-gg/shared-ui";import l from"@react-native-async-storage/async-storage";import{writeMany as f,removeMany as y}from"./asyncStorageCompat";function c(s){return!!s&&typeof s==="object"&&s.__buoyValueOnDevice===true}export async function undoOperation(s){const{action:r,data:e}=s;if(c(e?.prevValue)||c(e?.prevPairs)){throw new Error("Cannot undo: previous value is still on the device \u2014 fetch getEventDetail first")}{switch(r){case"setItem":case"mergeItem":if(e?.key){if(e.prevValue===null||e.prevValue===void 0){await l.removeItem(e.key)}else{await l.setItem(e.key,e.prevValue)}}break;case"removeItem":if(e?.key&&e.prevValue!==null&&e.prevValue!==void 0){await l.setItem(e.key,e.prevValue)}break;case"multiSet":case"multiMerge":if(e?.prevPairs&&e.prevPairs.length>0){for(const[t,a]of e.prevPairs){if(a===null){await l.removeItem(t)}else{await l.setItem(t,a)}}}break;case"multiRemove":if(e?.prevPairs&&e.prevPairs.length>0){for(const[t,a]of e.prevPairs){if(a!==null){await l.setItem(t,a)}}}break;case"clear":if(e?.prevPairs&&e.prevPairs.length>0){const t=e.prevPairs.filter(([,a])=>a!==null);if(t.length>0){await f(t)}}break;default:throw new Error(`Cannot undo unknown action type: ${r}`)}}}export async function jumpToState(s,r){if(r<0||r>=s.length){throw new Error(`Invalid event index: ${r}`)}for(const i of s){const o=i.data;if(c(o?.value)||c(o?.prevValue)||c(o?.pairs)||c(o?.prevPairs)){throw new Error("Cannot jump: some event values are still on the device \u2014 fetch getEventDetail first")}}const e=new Map;for(let i=0;i<=r;i++){k(s[i],e)}const t=new Set;for(const i of s){p(i,t)}const a=[];const n=[];for(const i of t){if(m(i))continue;const o=e.get(i);if(o===void 0||o===null){n.push(i)}else{a.push([i,o])}}if(n.length>0){await y(n)}if(a.length>0){await f(a)}}function p(s,r){const{data:e}=s;if(!e)return;if(e.key)r.add(e.key);if(e.keys)for(const t of e.keys)r.add(t);if(e.pairs)for(const[t]of e.pairs)r.add(t);if(e.prevPairs)for(const[t]of e.prevPairs)r.add(t)}function k(s,r){const{action:e,data:t}=s;switch(e){case"setItem":if(t?.key&&t?.value!==void 0){r.set(t.key,t.value)}break;case"removeItem":if(t?.key){r.set(t.key,null)}break;case"mergeItem":if(t?.key&&t?.value!==void 0){const a=r.get(t.key);if(a){try{const n=JSON.parse(a);const i=JSON.parse(t.value);const o={...n,...i};r.set(t.key,JSON.stringify(o))}catch{r.set(t.key,t.value)}}else{r.set(t.key,t.value)}}break;case"multiSet":if(t?.pairs){for(const[a,n]of t.pairs){r.set(a,n)}}break;case"multiRemove":if(t?.keys){for(const a of t.keys){r.set(a,null)}}break;case"multiMerge":if(t?.pairs){for(const[a,n]of t.pairs){const i=r.get(a);if(i){try{const o=JSON.parse(i);const u=JSON.parse(n);const v={...o,...u};r.set(a,JSON.stringify(v))}catch{r.set(a,n)}}else{r.set(a,n)}}}break;case"clear":r.clear();break}}export function canUndo(s){const{action:r,data:e}=s;switch(r){case"setItem":case"mergeItem":case"removeItem":return!!e?.key&&!c(e.prevValue);case"multiSet":case"multiRemove":case"multiMerge":case"clear":return!!e?.prevPairs&&e.prevPairs.length>0&&!c(e.prevPairs);default:return false}}
@@ -1,76 +1 @@
1
- "use strict";
2
-
3
- /** Return a concise string describing the JavaScript type of the provided value. */
4
- export function getValueTypeLabel(value) {
5
- if (value === null) return "null";
6
- if (value === undefined) return "undefined";
7
- if (Array.isArray(value)) return "array";
8
- const type = typeof value;
9
- if (type === "object") return "object";
10
- if (type === "boolean") return "boolean";
11
- if (type === "number") return "number";
12
- if (type === "string") return "string";
13
- return "unknown";
14
- }
15
-
16
- /**
17
- * A stored value as a tree can show it.
18
- *
19
- * AsyncStorage and SecureStore hold strings, so an object arrives as the text
20
- * `{"a":1}` — displaying that as a string is technically true and useless. Any
21
- * surface that renders or edits a value structurally has to do this same
22
- * un-stringify first, so it lives here rather than being re-derived (slightly
23
- * differently) in each one.
24
- *
25
- * A string that doesn't parse comes back untouched: it was just a string that
26
- * happened to start with a brace.
27
- */
28
- export function parseStorageValue(value) {
29
- if (typeof value !== "string") return value;
30
- const trimmed = value.trim();
31
- if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return value;
32
- try {
33
- return JSON.parse(value);
34
- } catch {
35
- return value;
36
- }
37
- }
38
-
39
- /** Longest value preview rendered inline next to the type label. */
40
- const MAX_INLINE_PREVIEW = 40;
41
-
42
- /**
43
- * Short, human-readable preview of a value for inline display next to the type
44
- * label, or `null` when the value is too large/complex to preview (long
45
- * strings, objects, arrays). Lets the user read simple values without opening
46
- * the card.
47
- */
48
- export function getValuePreview(value) {
49
- switch (typeof value) {
50
- case "boolean":
51
- return value ? "true" : "false";
52
- case "number":
53
- return Number.isFinite(value) ? String(value) : null;
54
- case "string":
55
- {
56
- if (value.length === 0) return '""';
57
- if (value.length > MAX_INLINE_PREVIEW) return null;
58
- // Collapse whitespace so multi-line/tabbed values stay on one line.
59
- return `"${value.replace(/\s+/g, " ")}"`;
60
- }
61
- default:
62
- return null;
63
- // objects, arrays, null, undefined
64
- }
65
- }
66
-
67
- /**
68
- * Type label optionally followed by a short value preview — e.g. `boolean · true`,
69
- * `number · 42`, `string · "hello"`. Falls back to just the type label when the
70
- * value is too large to preview.
71
- */
72
- export function getValueTypeWithPreview(value) {
73
- const label = getValueTypeLabel(value);
74
- const preview = getValuePreview(value);
75
- return preview ? `${label} · ${preview}` : label;
76
- }
1
+ "use strict";export function getValueTypeLabel(r){if(r===null)return"null";if(r===void 0)return"undefined";if(Array.isArray(r))return"array";const t=typeof r;if(t==="object")return"object";if(t==="boolean")return"boolean";if(t==="number")return"number";if(t==="string")return"string";return"unknown"}export function parseStorageValue(r){if(typeof r!=="string")return r;const t=r.trim();if(!t.startsWith("{")&&!t.startsWith("["))return r;try{return JSON.parse(r)}catch{return r}}const n=40;export function getValuePreview(r){switch(typeof r){case"boolean":return r?"true":"false";case"number":return Number.isFinite(r)?String(r):null;case"string":{if(r.length===0)return'""';if(r.length>n)return null;return`"${r.replace(/\s+/g," ")}"`}default:return null}}export function getValueTypeWithPreview(r){const t=getValueTypeLabel(r);const e=getValuePreview(r);return e?`${t} \xB7 ${e}`:t}
@@ -51,4 +51,5 @@ export { storageEventStore, isValueOnDevice, batchPairsOf, } from "./storage/sto
51
51
  * @internal
52
52
  */
53
53
  export { requestStorageBrowserRefresh } from "./storage/utils/storageBrowserRefresh";
54
+ export { startBrowserStorageCapture } from './storage/utils/browserStorageLifecycle';
54
55
  //# sourceMappingURL=index.d.ts.map
@@ -1,11 +1,3 @@
1
- /**
2
- * MMKVInstanceSelector Component
3
- *
4
- * Dropdown selector for choosing between multiple MMKV instances.
5
- * Shows instance ID, key count, and metadata badges (encrypted, read-only).
6
- *
7
- * Used in GameUIStorageBrowser when storage type filter is set to "mmkv".
8
- */
9
1
  interface MMKVInstanceSelectorProps {
10
2
  selectedInstanceId: string | null;
11
3
  onSelectInstance: (instanceId: string) => void;
@@ -1,10 +1,3 @@
1
- /**
2
- * StorageEventCard
3
- *
4
- * Shared card component for displaying storage events.
5
- * Used by both Storage DevTools and Events DevTools for consistent UI.
6
- * Uses CompactRow for consistent layout with Redux/React Query cards.
7
- */
8
1
  /** Value type for storage events */
9
2
  export type StorageValueType = "string" | "number" | "boolean" | "null" | "undefined" | "object" | "array";
10
3
  /**
@@ -20,12 +20,8 @@ interface StorageKeyRowProps {
20
20
  /** Toggle this key's pinned state */
21
21
  onTogglePin?: (key: string) => void;
22
22
  /**
23
- * Open the full-screen editor for this key. Omit to keep the row read-only —
24
- * the Edit affordance only appears when a host supplies this.
25
- *
26
- * The card deliberately doesn't edit anything itself: a tree, six structural
27
- * actions and a keyboard don't fit in an expanded row, and cramming them in
28
- * is what this replaced. See `StorageKeyEditorScreen`.
23
+ * Open `StorageKeyDetailScreen` to edit this key. The Edit affordance appears
24
+ * only when the host supplies this callback; the row does not edit values.
29
25
  */
30
26
  onEditKey?: (storageKey: StorageKeyInfo) => void;
31
27
  /**
@@ -1,18 +1,3 @@
1
- /**
2
- * "Which backend?" — the pill row shared by the Keys and Events tabs.
3
- *
4
- * Both tabs answer questions about the same three backends, so asking the
5
- * question two different ways (or, as it was, only on one tab) is a gap rather
6
- * than a simplification: you filter the key list to Keychain, switch to Events
7
- * to see what wrote to it, and you're looking at everything again.
8
- *
9
- * The selection is owned by the modal and passed to both, so switching tabs
10
- * keeps the filter you set.
11
- *
12
- * Each pill carries the count it WOULD show, computed before the type filter is
13
- * applied — a count that collapsed to zero the moment you picked another type
14
- * would tell you nothing about where to look next.
15
- */
16
1
  export type StorageTypeFilter = "all" | "async" | "mmkv" | "secure";
17
2
  export type StorageTypeCounts = Record<StorageTypeFilter, number>;
18
3
  interface StorageTypeFilterBarProps {
@@ -1,4 +1,4 @@
1
- import { StorageKeyInfo } from "../types";
1
+ import { RequiredStorageKey, StorageKeyInfo } from "../types";
2
2
  interface UseSecureStoreKeysOptions {
3
3
  /** Re-read interval in ms. `0` disables polling. */
4
4
  pollMs?: number;
@@ -20,6 +20,6 @@ interface UseSecureStoreKeysResult {
20
20
  * Values are re-read on a poll and whenever the registry changes, so the
21
21
  * browser tracks writes the app makes while the tool is open.
22
22
  */
23
- export declare function useSecureStoreKeys(options?: UseSecureStoreKeysOptions): UseSecureStoreKeysResult;
23
+ export declare function useSecureStoreKeys(requiredStorageKeys?: RequiredStorageKey[], options?: UseSecureStoreKeysOptions): UseSecureStoreKeysResult;
24
24
  export {};
25
25
  //# sourceMappingURL=useSecureStoreKeys.d.ts.map
@@ -1,4 +1,5 @@
1
1
  import { type StorageEvent } from "../stores/storageEventStore";
2
+ import type { RequiredStorageKey } from "../types";
2
3
  /**
3
4
  * Sentinel used in WIRE-FORM snapshots in place of oversized values.
4
5
  * Storage events, MMKV browse dumps, and SecureStore dumps all reuse this
@@ -47,26 +48,19 @@ export interface SecureSnapshotEntry {
47
48
  value: unknown;
48
49
  }
49
50
  /**
50
- * Sync adapter for the storage tool, consumed by @buoy-gg/external-sync's
51
- * `useExternalSync` (structurally matches its ToolSyncAdapter interface so
52
- * this package doesn't need a dependency on it).
53
- *
54
- * Subscribing starts the underlying capture lifecycle (including the initial
55
- * key scan), so storage events are only recorded while a dashboard is
56
- * watching.
57
- *
58
- * The `async.*` actions mirror the AsyncStorage API so the desktop dashboard
59
- * can proxy its browse/edit mode against the device's real storage.
60
- *
61
- * v2: oversized / unserializable event values are replaced with
62
- * VALUE_ON_DEVICE. Dashboards fetch them via `getEventDetail`.
51
+ * Called by `createStorageTool` so remote dashboards validate against the
52
+ * same required keys as the on-device tool. The desktop panel used to have no
53
+ * way to learn them and showed every key as unchecked.
63
54
  */
55
+ export declare function setToolRequiredStorageKeys(keys: RequiredStorageKey[]): void;
64
56
  export declare const storageSyncAdapter: {
65
57
  version: number;
66
58
  getSnapshot: () => StorageEvent[];
67
59
  subscribe: (onChange: () => void) => () => void;
68
60
  actions: {
69
61
  clearEvents: () => void;
62
+ /** The app's required storage keys, as given to `createStorageTool`. */
63
+ getRequiredKeys: () => RequiredStorageKey[];
70
64
  /**
71
65
  * On-demand detail: one event's real value/prevValue/pairs.
72
66
  * The per-snapshot stream stays payload-light; this is the explicit,
@@ -0,0 +1,24 @@
1
+ import type { AsyncStorageEventListener } from './AsyncStorageListener';
2
+ export type { AsyncStorageEvent, AsyncStorageEventListener } from './AsyncStorageListener';
3
+ export declare function startListening(): Promise<void>;
4
+ export declare function stopListening(): void;
5
+ export declare function addListener(listener: AsyncStorageEventListener): () => void;
6
+ export declare function removeAllListeners(): void;
7
+ export declare function isListening(): boolean;
8
+ export declare function getListenerCount(): number;
9
+ export declare function pauseCapture(): void;
10
+ export declare function resumeCapture(): void;
11
+ export declare function isPaused(): boolean;
12
+ declare const asyncStorageListener: {
13
+ startListening: typeof startListening;
14
+ stopListening: typeof stopListening;
15
+ addListener: typeof addListener;
16
+ removeAllListeners: typeof removeAllListeners;
17
+ pause: typeof pauseCapture;
18
+ resume: typeof resumeCapture;
19
+ readonly isActive: boolean;
20
+ readonly listenerCount: number;
21
+ readonly paused: boolean;
22
+ };
23
+ export default asyncStorageListener;
24
+ //# sourceMappingURL=AsyncStorageListener.web.d.ts.map
@@ -0,0 +1,3 @@
1
+ /** Native backends are registered by the host application. */
2
+ export declare function startBrowserStorageCapture(): () => void;
3
+ //# sourceMappingURL=browserStorageLifecycle.d.ts.map
@@ -0,0 +1,2 @@
1
+ export declare function startBrowserStorageCapture(): () => void;
2
+ //# sourceMappingURL=browserStorageLifecycle.web.d.ts.map
@@ -0,0 +1,4 @@
1
+ export declare function isMMKVAvailable(): boolean;
2
+ export declare function getMMKVClass(): null;
3
+ export declare function getMMKVUnavailableMessage(): string;
4
+ //# sourceMappingURL=mmkvAvailability.web.d.ts.map
@@ -0,0 +1,8 @@
1
+ export declare const storageLabels: {
2
+ async: string;
3
+ asyncFull: string;
4
+ mmkv: string;
5
+ secure: string;
6
+ hasSecure: boolean;
7
+ };
8
+ //# sourceMappingURL=storageLabels.d.ts.map
@@ -0,0 +1,8 @@
1
+ export declare const storageLabels: {
2
+ async: string;
3
+ asyncFull: string;
4
+ mmkv: string;
5
+ secure: string;
6
+ hasSecure: boolean;
7
+ };
8
+ //# sourceMappingURL=storageLabels.web.d.ts.map