@buoy-gg/storage 7.0.4 → 7.0.5

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 (148) hide show
  1. package/lib/commonjs/index.js +77 -1
  2. package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +10 -3
  3. package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +26 -8
  4. package/lib/commonjs/storage/components/GameUIStorageBrowser.js +263 -115
  5. package/lib/commonjs/storage/components/GameUIStorageStats.js +7 -7
  6. package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +1 -1
  7. package/lib/commonjs/storage/components/MMKVInstanceSelector.js +1 -1
  8. package/lib/commonjs/storage/components/SelectionActionBar.js +2 -36
  9. package/lib/commonjs/storage/components/StorageActions.js +6 -6
  10. package/lib/commonjs/storage/components/StorageBrowserMode.js +16 -2
  11. package/lib/commonjs/storage/components/StorageEventDetailContent.js +106 -149
  12. package/lib/commonjs/storage/components/StorageEventListener.js +13 -13
  13. package/lib/commonjs/storage/components/StorageFilterCards.js +13 -135
  14. package/lib/commonjs/storage/components/StorageKeyCard.js +1 -1
  15. package/lib/commonjs/storage/components/StorageKeyEditorScreen.js +392 -0
  16. package/lib/commonjs/storage/components/StorageKeyRow.js +53 -15
  17. package/lib/commonjs/storage/components/StorageKeySection.js +10 -4
  18. package/lib/commonjs/storage/components/StorageKeyStats.js +10 -10
  19. package/lib/commonjs/storage/components/StorageModalWithTabs.js +272 -129
  20. package/lib/commonjs/storage/components/StorageScalarKeyEditor.js +46 -0
  21. package/lib/commonjs/storage/components/StorageTypeFilterBar.js +141 -0
  22. package/lib/commonjs/storage/components/StorageValueEditModal.js +361 -0
  23. package/lib/commonjs/storage/hooks/useKeyEditor.js +104 -0
  24. package/lib/commonjs/storage/hooks/useMeasuredWidth.js +74 -0
  25. package/lib/commonjs/storage/hooks/useSecureStoreKeys.js +70 -15
  26. package/lib/commonjs/storage/hooks/useTreeDraft.js +107 -0
  27. package/lib/commonjs/storage/index.js +29 -0
  28. package/lib/commonjs/storage/stores/storageEventStore.js +4 -2
  29. package/lib/commonjs/storage/sync/storageSyncAdapter.js +125 -3
  30. package/lib/commonjs/storage/utils/AsyncStorageListener.js +76 -12
  31. package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +10 -9
  32. package/lib/commonjs/storage/utils/MMKVListener.js +40 -4
  33. package/lib/commonjs/storage/utils/SecureStoreRegistry.js +52 -1
  34. package/lib/commonjs/storage/utils/deleteStorageKeys.js +53 -0
  35. package/lib/commonjs/storage/utils/index.js +13 -0
  36. package/lib/commonjs/storage/utils/lineDiff.js +21 -354
  37. package/lib/commonjs/storage/utils/setStorageValue.js +218 -0
  38. package/lib/commonjs/storage/utils/storageBrowserRefresh.js +49 -0
  39. package/lib/commonjs/storage/utils/storageOps.js +53 -0
  40. package/lib/commonjs/storage/utils/storageTimeTravelUtils.js +60 -38
  41. package/lib/commonjs/storage/utils/valueType.js +24 -0
  42. package/lib/module/index.js +18 -1
  43. package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +10 -3
  44. package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +26 -8
  45. package/lib/module/storage/components/GameUIStorageBrowser.js +266 -118
  46. package/lib/module/storage/components/GameUIStorageStats.js +7 -7
  47. package/lib/module/storage/components/MMKVInstanceInfoPanel.js +1 -1
  48. package/lib/module/storage/components/MMKVInstanceSelector.js +1 -1
  49. package/lib/module/storage/components/SelectionActionBar.js +2 -36
  50. package/lib/module/storage/components/StorageActions.js +7 -7
  51. package/lib/module/storage/components/StorageBrowserMode.js +16 -2
  52. package/lib/module/storage/components/StorageEventDetailContent.js +110 -151
  53. package/lib/module/storage/components/StorageEventListener.js +14 -14
  54. package/lib/module/storage/components/StorageFilterCards.js +13 -135
  55. package/lib/module/storage/components/StorageKeyCard.js +1 -1
  56. package/lib/module/storage/components/StorageKeyEditorScreen.js +388 -0
  57. package/lib/module/storage/components/StorageKeyRow.js +55 -17
  58. package/lib/module/storage/components/StorageKeySection.js +11 -5
  59. package/lib/module/storage/components/StorageKeyStats.js +11 -10
  60. package/lib/module/storage/components/StorageModalWithTabs.js +272 -130
  61. package/lib/module/storage/components/StorageScalarKeyEditor.js +42 -0
  62. package/lib/module/storage/components/StorageTypeFilterBar.js +136 -0
  63. package/lib/module/storage/components/StorageValueEditModal.js +357 -0
  64. package/lib/module/storage/hooks/useKeyEditor.js +100 -0
  65. package/lib/module/storage/hooks/useMeasuredWidth.js +71 -0
  66. package/lib/module/storage/hooks/useSecureStoreKeys.js +71 -16
  67. package/lib/module/storage/hooks/useTreeDraft.js +103 -0
  68. package/lib/module/storage/index.js +3 -0
  69. package/lib/module/storage/stores/storageEventStore.js +4 -2
  70. package/lib/module/storage/sync/storageSyncAdapter.js +125 -3
  71. package/lib/module/storage/utils/AsyncStorageListener.js +76 -12
  72. package/lib/module/storage/utils/MMKVInstanceRegistry.js +8 -7
  73. package/lib/module/storage/utils/MMKVListener.js +40 -4
  74. package/lib/module/storage/utils/SecureStoreRegistry.js +52 -1
  75. package/lib/module/storage/utils/deleteStorageKeys.js +49 -0
  76. package/lib/module/storage/utils/index.js +3 -0
  77. package/lib/module/storage/utils/lineDiff.js +7 -354
  78. package/lib/module/storage/utils/setStorageValue.js +209 -0
  79. package/lib/module/storage/utils/storageBrowserRefresh.js +44 -0
  80. package/lib/module/storage/utils/storageOps.js +46 -0
  81. package/lib/module/storage/utils/storageTimeTravelUtils.js +61 -40
  82. package/lib/module/storage/utils/valueType.js +23 -0
  83. package/lib/typescript/index.d.ts +12 -1
  84. package/lib/typescript/index.d.ts.map +1 -1
  85. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts +4 -1
  86. package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +1 -1
  87. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts +7 -1
  88. package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +1 -1
  89. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts +27 -1
  90. package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +1 -1
  91. package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +1 -1
  92. package/lib/typescript/storage/components/StorageBrowserMode.d.ts +17 -1
  93. package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +1 -1
  94. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts +4 -1
  95. package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +1 -1
  96. package/lib/typescript/storage/components/StorageFilterCards.d.ts +9 -3
  97. package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +1 -1
  98. package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts +42 -0
  99. package/lib/typescript/storage/components/StorageKeyEditorScreen.d.ts.map +1 -0
  100. package/lib/typescript/storage/components/StorageKeyRow.d.ts +17 -0
  101. package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +1 -1
  102. package/lib/typescript/storage/components/StorageKeySection.d.ts +7 -1
  103. package/lib/typescript/storage/components/StorageKeySection.d.ts.map +1 -1
  104. package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +1 -1
  105. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts +28 -1
  106. package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +1 -1
  107. package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts +24 -0
  108. package/lib/typescript/storage/components/StorageScalarKeyEditor.d.ts.map +1 -0
  109. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts +29 -0
  110. package/lib/typescript/storage/components/StorageTypeFilterBar.d.ts.map +1 -0
  111. package/lib/typescript/storage/components/StorageValueEditModal.d.ts +36 -0
  112. package/lib/typescript/storage/components/StorageValueEditModal.d.ts.map +1 -0
  113. package/lib/typescript/storage/hooks/useKeyEditor.d.ts +51 -0
  114. package/lib/typescript/storage/hooks/useKeyEditor.d.ts.map +1 -0
  115. package/lib/typescript/storage/hooks/useMeasuredWidth.d.ts +37 -0
  116. package/lib/typescript/storage/hooks/useMeasuredWidth.d.ts.map +1 -0
  117. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts +8 -1
  118. package/lib/typescript/storage/hooks/useSecureStoreKeys.d.ts.map +1 -1
  119. package/lib/typescript/storage/hooks/useTreeDraft.d.ts +67 -0
  120. package/lib/typescript/storage/hooks/useTreeDraft.d.ts.map +1 -0
  121. package/lib/typescript/storage/index.d.ts +2 -0
  122. package/lib/typescript/storage/index.d.ts.map +1 -1
  123. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts +41 -0
  124. package/lib/typescript/storage/sync/storageSyncAdapter.d.ts.map +1 -1
  125. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts +15 -0
  126. package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +1 -1
  127. package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +1 -1
  128. package/lib/typescript/storage/utils/MMKVListener.d.ts +7 -0
  129. package/lib/typescript/storage/utils/MMKVListener.d.ts.map +1 -1
  130. package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts +20 -0
  131. package/lib/typescript/storage/utils/SecureStoreRegistry.d.ts.map +1 -1
  132. package/lib/typescript/storage/utils/deleteStorageKeys.d.ts +27 -0
  133. package/lib/typescript/storage/utils/deleteStorageKeys.d.ts.map +1 -0
  134. package/lib/typescript/storage/utils/index.d.ts +1 -0
  135. package/lib/typescript/storage/utils/index.d.ts.map +1 -1
  136. package/lib/typescript/storage/utils/lineDiff.d.ts +7 -31
  137. package/lib/typescript/storage/utils/lineDiff.d.ts.map +1 -1
  138. package/lib/typescript/storage/utils/setStorageValue.d.ts +64 -0
  139. package/lib/typescript/storage/utils/setStorageValue.d.ts.map +1 -0
  140. package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts +28 -0
  141. package/lib/typescript/storage/utils/storageBrowserRefresh.d.ts.map +1 -0
  142. package/lib/typescript/storage/utils/storageOps.d.ts +25 -0
  143. package/lib/typescript/storage/utils/storageOps.d.ts.map +1 -0
  144. package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts +15 -5
  145. package/lib/typescript/storage/utils/storageTimeTravelUtils.d.ts.map +1 -1
  146. package/lib/typescript/storage/utils/valueType.d.ts +13 -0
  147. package/lib/typescript/storage/utils/valueType.d.ts.map +1 -1
  148. package/package.json +5 -5
