@buoy-gg/storage 7.0.41 → 7.0.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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 +5 -5
  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,148 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * MMKV Type Detection Utilities
5
- *
6
- * MMKV stores values with native types (string, number, boolean, ArrayBuffer).
7
- * This module provides utilities to detect the type of a stored value by trying
8
- * each getter sequentially.
9
- */
10
-
11
- // Use 'any' type for MMKV to avoid hard dependency on react-native-mmkv
12
-
13
- /**
14
- * Detect the type of a value stored in MMKV by trying each getter.
15
- *
16
- * Since MMKV doesn't provide a getType() method, we must try each getter
17
- * (getString, getNumber, getBoolean, getBuffer) until one returns a value.
18
- *
19
- * Order matters: We try in order of most common types first.
20
- *
21
- * @param instance - MMKV instance to read from
22
- * @param key - Storage key
23
- * @returns Value and its detected type
24
- *
25
- * @example
26
- * ```typescript
27
- * const instance = createMMKV();
28
- * instance.set('name', 'John');
29
- * instance.set('age', 30);
30
- * instance.set('active', true);
31
- *
32
- * detectMMKVType(instance, 'name'); // { value: 'John', type: 'string' }
33
- * detectMMKVType(instance, 'age'); // { value: 30, type: 'number' }
34
- * detectMMKVType(instance, 'active'); // { value: true, type: 'boolean' }
35
- * detectMMKVType(instance, 'missing');// { value: undefined, type: 'unknown' }
36
- * ```
37
- */
38
- export function detectMMKVType(instance, key) {
39
- // MMKV stores no type metadata, so the native getters can cross-read: in
40
- // particular `getString` returns "" (an empty string, NOT undefined) for many
41
- // non-string values like numbers and `false`. Trying getString first and
42
- // trusting its result therefore mis-detects those as empty strings — e.g.
43
- // a key set to 42 or false would render as "". Probe the getters and only let
44
- // getString win when it returns a NON-empty string; treat an empty result as
45
- // ambiguous and prefer the number/boolean getters.
46
- const stringValue = instance.getString(key);
47
-
48
- // A non-empty string is unambiguously a string.
49
- if (stringValue !== undefined && stringValue !== '') {
50
- return {
51
- value: stringValue,
52
- type: 'string'
53
- };
54
- }
55
-
56
- // Empty getString result is ambiguous (genuine "" vs a number/boolean the
57
- // native layer decoded to ""). Prefer typed getters when they have a value.
58
- const numberValue = instance.getNumber(key);
59
- if (numberValue !== undefined) {
60
- return {
61
- value: numberValue,
62
- type: 'number'
63
- };
64
- }
65
- const booleanValue = instance.getBoolean(key);
66
- if (booleanValue !== undefined) {
67
- return {
68
- value: booleanValue,
69
- type: 'boolean'
70
- };
71
- }
72
-
73
- // getString returned "" and nothing else matched -> a genuine empty string.
74
- if (stringValue === '') {
75
- return {
76
- value: '',
77
- type: 'string'
78
- };
79
- }
80
-
81
- // Try buffer (least common)
82
- const bufferValue = instance.getBuffer(key);
83
- if (bufferValue !== undefined) {
84
- // Format buffer for display (don't return raw ArrayBuffer)
85
- return {
86
- value: `<ArrayBuffer ${bufferValue.byteLength} bytes>`,
87
- type: 'buffer'
88
- };
89
- }
90
-
91
- // Key doesn't exist or unknown type
92
- return {
93
- value: undefined,
94
- type: 'unknown'
95
- };
96
- }
97
-
98
- /**
99
- * Format an MMKV value for display in the UI.
100
- *
101
- * @param value - The value to format
102
- * @param type - The detected type
103
- * @returns Formatted string representation
104
- *
105
- * @example
106
- * ```typescript
107
- * formatMMKVValue('hello', 'string'); // '"hello"'
108
- * formatMMKVValue(42, 'number'); // '42'
109
- * formatMMKVValue(true, 'boolean'); // 'true'
110
- * formatMMKVValue('<ArrayBuffer 1024 bytes>', 'buffer'); // '<ArrayBuffer 1024 bytes>'
111
- * ```
112
- */
113
- export function formatMMKVValue(value, type) {
114
- if (value === undefined) return 'undefined';
115
- if (value === null) return 'null';
116
- switch (type) {
117
- case 'string':
118
- return `"${value}"`;
119
- case 'number':
120
- return String(value);
121
- case 'boolean':
122
- return value ? 'true' : 'false';
123
- case 'buffer':
124
- // Value is already formatted as "<ArrayBuffer X bytes>"
125
- return value;
126
- case 'unknown':
127
- return 'unknown';
128
- default:
129
- return String(value);
130
- }
131
- }
132
-
133
- /**
134
- * Check if a value type matches an expected type for validation.
135
- *
136
- * @param actualType - Detected type
137
- * @param expectedType - Expected type from configuration
138
- * @returns True if types match
139
- *
140
- * @example
141
- * ```typescript
142
- * isTypeMatch('string', 'string'); // true
143
- * isTypeMatch('number', 'string'); // false
144
- * ```
145
- */
146
- export function isTypeMatch(actualType, expectedType) {
147
- return actualType === expectedType;
148
- }
1
+ "use strict";export function detectMMKVType(e,n){const r=e.getString(n);if(r!==void 0&&r!==""){return{value:r,type:"string"}}const t=e.getNumber(n);if(t!==void 0){return{value:t,type:"number"}}const u=e.getBoolean(n);if(u!==void 0){return{value:u,type:"boolean"}}if(r===""){return{value:"",type:"string"}}const f=e.getBuffer(n);if(f!==void 0){return{value:`<ArrayBuffer ${f.byteLength} bytes>`,type:"buffer"}}return{value:void 0,type:"unknown"}}export function formatMMKVValue(e,n){if(e===void 0)return"undefined";if(e===null)return"null";switch(n){case"string":return`"${e}"`;case"number":return String(e);case"boolean":return e?"true":"false";case"buffer":return e;case"unknown":return"unknown";default:return String(e)}}export function isTypeMatch(e,n){return e===n}
@@ -1,13 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Whether a required-key declaration should be enforced by a given backend
5
- * hook. Explicit `storageType` wins; bare string keys default to AsyncStorage
6
- * (the historical zero-config backend). Objects without `storageType` still
7
- * apply to every backend — matching prior behavior for apps that never set it.
8
- */
9
- export function requiredKeyAppliesTo(req, backend) {
10
- if (typeof req === "string") return backend === "async";
11
- if (req.storageType) return req.storageType === backend;
12
- return true;
13
- }
1
+ "use strict";export function requiredKeyAppliesTo(e,r){if(typeof e==="string")return r==="async";if(e.storageType)return e.storageType===r;return true}
@@ -1,209 +1 @@
1
- "use strict";
2
-
3
- /**
4
- * Writing a storage value back, in one place.
5
- *
6
- * The counterpart to `deleteStorageKeys` — and the same reasoning applies: each
7
- * backend writes differently, and a second copy of that fan-out is how one
8
- * backend quietly starts corrupting values.
9
- *
10
- * The hard part is NOT the write, it's the types:
11
- *
12
- * - **AsyncStorage** stores strings only. A value that was stored as JSON must
13
- * stay valid JSON, or an object silently becomes a quoted string and the app
14
- * that reads it breaks in a way that looks nothing like a devtools edit.
15
- * - **MMKV** is natively typed (string / number / boolean / buffer). Writing
16
- * `"42"` over a number turns it into a string, so the original type is
17
- * restored from `valueType`. Buffers can't round-trip at all — the snapshot
18
- * only ever carried a `<ArrayBuffer n bytes>` placeholder.
19
- * - **SecureStore** stores strings, and biometric-protected keys are never
20
- * touched (writing needs the same auth prompt reading does).
21
- *
22
- * Pro gating and confirmation are deliberately NOT here; they belong to the UI
23
- * that has the user's attention. This assumes the caller already asked.
24
- */
25
-
26
- import AsyncStorage from "@react-native-async-storage/async-storage";
27
- import { secureStoreRegistry } from "./SecureStoreRegistry";
28
- /**
29
- * Why a key can't be edited, or null when it can. UI uses this both to hide the
30
- * edit affordance and to explain itself, rather than failing at save time.
31
- */
32
- export function storageEditBlockedReason(storageKey, mmkvInstances = []) {
33
- if (storageKey.storageType === "mmkv") {
34
- if (storageKey.valueType === "buffer") {
35
- return "Buffer values can't be edited — the tool only ever sees their byte length, not their contents.";
36
- }
37
- const instance = mmkvInstances.find(i => i.id === (storageKey.instanceId || "default"));
38
- if (instance?.readOnly) {
39
- return `MMKV instance "${instance.id}" is registered read-only.`;
40
- }
41
- }
42
- if (storageKey.storageType === "secure") {
43
- const entry = secureStoreRegistry.getAll().find(e => e.key === storageKey.key);
44
- if (entry?.options.requireAuthentication) {
45
- return "Biometric-protected keys can't be edited — writing one would fire an auth prompt.";
46
- }
47
- if (!secureStoreRegistry.getModule()) {
48
- return "No SecureStore module is registered.";
49
- }
50
- }
51
- return null;
52
- }
53
-
54
- /**
55
- * Validate `raw` for this key WITHOUT writing. Returns an error message, or
56
- * null when the text is acceptable. The editor calls this as you type.
57
- */
58
- export function validateStorageValue(storageKey, raw) {
59
- if (storageKey.storageType === "mmkv") {
60
- const type = mmkvTargetType(storageKey);
61
- if (type === "number") {
62
- if (raw.trim() === "" || Number.isNaN(Number(raw))) {
63
- return "Must be a number — this MMKV key is stored as a number.";
64
- }
65
- }
66
- if (type === "boolean") {
67
- const t = raw.trim().toLowerCase();
68
- if (t !== "true" && t !== "false") {
69
- return 'Must be "true" or "false" — this MMKV key is stored as a boolean.';
70
- }
71
- }
72
- return null;
73
- }
74
-
75
- // AsyncStorage + SecureStore are string-valued. Only guard the case where
76
- // the CURRENT value is structured: silently flattening an object into a
77
- // string is the corruption worth preventing. A plain string stays free-form.
78
- if (isStructured(storageKey.value)) {
79
- try {
80
- JSON.parse(raw);
81
- } catch (e) {
82
- return `This key holds JSON — ${e instanceof Error ? e.message : "invalid JSON"}`;
83
- }
84
- }
85
- return null;
86
- }
87
-
88
- /**
89
- * The text an editor should open with: JSON pretty-printed so it's actually
90
- * editable, everything else verbatim.
91
- */
92
- export function storageValueToEditableText(value) {
93
- if (value === undefined || value === null) return "";
94
- if (typeof value === "string") {
95
- // Values arrive already parsed when they were JSON, so a string here is a
96
- // real string — except AsyncStorage hands back raw JSON text sometimes.
97
- const trimmed = value.trim();
98
- if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
99
- try {
100
- return JSON.stringify(JSON.parse(value), null, 2);
101
- } catch {
102
- return value;
103
- }
104
- }
105
- return value;
106
- }
107
- if (typeof value === "object") return JSON.stringify(value, null, 2);
108
- return String(value);
109
- }
110
-
111
- /**
112
- * The value as a STRUCTURE, for the tree editor to apply ops against.
113
- *
114
- * Backends disagree on how far they've already parsed: `useAsyncStorageKeys`
115
- * hands back a parsed object, while MMKV reports its native type so a JSON blob
116
- * arrives as the raw string. Both have to end up as the same thing before an op
117
- * can address a path inside them.
118
- *
119
- * Returns `undefined` when the value isn't a container — scalars are edited
120
- * through the plain value editor, not the tree.
121
- */
122
- export function structuredStorageValue(storageKey) {
123
- const {
124
- value
125
- } = storageKey;
126
- if (value !== null && typeof value === "object") return value;
127
- if (typeof value === "string") {
128
- const trimmed = value.trim();
129
- if (!trimmed.startsWith("{") && !trimmed.startsWith("[")) return undefined;
130
- try {
131
- const parsed = JSON.parse(value);
132
- return parsed !== null && typeof parsed === "object" ? parsed : undefined;
133
- } catch {
134
- return undefined;
135
- }
136
- }
137
- return undefined;
138
- }
139
-
140
- /**
141
- * Write `raw` to whichever backend holds this key, restoring the value's
142
- * original type. Rejects (rather than writing something lossy) when the key
143
- * isn't editable or the text doesn't fit the type — callers surface that.
144
- */
145
- export async function setStorageValue(storageKey, raw, mmkvInstances = []) {
146
- const blocked = storageEditBlockedReason(storageKey, mmkvInstances);
147
- if (blocked) throw new Error(blocked);
148
- const invalid = validateStorageValue(storageKey, raw);
149
- if (invalid) throw new Error(invalid);
150
- switch (storageKey.storageType) {
151
- case "async":
152
- {
153
- await AsyncStorage.setItem(storageKey.key, normalizeJsonText(storageKey, raw));
154
- return;
155
- }
156
- case "secure":
157
- {
158
- await secureStoreRegistry.setValue(storageKey.key, normalizeJsonText(storageKey, raw));
159
- return;
160
- }
161
- case "mmkv":
162
- {
163
- const instanceId = storageKey.instanceId || "default";
164
- const target = mmkvInstances.find(i => i.id === instanceId);
165
- if (!target) {
166
- throw new Error(`MMKV instance "${instanceId}" is not registered.`);
167
- }
168
- target.instance.set(storageKey.key, coerceMMKV(storageKey, raw));
169
- return;
170
- }
171
- default:
172
- {
173
- throw new Error(`Unsupported storage type "${String(storageKey.storageType)}"`);
174
- }
175
- }
176
- }
177
-
178
- /** True when the value is an object/array (so its text must stay valid JSON). */
179
- function isStructured(value) {
180
- return value !== null && typeof value === "object";
181
- }
182
-
183
- /**
184
- * Re-serialize JSON so the stored string is compact and canonical, matching
185
- * what the app itself would have written with `JSON.stringify`. Free-form
186
- * strings pass through untouched.
187
- */
188
- function normalizeJsonText(storageKey, raw) {
189
- if (!isStructured(storageKey.value)) return raw;
190
- return JSON.stringify(JSON.parse(raw));
191
- }
192
-
193
- /** The MMKV native type to write back, defaulting to the current JS type. */
194
- function mmkvTargetType(storageKey) {
195
- if (storageKey.valueType) return storageKey.valueType;
196
- if (typeof storageKey.value === "number") return "number";
197
- if (typeof storageKey.value === "boolean") return "boolean";
198
- return "string";
199
- }
200
- function coerceMMKV(storageKey, raw) {
201
- switch (mmkvTargetType(storageKey)) {
202
- case "number":
203
- return Number(raw);
204
- case "boolean":
205
- return raw.trim().toLowerCase() === "true";
206
- default:
207
- return raw;
208
- }
209
- }
1
+ "use strict";import l from"@react-native-async-storage/async-storage";import{secureStoreRegistry as i}from"./SecureStoreRegistry";export function storageEditBlockedReason(e,t=[]){if(e.storageType==="mmkv"){if(e.valueType==="buffer"){return"Buffer values can't be edited \u2014 the tool only ever sees their byte length, not their contents."}const r=t.find(n=>n.id===(e.instanceId||"default"));if(r?.readOnly){return`MMKV instance "${r.id}" is registered read-only.`}}if(e.storageType==="secure"){const r=i.getAll().find(n=>n.key===e.key);if(r?.options.requireAuthentication){return"Biometric-protected keys can't be edited \u2014 writing one would fire an auth prompt."}if(!i.getModule()){return"No SecureStore module is registered."}}return null}export function validateStorageValue(e,t){if(e.storageType==="mmkv"){const r=a(e);if(r==="number"){if(t.trim()===""||Number.isNaN(Number(t))){return"Must be a number \u2014 this MMKV key is stored as a number."}}if(r==="boolean"){const n=t.trim().toLowerCase();if(n!=="true"&&n!=="false"){return'Must be "true" or "false" \u2014 this MMKV key is stored as a boolean.'}}return null}if(f(e.value)){try{JSON.parse(t)}catch(r){return`This key holds JSON \u2014 ${r instanceof Error?r.message:"invalid JSON"}`}}return null}export function storageValueToEditableText(e){if(e===void 0||e===null)return"";if(typeof e==="string"){const t=e.trim();if(t.startsWith("{")||t.startsWith("[")){try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}return e}if(typeof e==="object")return JSON.stringify(e,null,2);return String(e)}export function structuredStorageValue(e){const{value:t}=e;if(t!==null&&typeof t==="object")return t;if(typeof t==="string"){const r=t.trim();if(!r.startsWith("{")&&!r.startsWith("["))return void 0;try{const n=JSON.parse(t);return n!==null&&typeof n==="object"?n:void 0}catch{return void 0}}return void 0}export async function setStorageValue(e,t,r=[]){const n=storageEditBlockedReason(e,r);if(n)throw new Error(n);const u=validateStorageValue(e,t);if(u)throw new Error(u);switch(e.storageType){case"async":{await l.setItem(e.key,c(e,t));return}case"secure":{await i.setValue(e.key,c(e,t));return}case"mmkv":{const o=e.instanceId||"default";const s=r.find(d=>d.id===o);if(!s){throw new Error(`MMKV instance "${o}" is not registered.`)}s.instance.set(e.key,p(e,t));return}default:{throw new Error(`Unsupported storage type "${String(e.storageType)}"`)}}}function f(e){return e!==null&&typeof e==="object"}function c(e,t){if(!f(e.value))return t;return JSON.stringify(JSON.parse(t))}function a(e){if(e.valueType)return e.valueType;if(typeof e.value==="number")return"number";if(typeof e.value==="boolean")return"boolean";return"string"}function p(e,t){switch(a(e)){case"number":return Number(t);case"boolean":return t.trim().toLowerCase()==="true";default:return t}}