@buoy-gg/storage 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +607 -0
- package/lib/commonjs/index.js +34 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/preset.js +94 -0
- package/lib/commonjs/storage/components/DiffViewer/DiffOptionsPanel.js +356 -0
- package/lib/commonjs/storage/components/DiffViewer/TreeDiffViewer.js +29 -0
- package/lib/commonjs/storage/components/DiffViewer/components/DiffSummary.js +121 -0
- package/lib/commonjs/storage/components/DiffViewer/modes/ThemedSplitView.js +419 -0
- package/lib/commonjs/storage/components/DiffViewer/themes/diffThemes.js +122 -0
- package/lib/commonjs/storage/components/GameUIStorageBrowser.js +924 -0
- package/lib/commonjs/storage/components/GameUIStorageStats.js +746 -0
- package/lib/commonjs/storage/components/MMKVInstanceInfoPanel.js +257 -0
- package/lib/commonjs/storage/components/MMKVInstanceSelector.js +418 -0
- package/lib/commonjs/storage/components/SelectionActionBar.js +224 -0
- package/lib/commonjs/storage/components/StorageActionButtons.js +239 -0
- package/lib/commonjs/storage/components/StorageActions.js +192 -0
- package/lib/commonjs/storage/components/StorageBrowserMode.js +31 -0
- package/lib/commonjs/storage/components/StorageEventDetailContent.js +1025 -0
- package/lib/commonjs/storage/components/StorageEventFilterView.js +141 -0
- package/lib/commonjs/storage/components/StorageEventListener.js +357 -0
- package/lib/commonjs/storage/components/StorageEventsSection.js +24 -0
- package/lib/commonjs/storage/components/StorageFilterCards.js +345 -0
- package/lib/commonjs/storage/components/StorageFilterViewV2.js +42 -0
- package/lib/commonjs/storage/components/StorageKeyCard.js +516 -0
- package/lib/commonjs/storage/components/StorageKeyRow.js +356 -0
- package/lib/commonjs/storage/components/StorageKeySection.js +105 -0
- package/lib/commonjs/storage/components/StorageKeyStats.js +344 -0
- package/lib/commonjs/storage/components/StorageModalWithTabs.js +871 -0
- package/lib/commonjs/storage/components/StorageSection.js +43 -0
- package/lib/commonjs/storage/hooks/useAsyncStorageKeys.js +126 -0
- package/lib/commonjs/storage/hooks/useMMKVInstances.js +221 -0
- package/lib/commonjs/storage/hooks/useMMKVKeys.js +362 -0
- package/lib/commonjs/storage/hooks/useTickEverySecond.js +21 -0
- package/lib/commonjs/storage/index.js +148 -0
- package/lib/commonjs/storage/types.js +5 -0
- package/lib/commonjs/storage/utils/AsyncStorageListener.js +510 -0
- package/lib/commonjs/storage/utils/MMKVInstanceRegistry.js +202 -0
- package/lib/commonjs/storage/utils/MMKVListener.js +380 -0
- package/lib/commonjs/storage/utils/clearAllStorage.js +47 -0
- package/lib/commonjs/storage/utils/index.js +180 -0
- package/lib/commonjs/storage/utils/lineDiff.js +363 -0
- package/lib/commonjs/storage/utils/mmkvAvailability.js +62 -0
- package/lib/commonjs/storage/utils/mmkvTypeDetection.js +139 -0
- package/lib/commonjs/storage/utils/objectDiff.js +157 -0
- package/lib/commonjs/storage/utils/safeAsyncStorage.js +140 -0
- package/lib/commonjs/storage/utils/storageActionHelpers.js +46 -0
- package/lib/commonjs/storage/utils/storageQueryUtils.js +35 -0
- package/lib/commonjs/storage/utils/valueType.js +18 -0
- package/lib/module/index.js +7 -0
- package/lib/module/preset.js +89 -0
- package/lib/module/storage/components/DiffViewer/DiffOptionsPanel.js +352 -0
- package/lib/module/storage/components/DiffViewer/TreeDiffViewer.js +25 -0
- package/lib/module/storage/components/DiffViewer/components/DiffSummary.js +117 -0
- package/lib/module/storage/components/DiffViewer/modes/ThemedSplitView.js +415 -0
- package/lib/module/storage/components/DiffViewer/themes/diffThemes.js +118 -0
- package/lib/module/storage/components/GameUIStorageBrowser.js +922 -0
- package/lib/module/storage/components/GameUIStorageStats.js +742 -0
- package/lib/module/storage/components/MMKVInstanceInfoPanel.js +253 -0
- package/lib/module/storage/components/MMKVInstanceSelector.js +414 -0
- package/lib/module/storage/components/SelectionActionBar.js +221 -0
- package/lib/module/storage/components/StorageActionButtons.js +236 -0
- package/lib/module/storage/components/StorageActions.js +189 -0
- package/lib/module/storage/components/StorageBrowserMode.js +27 -0
- package/lib/module/storage/components/StorageEventDetailContent.js +1020 -0
- package/lib/module/storage/components/StorageEventFilterView.js +137 -0
- package/lib/module/storage/components/StorageEventListener.js +354 -0
- package/lib/module/storage/components/StorageEventsSection.js +20 -0
- package/lib/module/storage/components/StorageFilterCards.js +341 -0
- package/lib/module/storage/components/StorageFilterViewV2.js +38 -0
- package/lib/module/storage/components/StorageKeyCard.js +513 -0
- package/lib/module/storage/components/StorageKeyRow.js +353 -0
- package/lib/module/storage/components/StorageKeySection.js +101 -0
- package/lib/module/storage/components/StorageKeyStats.js +340 -0
- package/lib/module/storage/components/StorageModalWithTabs.js +867 -0
- package/lib/module/storage/components/StorageSection.js +40 -0
- package/lib/module/storage/hooks/useAsyncStorageKeys.js +121 -0
- package/lib/module/storage/hooks/useMMKVInstances.js +216 -0
- package/lib/module/storage/hooks/useMMKVKeys.js +359 -0
- package/lib/module/storage/hooks/useTickEverySecond.js +18 -0
- package/lib/module/storage/index.js +25 -0
- package/lib/module/storage/types.js +3 -0
- package/lib/module/storage/utils/AsyncStorageListener.js +500 -0
- package/lib/module/storage/utils/MMKVInstanceRegistry.js +196 -0
- package/lib/module/storage/utils/MMKVListener.js +367 -0
- package/lib/module/storage/utils/clearAllStorage.js +42 -0
- package/lib/module/storage/utils/index.js +22 -0
- package/lib/module/storage/utils/lineDiff.js +359 -0
- package/lib/module/storage/utils/mmkvAvailability.js +56 -0
- package/lib/module/storage/utils/mmkvTypeDetection.js +133 -0
- package/lib/module/storage/utils/objectDiff.js +153 -0
- package/lib/module/storage/utils/safeAsyncStorage.js +134 -0
- package/lib/module/storage/utils/storageActionHelpers.js +42 -0
- package/lib/module/storage/utils/storageQueryUtils.js +30 -0
- package/lib/module/storage/utils/valueType.js +14 -0
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/preset.d.ts +90 -0
- package/lib/typescript/preset.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts +18 -0
- package/lib/typescript/storage/components/DiffViewer/DiffOptionsPanel.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts +7 -0
- package/lib/typescript/storage/components/DiffViewer/TreeDiffViewer.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts +12 -0
- package/lib/typescript/storage/components/DiffViewer/components/DiffSummary.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts +13 -0
- package/lib/typescript/storage/components/DiffViewer/modes/ThemedSplitView.d.ts.map +1 -0
- package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts +64 -0
- package/lib/typescript/storage/components/DiffViewer/themes/diffThemes.d.ts.map +1 -0
- package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts +16 -0
- package/lib/typescript/storage/components/GameUIStorageBrowser.d.ts.map +1 -0
- package/lib/typescript/storage/components/GameUIStorageStats.d.ts +7 -0
- package/lib/typescript/storage/components/GameUIStorageStats.d.ts.map +1 -0
- package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts +42 -0
- package/lib/typescript/storage/components/MMKVInstanceInfoPanel.d.ts.map +1 -0
- package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts +35 -0
- package/lib/typescript/storage/components/MMKVInstanceSelector.d.ts.map +1 -0
- package/lib/typescript/storage/components/SelectionActionBar.d.ts +21 -0
- package/lib/typescript/storage/components/SelectionActionBar.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageActionButtons.d.ts +21 -0
- package/lib/typescript/storage/components/StorageActionButtons.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageActions.d.ts +10 -0
- package/lib/typescript/storage/components/StorageActions.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageBrowserMode.d.ts +18 -0
- package/lib/typescript/storage/components/StorageBrowserMode.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts +40 -0
- package/lib/typescript/storage/components/StorageEventDetailContent.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageEventFilterView.d.ts +11 -0
- package/lib/typescript/storage/components/StorageEventFilterView.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageEventListener.d.ts +6 -0
- package/lib/typescript/storage/components/StorageEventListener.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageEventsSection.d.ts +7 -0
- package/lib/typescript/storage/components/StorageEventsSection.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageFilterCards.d.ts +36 -0
- package/lib/typescript/storage/components/StorageFilterCards.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageFilterViewV2.d.ts +9 -0
- package/lib/typescript/storage/components/StorageFilterViewV2.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeyCard.d.ts +17 -0
- package/lib/typescript/storage/components/StorageKeyCard.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeyRow.d.ts +15 -0
- package/lib/typescript/storage/components/StorageKeyRow.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeySection.d.ts +25 -0
- package/lib/typescript/storage/components/StorageKeySection.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageKeyStats.d.ts +15 -0
- package/lib/typescript/storage/components/StorageKeyStats.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts +13 -0
- package/lib/typescript/storage/components/StorageModalWithTabs.d.ts.map +1 -0
- package/lib/typescript/storage/components/StorageSection.d.ts +10 -0
- package/lib/typescript/storage/components/StorageSection.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts +10 -0
- package/lib/typescript/storage/hooks/useAsyncStorageKeys.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useMMKVInstances.d.ts +114 -0
- package/lib/typescript/storage/hooks/useMMKVInstances.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useMMKVKeys.d.ts +94 -0
- package/lib/typescript/storage/hooks/useMMKVKeys.d.ts.map +1 -0
- package/lib/typescript/storage/hooks/useTickEverySecond.d.ts +6 -0
- package/lib/typescript/storage/hooks/useTickEverySecond.d.ts.map +1 -0
- package/lib/typescript/storage/index.d.ts +15 -0
- package/lib/typescript/storage/index.d.ts.map +1 -0
- package/lib/typescript/storage/types.d.ts +41 -0
- package/lib/typescript/storage/types.d.ts.map +1 -0
- package/lib/typescript/storage/utils/AsyncStorageListener.d.ts +195 -0
- package/lib/typescript/storage/utils/AsyncStorageListener.d.ts.map +1 -0
- package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts +224 -0
- package/lib/typescript/storage/utils/MMKVInstanceRegistry.d.ts.map +1 -0
- package/lib/typescript/storage/utils/MMKVListener.d.ts +218 -0
- package/lib/typescript/storage/utils/MMKVListener.d.ts.map +1 -0
- package/lib/typescript/storage/utils/clearAllStorage.d.ts +11 -0
- package/lib/typescript/storage/utils/clearAllStorage.d.ts.map +1 -0
- package/lib/typescript/storage/utils/index.d.ts +8 -0
- package/lib/typescript/storage/utils/index.d.ts.map +1 -0
- package/lib/typescript/storage/utils/lineDiff.d.ts +34 -0
- package/lib/typescript/storage/utils/lineDiff.d.ts.map +1 -0
- package/lib/typescript/storage/utils/mmkvAvailability.d.ts +23 -0
- package/lib/typescript/storage/utils/mmkvAvailability.d.ts.map +1 -0
- package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts +71 -0
- package/lib/typescript/storage/utils/mmkvTypeDetection.d.ts.map +1 -0
- package/lib/typescript/storage/utils/objectDiff.d.ts +35 -0
- package/lib/typescript/storage/utils/objectDiff.d.ts.map +1 -0
- package/lib/typescript/storage/utils/safeAsyncStorage.d.ts +56 -0
- package/lib/typescript/storage/utils/safeAsyncStorage.d.ts.map +1 -0
- package/lib/typescript/storage/utils/storageActionHelpers.d.ts +5 -0
- package/lib/typescript/storage/utils/storageActionHelpers.d.ts.map +1 -0
- package/lib/typescript/storage/utils/storageQueryUtils.d.ts +6 -0
- package/lib/typescript/storage/utils/storageQueryUtils.d.ts.map +1 -0
- package/lib/typescript/storage/utils/valueType.d.ts +3 -0
- package/lib/typescript/storage/utils/valueType.d.ts.map +1 -0
- package/package.json +68 -0
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
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
|
+
};
|
|
59
|
+
}
|
|
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;
|
|
251
|
+
}
|
|
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
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Apply showDiffOnly filter if enabled
|
|
359
|
+
if (showDiffOnly) {
|
|
360
|
+
return filterDiffWithContext(result, contextLines);
|
|
361
|
+
}
|
|
362
|
+
return result;
|
|
363
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getMMKVClass = getMMKVClass;
|
|
7
|
+
exports.getMMKVUnavailableMessage = getMMKVUnavailableMessage;
|
|
8
|
+
exports.isMMKVAvailable = isMMKVAvailable;
|
|
9
|
+
/**
|
|
10
|
+
* MMKV Availability Detection
|
|
11
|
+
*
|
|
12
|
+
* Safely detects if react-native-mmkv is available in the current environment.
|
|
13
|
+
* This allows the app to work in Expo Go where native modules aren't available.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
let _isMMKVAvailable = null;
|
|
17
|
+
let _MMKVClass = null;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Check if MMKV is available in the current environment
|
|
21
|
+
*
|
|
22
|
+
* @returns True if react-native-mmkv is installed and available
|
|
23
|
+
*/
|
|
24
|
+
function isMMKVAvailable() {
|
|
25
|
+
// Cache the result after first check
|
|
26
|
+
if (_isMMKVAvailable !== null) {
|
|
27
|
+
return _isMMKVAvailable;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
// Attempt to require MMKV
|
|
31
|
+
const MMKVModule = require('react-native-mmkv');
|
|
32
|
+
|
|
33
|
+
// v4 uses createMMKV factory function, v3 used MMKV class
|
|
34
|
+
// Try v4 API first (recommended), fall back to v3
|
|
35
|
+
_MMKVClass = MMKVModule.createMMKV || MMKVModule.MMKV;
|
|
36
|
+
_isMMKVAvailable = _MMKVClass !== undefined;
|
|
37
|
+
return _isMMKVAvailable;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
// MMKV is not available (e.g., Expo Go, not installed)
|
|
40
|
+
_isMMKVAvailable = false;
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get the MMKV class if available
|
|
47
|
+
*
|
|
48
|
+
* @returns MMKV class or null if not available
|
|
49
|
+
*/
|
|
50
|
+
function getMMKVClass() {
|
|
51
|
+
if (!isMMKVAvailable()) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return _MMKVClass;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get a user-friendly error message when MMKV is not available
|
|
59
|
+
*/
|
|
60
|
+
function getMMKVUnavailableMessage() {
|
|
61
|
+
return 'MMKV is not available in this environment. MMKV requires native modules and cannot run in Expo Go. Please use a development build or EAS Build.';
|
|
62
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.detectMMKVType = detectMMKVType;
|
|
7
|
+
exports.formatMMKVValue = formatMMKVValue;
|
|
8
|
+
exports.isTypeMatch = isTypeMatch;
|
|
9
|
+
/**
|
|
10
|
+
* MMKV Type Detection Utilities
|
|
11
|
+
*
|
|
12
|
+
* MMKV stores values with native types (string, number, boolean, ArrayBuffer).
|
|
13
|
+
* This module provides utilities to detect the type of a stored value by trying
|
|
14
|
+
* each getter sequentially.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// Use 'any' type for MMKV to avoid hard dependency on react-native-mmkv
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Detect the type of a value stored in MMKV by trying each getter.
|
|
21
|
+
*
|
|
22
|
+
* Since MMKV doesn't provide a getType() method, we must try each getter
|
|
23
|
+
* (getString, getNumber, getBoolean, getBuffer) until one returns a value.
|
|
24
|
+
*
|
|
25
|
+
* Order matters: We try in order of most common types first.
|
|
26
|
+
*
|
|
27
|
+
* @param instance - MMKV instance to read from
|
|
28
|
+
* @param key - Storage key
|
|
29
|
+
* @returns Value and its detected type
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const instance = createMMKV();
|
|
34
|
+
* instance.set('name', 'John');
|
|
35
|
+
* instance.set('age', 30);
|
|
36
|
+
* instance.set('active', true);
|
|
37
|
+
*
|
|
38
|
+
* detectMMKVType(instance, 'name'); // { value: 'John', type: 'string' }
|
|
39
|
+
* detectMMKVType(instance, 'age'); // { value: 30, type: 'number' }
|
|
40
|
+
* detectMMKVType(instance, 'active'); // { value: true, type: 'boolean' }
|
|
41
|
+
* detectMMKVType(instance, 'missing');// { value: undefined, type: 'unknown' }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
function detectMMKVType(instance, key) {
|
|
45
|
+
// Try string (most common)
|
|
46
|
+
const stringValue = instance.getString(key);
|
|
47
|
+
if (stringValue !== undefined) {
|
|
48
|
+
return {
|
|
49
|
+
value: stringValue,
|
|
50
|
+
type: 'string'
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Try number
|
|
55
|
+
const numberValue = instance.getNumber(key);
|
|
56
|
+
if (numberValue !== undefined) {
|
|
57
|
+
return {
|
|
58
|
+
value: numberValue,
|
|
59
|
+
type: 'number'
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Try boolean
|
|
64
|
+
const booleanValue = instance.getBoolean(key);
|
|
65
|
+
if (booleanValue !== undefined) {
|
|
66
|
+
return {
|
|
67
|
+
value: booleanValue,
|
|
68
|
+
type: 'boolean'
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Try buffer (least common)
|
|
73
|
+
const bufferValue = instance.getBuffer(key);
|
|
74
|
+
if (bufferValue !== undefined) {
|
|
75
|
+
// Format buffer for display (don't return raw ArrayBuffer)
|
|
76
|
+
return {
|
|
77
|
+
value: `<ArrayBuffer ${bufferValue.byteLength} bytes>`,
|
|
78
|
+
type: 'buffer'
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Key doesn't exist or unknown type
|
|
83
|
+
return {
|
|
84
|
+
value: undefined,
|
|
85
|
+
type: 'unknown'
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Format an MMKV value for display in the UI.
|
|
91
|
+
*
|
|
92
|
+
* @param value - The value to format
|
|
93
|
+
* @param type - The detected type
|
|
94
|
+
* @returns Formatted string representation
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* formatMMKVValue('hello', 'string'); // '"hello"'
|
|
99
|
+
* formatMMKVValue(42, 'number'); // '42'
|
|
100
|
+
* formatMMKVValue(true, 'boolean'); // 'true'
|
|
101
|
+
* formatMMKVValue('<ArrayBuffer 1024 bytes>', 'buffer'); // '<ArrayBuffer 1024 bytes>'
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
function formatMMKVValue(value, type) {
|
|
105
|
+
if (value === undefined) return 'undefined';
|
|
106
|
+
if (value === null) return 'null';
|
|
107
|
+
switch (type) {
|
|
108
|
+
case 'string':
|
|
109
|
+
return `"${value}"`;
|
|
110
|
+
case 'number':
|
|
111
|
+
return String(value);
|
|
112
|
+
case 'boolean':
|
|
113
|
+
return value ? 'true' : 'false';
|
|
114
|
+
case 'buffer':
|
|
115
|
+
// Value is already formatted as "<ArrayBuffer X bytes>"
|
|
116
|
+
return value;
|
|
117
|
+
case 'unknown':
|
|
118
|
+
return 'unknown';
|
|
119
|
+
default:
|
|
120
|
+
return String(value);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Check if a value type matches an expected type for validation.
|
|
126
|
+
*
|
|
127
|
+
* @param actualType - Detected type
|
|
128
|
+
* @param expectedType - Expected type from configuration
|
|
129
|
+
* @returns True if types match
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* ```typescript
|
|
133
|
+
* isTypeMatch('string', 'string'); // true
|
|
134
|
+
* isTypeMatch('number', 'string'); // false
|
|
135
|
+
* ```
|
|
136
|
+
*/
|
|
137
|
+
function isTypeMatch(actualType, expectedType) {
|
|
138
|
+
return actualType === expectedType;
|
|
139
|
+
}
|