@@ -129,6 +129,20 @@ class MMKVListener {
129
129
  // The native listener (addOnValueChangedListener) is sufficient for monitoring writes
130
130
 
131
131
  let nativeListenerUnsubscribe;
132
+
133
+ // Seed the shadow copy so the FIRST observed write already knows what it
134
+ // replaced. Without this, every key's first event would claim the key never
135
+ // existed even when it was carried over from a previous launch.
136
+ const lastKnownValues = new Map();
137
+ try {
138
+ for (const key of instance.getAllKeys() ?? []) {
139
+ if (this.shouldIgnoreKey(key)) continue;
140
+ lastKnownValues.set(key, (0, _mmkvTypeDetection.detectMMKVType)(instance, key).value);
141
+ }
142
+ } catch {
143
+ // Key scan unavailable — prevValue is simply absent until each key is
144
+ // written once, which is strictly better than reporting a wrong value.
145
+ }
132
146
  if (typeof instance.addOnValueChangedListener === "function") {
133
147
  try {
134
148
  nativeListenerUnsubscribe = instance.addOnValueChangedListener(key => {
@@ -141,9 +155,15 @@ class MMKVListener {
141
155
  type
142
156
  } = (0, _mmkvTypeDetection.detectMMKVType)(instance, key);
143
157
 
158
+ // Read the shadow copy BEFORE overwriting it — this is the value the
159
+ // write replaced. `undefined` means the key did not exist.
160
+ const prevValue = lastKnownValues.get(key);
161
+
144
162
  // Determine action: if value is undefined/unknown, it was deleted
145
163
  const isDelete = type === "unknown" || value === undefined;
146
164
  if (isDelete) {
165
+ lastKnownValues.delete(key);
166
+
147
167
  // Key was deleted
148
168
  const event = {
149
169
  action: "delete",
@@ -151,11 +171,14 @@ class MMKVListener {
151
171
  instanceId,
152
172
  data: {
153
173
  key,
174
+ prevValue,
154
175
  success: true
155
176
  }
156
177
  };
157
178
  this.emit(event);
158
179
  } else {
180
+ lastKnownValues.set(key, value);
181
+
159
182
  // Key was set/updated
160
183
  const action = type === "string" ? "set.string" : type === "number" ? "set.number" : type === "boolean" ? "set.boolean" : type === "buffer" ? "set.buffer" : "set.string"; // fallback
161
184
 
@@ -166,6 +189,7 @@ class MMKVListener {
166
189
  data: {
167
190
  key,
168
191
  value,
192
+ prevValue,
169
193
  valueType: type,
170
194
  success: true
171
195
  }
@@ -184,7 +208,8 @@ class MMKVListener {
184
208
  instanceId,
185
209
  originalMethods: {},
186
210
  // Not used in v4
187
- nativeListenerUnsubscribe
211
+ nativeListenerUnsubscribe,
212
+ lastKnownValues
188
213
  });
189
214
  }
190
215
 
@@ -204,9 +229,20 @@ class MMKVListener {
204
229
  nativeListenerUnsubscribe
205
230
  } = tracked;
206
231
 
207
- // Remove native listener
208
- if (nativeListenerUnsubscribe) {
209
- nativeListenerUnsubscribe();
232
+ // Remove native listener. The return of addOnValueChangedListener varies by
233
+ // implementation: a bare unsubscribe function, or a Listener object with a
234
+ // `.remove()` method (react-native-mmkv v4 and the desktop RemoteMMKV
235
+ // back-end). Handle both, and never let teardown throw — this runs during
236
+ // React unmount, where an exception escapes every error boundary and blanks
237
+ // the whole app.
238
+ try {
239
+ if (typeof nativeListenerUnsubscribe === "function") {
240
+ nativeListenerUnsubscribe();
241
+ } else if (typeof nativeListenerUnsubscribe?.remove === "function") {
242
+ nativeListenerUnsubscribe.remove();
243
+ }
244
+ } catch {
245
+ /* listener already gone / back-end offline — nothing to clean up */
210
246
  }
211
247
 
212
248
  // Remove from tracking
@@ -55,12 +55,14 @@ exports.unregisterSecureStoreKey = unregisterSecureStoreKey;
55
55
  class SecureStoreRegistry {
56
56
  module = null;
57
57
  keys = new Map();
58
+ listeners = new Set();
58
59
 
59
60
  /**
60
61
  * Register the SecureStore module and the keys to expose. Callable multiple
61
62
  * times — keys accumulate, the latest module wins.
62
63
  */
63
64
  register(module, descriptors) {
65
+ const before = this.signature();
64
66
  this.module = module;
65
67
  for (const d of descriptors) {
66
68
  const entry = typeof d === "string" ? {
@@ -77,11 +79,41 @@ class SecureStoreRegistry {
77
79
  };
78
80
  this.keys.set(entry.key, entry);
79
81
  }
82
+ // Only announce a real change. The desktop dashboard re-registers the same
83
+ // key set on every device snapshot, and subscribers re-read the keychain on
84
+ // notify — signature-comparing keeps that from turning into a read storm.
85
+ if (this.signature() !== before) this.notify();
80
86
  }
81
87
 
82
88
  /** Remove a key from the registry (does not delete the stored value). */
83
89
  unregister(key) {
84
- this.keys.delete(key);
90
+ if (this.keys.delete(key)) this.notify();
91
+ }
92
+
93
+ /**
94
+ * Subscribe to registry changes (keys registered/unregistered). Lets the
95
+ * browser pick up keys that register after the tool is already open.
96
+ * Returns an unsubscribe function.
97
+ */
98
+ subscribe(listener) {
99
+ this.listeners.add(listener);
100
+ return () => {
101
+ this.listeners.delete(listener);
102
+ };
103
+ }
104
+
105
+ /** Content signature of the registered entries (module identity excluded). */
106
+ signature() {
107
+ return JSON.stringify(Array.from(this.keys.values()));
108
+ }
109
+ notify() {
110
+ this.listeners.forEach(listener => {
111
+ try {
112
+ listener();
113
+ } catch {
114
+ // Listener errors are not ours
115
+ }
116
+ });
85
117
  }
86
118
 
87
119
  /** The registered SecureStore module, or null if none registered yet. */
@@ -108,6 +140,25 @@ class SecureStoreRegistry {
108
140
  if (!this.module || !entry) return;
109
141
  await this.module.deleteItemAsync(key, entry.options);
110
142
  }
143
+
144
+ /**
145
+ * Write a stored value via the registered module, using the options the key
146
+ * was registered with — writing with different `keychainService` options than
147
+ * the value was created with silently creates a SECOND entry the app can't
148
+ * read, so the registered options are the only safe ones to use.
149
+ *
150
+ * Throws rather than no-ops: unlike a delete, a write that quietly did
151
+ * nothing would leave the UI showing a value that was never stored.
152
+ */
153
+ async setValue(key, value) {
154
+ const entry = this.keys.get(key);
155
+ if (!this.module) throw new Error("No SecureStore module is registered");
156
+ if (!entry) throw new Error(`SecureStore key "${key}" is not registered`);
157
+ if (entry.options.requireAuthentication) {
158
+ throw new Error(`SecureStore key "${key}" is biometric-protected — DevTools never writes it`);
159
+ }
160
+ await this.module.setItemAsync(key, value, entry.options);
161
+ }
111
162
  }
112
163
 
113
164
  /**
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.deleteStorageKeys = deleteStorageKeys;
7
+ var _asyncStorageCompat = require("./asyncStorageCompat");
8
+ var _SecureStoreRegistry = require("./SecureStoreRegistry");
9
+ /**
10
+ * Deleting storage keys, in one place.
11
+ *
12
+ * Each backend removes keys differently — AsyncStorage takes a batch,
13
+ * SecureStore has to go through the registry (only it knows each key's
14
+ * `keychainService` options), and MMKV deletes per registered instance. Two call
15
+ * sites need this (the selection action bar and a single row's "Delete key"),
16
+ * and a second copy of that fan-out is exactly how one backend quietly stops
17
+ * being cleaned up.
18
+ *
19
+ * Pro gating and confirmation are deliberately NOT here: they belong to the UI
20
+ * that has the user's attention. This function assumes the caller already asked.
21
+ */
22
+
23
+ /**
24
+ * Removes every key from whichever backend holds it. Rejects on the first
25
+ * failure — callers surface that, rather than reporting a partial delete as
26
+ * success.
27
+ */
28
+ async function deleteStorageKeys(keys, mmkvInstances) {
29
+ if (keys.length === 0) return;
30
+ const asyncKeys = keys.filter(k => k.storageType === "async");
31
+ const mmkvKeys = keys.filter(k => k.storageType === "mmkv");
32
+ const secureKeys = keys.filter(k => k.storageType === "secure");
33
+ if (asyncKeys.length > 0) {
34
+ await (0, _asyncStorageCompat.removeMany)(asyncKeys.map(k => k.key));
35
+ }
36
+ for (const k of secureKeys) {
37
+ await _SecureStoreRegistry.secureStoreRegistry.deleteValue(k.key);
38
+ }
39
+ if (mmkvKeys.length > 0) {
40
+ const byInstance = {};
41
+ mmkvKeys.forEach(k => {
42
+ const instanceId = k.instanceId || "default";
43
+ if (!byInstance[instanceId]) byInstance[instanceId] = [];
44
+ byInstance[instanceId].push(k.key);
45
+ });
46
+ Object.entries(byInstance).forEach(([instanceId, instanceKeys]) => {
47
+ const inst = mmkvInstances.find(i => i.id === instanceId);
48
+ if (inst) {
49
+ instanceKeys.forEach(key => inst.instance.delete(key));
50
+ }
51
+ });
52
+ }
53
+ }
@@ -141,6 +141,12 @@ Object.defineProperty(exports, "mmkvListener", {
141
141
  return _MMKVListener.mmkvListener;
142
142
  }
143
143
  });
144
+ Object.defineProperty(exports, "onStorageBrowserRefresh", {
145
+ enumerable: true,
146
+ get: function () {
147
+ return _storageBrowserRefresh.onStorageBrowserRefresh;
148
+ }
149
+ });
144
150
  Object.defineProperty(exports, "pauseCapture", {
145
151
  enumerable: true,
146
152
  get: function () {
@@ -177,6 +183,12 @@ Object.defineProperty(exports, "removeMMKVInstance", {
177
183
  return _MMKVListener.removeMMKVInstance;
178
184
  }
179
185
  });
186
+ Object.defineProperty(exports, "requestStorageBrowserRefresh", {
187
+ enumerable: true,
188
+ get: function () {
189
+ return _storageBrowserRefresh.requestStorageBrowserRefresh;
190
+ }
191
+ });
180
192
  Object.defineProperty(exports, "resumeCapture", {
181
193
  enumerable: true,
182
194
  get: function () {
@@ -213,5 +225,6 @@ var _AsyncStorageListener = _interopRequireWildcard(require("./AsyncStorageListe
213
225
  var _storageTimeTravelUtils = require("./storageTimeTravelUtils");
214
226
  var _MMKVInstanceRegistry = require("./MMKVInstanceRegistry");
215
227
  var _MMKVListener = require("./MMKVListener");
228
+ var _storageBrowserRefresh = require("./storageBrowserRefresh");
216
229
  var _mmkvTypeDetection = require("./mmkvTypeDetection");
217
230
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); }
@@ -3,361 +3,28 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.DiffType = void 0;
7
- exports.computeLineDiff = computeLineDiff;
8
- /**
9
- * Line-by-line diff computation for React Native
10
- * Adapted from react-diff-viewer for object comparison
11
- */
12
- let DiffType = exports.DiffType = /*#__PURE__*/function (DiffType) {
13
- DiffType["DEFAULT"] = "unchanged";
14
- DiffType["ADDED"] = "added";
15
- DiffType["REMOVED"] = "removed";
16
- DiffType["MODIFIED"] = "modified";
17
- return DiffType;
18
- }({});
19
- /**
20
- * Compute diff based on method - for word-level diff within lines
21
- */
22
- function computeDiffByMethod(oldStr, newStr, method) {
23
- let oldParts;
24
- let newParts;
25
- switch (method) {
26
- case "chars":
27
- // Split into individual characters
28
- oldParts = oldStr.split("");
29
- newParts = newStr.split("");
30
- break;
31
- case "words":
32
- // Split by word boundaries, keeping whitespace
33
- oldParts = oldStr.match(/\S+|\s+/g) || [];
34
- newParts = newStr.match(/\S+|\s+/g) || [];
35
- break;
36
- case "trimmedLines":
37
- {
38
- // For trimmedLines, compare without leading/trailing whitespace
39
- const oldTrimmed = oldStr.trim();
40
- const newTrimmed = newStr.trim();
41
- // But still do word-level diff on the trimmed content
42
- oldParts = oldTrimmed.match(/\S+|\s+/g) || [];
43
- newParts = newTrimmed.match(/\S+|\s+/g) || [];
44
- break;
45
- }
46
- case "lines":
47
- default:
48
- // For lines mode, don't do word diff - just show the whole line
49
- return {
50
- left: [{
51
- value: oldStr,
52
- type: DiffType.REMOVED
53
- }],
54
- right: [{
55
- value: newStr,
56
- type: DiffType.ADDED
57
- }]
58
- };
6
+ Object.defineProperty(exports, "ABSENT_VALUE", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _dataViewer.ABSENT_VALUE;
59
10
  }
60
-
61
- // Simple LCS-like algorithm for better diff
62
- const left = [];
63
- const right = [];
64
- let i = 0,
65
- j = 0;
66
-
67
- // Find matching parts
68
- while (i < oldParts.length && j < newParts.length) {
69
- if (oldParts[i] === newParts[j]) {
70
- // Parts match
71
- left.push({
72
- value: oldParts[i],
73
- type: DiffType.DEFAULT
74
- });
75
- right.push({
76
- value: newParts[j],
77
- type: DiffType.DEFAULT
78
- });
79
- i++;
80
- j++;
81
- } else {
82
- // Look ahead for matches
83
- let foundMatch = false;
84
-
85
- // Check if we can find newParts[j] in upcoming oldParts
86
- for (let k = i + 1; k < Math.min(i + 5, oldParts.length); k++) {
87
- if (oldParts[k] === newParts[j]) {
88
- // Mark everything from i to k-1 as removed
89
- for (let m = i; m < k; m++) {
90
- left.push({
91
- value: oldParts[m],
92
- type: DiffType.REMOVED
93
- });
94
- }
95
- i = k;
96
- foundMatch = true;
97
- break;
98
- }
99
- }
100
- if (!foundMatch) {
101
- // Check if we can find oldParts[i] in upcoming newParts
102
- for (let k = j + 1; k < Math.min(j + 5, newParts.length); k++) {
103
- if (newParts[k] === oldParts[i]) {
104
- // Mark everything from j to k-1 as added
105
- for (let m = j; m < k; m++) {
106
- right.push({
107
- value: newParts[m],
108
- type: DiffType.ADDED
109
- });
110
- }
111
- j = k;
112
- foundMatch = true;
113
- break;
114
- }
115
- }
116
- }
117
- if (!foundMatch) {
118
- // No match found nearby, mark as changed
119
- left.push({
120
- value: oldParts[i],
121
- type: DiffType.REMOVED
122
- });
123
- right.push({
124
- value: newParts[j],
125
- type: DiffType.ADDED
126
- });
127
- i++;
128
- j++;
129
- }
130
- }
131
- }
132
-
133
- // Handle remaining parts
134
- while (i < oldParts.length) {
135
- left.push({
136
- value: oldParts[i],
137
- type: DiffType.REMOVED
138
- });
139
- i++;
140
- }
141
- while (j < newParts.length) {
142
- right.push({
143
- value: newParts[j],
144
- type: DiffType.ADDED
145
- });
146
- j++;
147
- }
148
- return {
149
- left,
150
- right
151
- };
152
- }
153
-
154
- /**
155
- * Convert object to formatted JSON lines
156
- */
157
- function objectToLines(obj) {
158
- if (obj === null || obj === undefined) {
159
- return [String(obj)];
160
- }
161
- try {
162
- // Pretty print JSON with 2 space indentation
163
- const jsonStr = JSON.stringify(obj, null, 2);
164
- // Split into lines and filter out empty lines that appear between array elements
165
- const lines = jsonStr.split("\n");
166
-
167
- // Remove empty lines but keep structure
168
- const filteredLines = [];
169
- for (let i = 0; i < lines.length; i++) {
170
- const line = lines[i];
171
- const trimmed = line.trim();
172
-
173
- // Keep the line if it's not empty or if it's meaningful whitespace
174
- if (trimmed !== "") {
175
- filteredLines.push(line);
176
- } else if (i === 0 || i === lines.length - 1) {
177
- // Keep first and last empty lines if they exist (though they shouldn't)
178
- filteredLines.push(line);
179
- }
180
- // Skip other empty lines
181
- }
182
- return filteredLines;
183
- } catch {
184
- return [String(obj)];
185
- }
186
- }
187
- /**
188
- * Apply showDiffOnly filter with context lines
189
- */
190
- function filterDiffWithContext(diffs, contextLines) {
191
- if (contextLines < 0) return diffs;
192
- const result = [];
193
- const changedIndices = [];
194
-
195
- // Find all changed lines
196
- diffs.forEach((diff, idx) => {
197
- if (diff.type !== DiffType.DEFAULT) {
198
- changedIndices.push(idx);
199
- }
200
- });
201
-
202
- // If no changes, return empty
203
- if (changedIndices.length === 0) {
204
- return [];
205
- }
206
-
207
- // Build ranges to include
208
- const ranges = [];
209
- let currentStart = Math.max(0, changedIndices[0] - contextLines);
210
- let currentEnd = Math.min(diffs.length - 1, changedIndices[0] + contextLines);
211
- for (let i = 1; i < changedIndices.length; i++) {
212
- const idx = changedIndices[i];
213
- const rangeStart = Math.max(0, idx - contextLines);
214
- const rangeEnd = Math.min(diffs.length - 1, idx + contextLines);
215
-
216
- // If ranges overlap or are adjacent, merge them
217
- if (rangeStart <= currentEnd + 1) {
218
- currentEnd = Math.max(currentEnd, rangeEnd);
219
- } else {
220
- // Save current range and start a new one
221
- ranges.push([currentStart, currentEnd]);
222
- currentStart = rangeStart;
223
- currentEnd = rangeEnd;
224
- }
225
- }
226
-
227
- // Don't forget the last range
228
- ranges.push([currentStart, currentEnd]);
229
-
230
- // Build result from ranges
231
- ranges.forEach(([start, end]) => {
232
- for (let i = start; i <= end; i++) {
233
- result.push(diffs[i]);
234
- }
235
- });
236
- return result;
237
- }
238
-
239
- /**
240
- * Compare lines based on method
241
- */
242
- function compareLinesWithMethod(line1, line2, method) {
243
- switch (method) {
244
- case "trimmedLines":
245
- return line1.trim() === line2.trim();
246
- case "chars":
247
- case "words":
248
- case "lines":
249
- default:
250
- return line1 === line2;
11
+ });
12
+ Object.defineProperty(exports, "DiffType", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _dataViewer.DiffType;
251
16
  }
252
- }
253
-
254
- /**
255
- * Compute line-by-line diff between two objects
256
- */
257
- function computeLineDiff(oldValue, newValue, options = {}) {
258
- const {
259
- compareMethod = "words",
260
- disableWordDiff = false,
261
- showDiffOnly = false,
262
- contextLines = 3
263
- } = options;
264
- const oldLines = objectToLines(oldValue);
265
- const newLines = objectToLines(newValue);
266
- const result = [];
267
- let leftLineNum = 1;
268
- let rightLineNum = 1;
269
-
270
- // Simple line diff algorithm (can be improved with LCS)
271
- let i = 0,
272
- j = 0;
273
- while (i < oldLines.length || j < newLines.length) {
274
- if (i >= oldLines.length) {
275
- // Rest are additions
276
- result.push({
277
- rightLineNumber: rightLineNum++,
278
- type: DiffType.ADDED,
279
- rightContent: newLines[j],
280
- rightRaw: newLines[j]
281
- });
282
- j++;
283
- } else if (j >= newLines.length) {
284
- // Rest are removals
285
- result.push({
286
- leftLineNumber: leftLineNum++,
287
- type: DiffType.REMOVED,
288
- leftContent: oldLines[i],
289
- leftRaw: oldLines[i]
290
- });
291
- i++;
292
- } else if (compareLinesWithMethod(oldLines[i], newLines[j], compareMethod === "trimmedLines" ? "trimmedLines" : "lines")) {
293
- // Lines match (possibly after trimming if trimmedLines)
294
- result.push({
295
- leftLineNumber: leftLineNum++,
296
- rightLineNumber: rightLineNum++,
297
- type: DiffType.DEFAULT,
298
- leftContent: oldLines[i],
299
- rightContent: newLines[j],
300
- leftRaw: oldLines[i],
301
- rightRaw: newLines[j]
302
- });
303
- i++;
304
- j++;
305
- } else {
306
- // Lines differ - check if it's a modification or separate add/remove
307
- const oldTrimmed = oldLines[i].trim();
308
- const newTrimmed = newLines[j].trim();
309
-
310
- // Simple heuristic: if lines start similarly, treat as modification
311
- if (oldTrimmed && newTrimmed && (oldTrimmed.startsWith(newTrimmed.substring(0, 3)) || newTrimmed.startsWith(oldTrimmed.substring(0, 3)))) {
312
- // Treat as modification - compute word diff if enabled
313
- if (!disableWordDiff && compareMethod !== "lines") {
314
- const wordDiff = computeDiffByMethod(oldLines[i], newLines[j], compareMethod);
315
- result.push({
316
- leftLineNumber: leftLineNum++,
317
- rightLineNumber: rightLineNum++,
318
- type: DiffType.MODIFIED,
319
- leftContent: wordDiff.left,
320
- rightContent: wordDiff.right,
321
- leftRaw: oldLines[i],
322
- rightRaw: newLines[j]
323
- });
324
- } else {
325
- // No word diff - just mark lines as different
326
- result.push({
327
- leftLineNumber: leftLineNum++,
328
- rightLineNumber: rightLineNum++,
329
- type: DiffType.MODIFIED,
330
- leftContent: oldLines[i],
331
- rightContent: newLines[j],
332
- leftRaw: oldLines[i],
333
- rightRaw: newLines[j]
334
- });
335
- }
336
- i++;
337
- j++;
338
- } else {
339
- // Treat as separate remove and add
340
- result.push({
341
- leftLineNumber: leftLineNum++,
342
- type: DiffType.REMOVED,
343
- leftContent: oldLines[i],
344
- leftRaw: oldLines[i]
345
- });
346
- result.push({
347
- rightLineNumber: rightLineNum++,
348
- type: DiffType.ADDED,
349
- rightContent: newLines[j],
350
- rightRaw: newLines[j]
351
- });
352
- i++;
353
- j++;
354
- }
355
- }
17
+ });
18
+ Object.defineProperty(exports, "computeLineDiff", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _dataViewer.computeLineDiff;
356
22
  }
357
-
358
- // Apply showDiffOnly filter if enabled
359
- if (showDiffOnly) {
360
- return filterDiffWithContext(result, contextLines);
23
+ });
24
+ Object.defineProperty(exports, "isAbsent", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _dataViewer.isAbsent;
361
28
  }
362
- return result;
363
- }
29
+ });
30
+ var _dataViewer = require("@buoy-gg/shared-ui/dataViewer");