react-native-nitro-storage 0.7.0 → 0.9.0
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/CHANGELOG.md +54 -0
- package/README.md +89 -22
- package/SECURITY.md +2 -2
- package/cpp/bindings/HybridStorage.cpp +5 -12
- package/cpp/bindings/HybridStorage.hpp +1 -1
- package/docs/api-reference.md +11 -1
- package/docs/batch-transactions-migrations.md +8 -2
- package/docs/benchmarks.md +19 -15
- package/docs/web-backends.md +18 -1
- package/ios/IOSStorageAdapterCpp.mm +162 -17
- package/lib/commonjs/capabilities.js +26 -0
- package/lib/commonjs/capabilities.js.map +1 -0
- package/lib/commonjs/core/durability.js +137 -0
- package/lib/commonjs/core/durability.js.map +1 -0
- package/lib/commonjs/core/metrics.js +91 -0
- package/lib/commonjs/core/metrics.js.map +1 -0
- package/lib/commonjs/index.js +47 -22
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +118 -66
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/indexeddb-backend.js +73 -23
- package/lib/commonjs/indexeddb-backend.js.map +1 -1
- package/lib/commonjs/internal.js +27 -4
- package/lib/commonjs/internal.js.map +1 -1
- package/lib/commonjs/shared.js +2 -2
- package/lib/commonjs/shared.js.map +1 -1
- package/lib/commonjs/storage-core.js +224 -237
- package/lib/commonjs/storage-core.js.map +1 -1
- package/lib/commonjs/storage-events.js.map +1 -1
- package/lib/commonjs/storage-platform.js +6 -0
- package/lib/commonjs/storage-platform.js.map +1 -0
- package/lib/commonjs/storage-runtime.js +3 -21
- package/lib/commonjs/storage-runtime.js.map +1 -1
- package/lib/commonjs/testing.js +19 -4
- package/lib/commonjs/testing.js.map +1 -1
- package/lib/commonjs/web-backend-contract.js +27 -0
- package/lib/commonjs/web-backend-contract.js.map +1 -0
- package/lib/module/capabilities.js +21 -0
- package/lib/module/capabilities.js.map +1 -0
- package/lib/module/core/durability.js +133 -0
- package/lib/module/core/durability.js.map +1 -0
- package/lib/module/core/metrics.js +87 -0
- package/lib/module/core/metrics.js.map +1 -0
- package/lib/module/index.js +48 -23
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +103 -64
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/indexeddb-backend.js +73 -23
- package/lib/module/indexeddb-backend.js.map +1 -1
- package/lib/module/internal.js +24 -3
- package/lib/module/internal.js.map +1 -1
- package/lib/module/shared.js +2 -2
- package/lib/module/shared.js.map +1 -1
- package/lib/module/storage-core.js +225 -238
- package/lib/module/storage-core.js.map +1 -1
- package/lib/module/storage-events.js.map +1 -1
- package/lib/module/storage-platform.js +4 -0
- package/lib/module/storage-platform.js.map +1 -0
- package/lib/module/storage-runtime.js +3 -21
- package/lib/module/storage-runtime.js.map +1 -1
- package/lib/module/testing.js +5 -3
- package/lib/module/testing.js.map +1 -1
- package/lib/module/web-backend-contract.js +22 -0
- package/lib/module/web-backend-contract.js.map +1 -0
- package/lib/typescript/capabilities.d.ts +11 -0
- package/lib/typescript/capabilities.d.ts.map +1 -0
- package/lib/typescript/core/durability.d.ts +27 -0
- package/lib/typescript/core/durability.d.ts.map +1 -0
- package/lib/typescript/core/metrics.d.ts +12 -0
- package/lib/typescript/core/metrics.d.ts.map +1 -0
- package/lib/typescript/index.d.ts +5 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +8 -4
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/indexeddb-backend.d.ts.map +1 -1
- package/lib/typescript/internal.d.ts +3 -0
- package/lib/typescript/internal.d.ts.map +1 -1
- package/lib/typescript/shared.d.ts +2 -1
- package/lib/typescript/shared.d.ts.map +1 -1
- package/lib/typescript/storage-core.d.ts +6 -6
- package/lib/typescript/storage-core.d.ts.map +1 -1
- package/lib/typescript/storage-events.d.ts +2 -2
- package/lib/typescript/storage-events.d.ts.map +1 -1
- package/lib/typescript/storage-platform.d.ts +12 -0
- package/lib/typescript/storage-platform.d.ts.map +1 -0
- package/lib/typescript/storage-runtime.d.ts.map +1 -1
- package/lib/typescript/testing.d.ts +5 -1
- package/lib/typescript/testing.d.ts.map +1 -1
- package/lib/typescript/web-backend-contract.d.ts +10 -0
- package/lib/typescript/web-backend-contract.d.ts.map +1 -0
- package/lib/typescript/web-storage-backend.d.ts +1 -1
- package/lib/typescript/web-storage-backend.d.ts.map +1 -1
- package/nitrogen/generated/shared/c++/HybridStorageSpec.hpp +1 -1
- package/package.json +4 -3
- package/react-native-nitro-storage.podspec +3 -1
- package/src/capabilities.ts +36 -0
- package/src/core/durability.ts +170 -0
- package/src/core/metrics.ts +133 -0
- package/src/index.ts +66 -40
- package/src/index.web.ts +158 -86
- package/src/indexeddb-backend.ts +91 -20
- package/src/internal.ts +50 -4
- package/src/shared.ts +7 -6
- package/src/storage-core.ts +327 -292
- package/src/storage-events.ts +2 -1
- package/src/storage-platform.ts +16 -0
- package/src/storage-runtime.ts +13 -47
- package/src/testing.ts +14 -7
- package/src/web-backend-contract.ts +34 -0
- package/src/web-storage-backend.ts +1 -1
|
@@ -4,10 +4,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.createStorageCore = createStorageCore;
|
|
7
|
-
var
|
|
8
|
-
var
|
|
7
|
+
var _durability = require("./core/durability");
|
|
8
|
+
var _metrics = require("./core/metrics");
|
|
9
9
|
var _internal = require("./internal");
|
|
10
|
+
var _shared = require("./shared");
|
|
10
11
|
var _storageEvents = require("./storage-events");
|
|
12
|
+
var _Storage = require("./Storage.types");
|
|
11
13
|
const EMPTY_KEYS = Object.freeze([]);
|
|
12
14
|
function asInternal(item) {
|
|
13
15
|
return item;
|
|
@@ -18,55 +20,38 @@ function createStorageCore(buildAdapter) {
|
|
|
18
20
|
const registeredKeyCounts = new Map();
|
|
19
21
|
const memoryStore = new Map();
|
|
20
22
|
const memoryListeners = new Map();
|
|
21
|
-
const scopedListeners =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
const scopedListeners = {
|
|
24
|
+
[_Storage.StorageScope.Disk]: new Map(),
|
|
25
|
+
[_Storage.StorageScope.Secure]: new Map()
|
|
26
|
+
};
|
|
27
|
+
const scopedRawCache = {
|
|
28
|
+
[_Storage.StorageScope.Disk]: new Map(),
|
|
29
|
+
[_Storage.StorageScope.Secure]: new Map()
|
|
30
|
+
};
|
|
28
31
|
let secureDefaultAccessControl = _Storage.AccessControl.WhenUnlocked;
|
|
29
|
-
let metricsObserver;
|
|
30
32
|
let eventObserver;
|
|
31
33
|
let eventObserverRedactSecureValues = true;
|
|
32
|
-
const metricsCounters = new Map();
|
|
33
34
|
const storageEvents = new _storageEvents.StorageEventRegistry();
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
scope,
|
|
50
|
-
durationMs,
|
|
51
|
-
keysCount
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
function measureOperation(operation, scope, fn, keysCount = 1) {
|
|
55
|
-
if (!metricsObserver) {
|
|
56
|
-
return fn();
|
|
57
|
-
}
|
|
58
|
-
const start = (0, _shared.now)();
|
|
59
|
-
try {
|
|
60
|
-
return fn();
|
|
61
|
-
} finally {
|
|
62
|
-
recordMetric(operation, scope, (0, _shared.now)() - start, keysCount);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
35
|
+
const metrics = (0, _metrics.createMetricsRegistry)();
|
|
36
|
+
const durability = (0, _durability.createDurabilityCoordinator)({
|
|
37
|
+
backend: {
|
|
38
|
+
setBatch: (keys, values, scope) => {
|
|
39
|
+
adapter.backend.setBatch(keys, values, scope);
|
|
40
|
+
},
|
|
41
|
+
removeBatch: (keys, scope) => {
|
|
42
|
+
adapter.backend.removeBatch(keys, scope);
|
|
43
|
+
},
|
|
44
|
+
setSecureAccessControl: level => {
|
|
45
|
+
adapter.backend.setSecureAccessControl(level);
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
resolveSecureDefaultAccessControl: () => secureDefaultAccessControl
|
|
49
|
+
});
|
|
65
50
|
function getScopedListeners(scope) {
|
|
66
|
-
return scopedListeners
|
|
51
|
+
return scopedListeners[scope];
|
|
67
52
|
}
|
|
68
53
|
function getScopeRawCache(scope) {
|
|
69
|
-
return scopedRawCache
|
|
54
|
+
return scopedRawCache[scope];
|
|
70
55
|
}
|
|
71
56
|
function cacheRawValue(scope, key, value) {
|
|
72
57
|
getScopeRawCache(scope).set(key, value);
|
|
@@ -98,7 +83,7 @@ function createStorageCore(buildAdapter) {
|
|
|
98
83
|
function getEventRawValue(scope, key) {
|
|
99
84
|
if (scope === _Storage.StorageScope.Memory) {
|
|
100
85
|
const value = memoryStore.get(key);
|
|
101
|
-
return typeof value === "string" ? value : undefined;
|
|
86
|
+
return typeof value === "string" ? (0, _internal.unescapeCollidingRawValue)(value) : undefined;
|
|
102
87
|
}
|
|
103
88
|
return getRawValue(key, scope);
|
|
104
89
|
}
|
|
@@ -144,118 +129,49 @@ function createStorageCore(buildAdapter) {
|
|
|
144
129
|
storageEvents.emitBatch(event);
|
|
145
130
|
eventObserver?.(eventForGlobalObserver(event));
|
|
146
131
|
}
|
|
132
|
+
function measureOperation(operation, scope, fn, keysCount = 1) {
|
|
133
|
+
return metrics.measure(operation, scope, fn, keysCount);
|
|
134
|
+
}
|
|
135
|
+
function recordMetric(operation, scope, durationMs, keysCount = 1) {
|
|
136
|
+
metrics.record(operation, scope, durationMs, keysCount);
|
|
137
|
+
}
|
|
147
138
|
function readPendingSecureWrite(key) {
|
|
148
|
-
return
|
|
139
|
+
return durability.readPendingSecureWrite(key);
|
|
149
140
|
}
|
|
150
141
|
function readPendingDiskWrite(key) {
|
|
151
|
-
return
|
|
142
|
+
return durability.readPendingDiskWrite(key);
|
|
152
143
|
}
|
|
153
144
|
function hasPendingDiskWrite(key) {
|
|
154
|
-
return
|
|
145
|
+
return durability.hasPendingDiskWrite(key);
|
|
155
146
|
}
|
|
156
147
|
function hasPendingSecureWrite(key) {
|
|
157
|
-
return
|
|
148
|
+
return durability.hasPendingSecureWrite(key);
|
|
158
149
|
}
|
|
159
150
|
function clearPendingDiskWrite(key) {
|
|
160
|
-
|
|
151
|
+
durability.clearPendingDiskWrite(key);
|
|
161
152
|
}
|
|
162
153
|
function clearPendingSecureWrite(key) {
|
|
163
|
-
|
|
154
|
+
durability.clearPendingSecureWrite(key);
|
|
164
155
|
}
|
|
165
156
|
function flushDiskWrites() {
|
|
166
|
-
|
|
167
|
-
if (pendingDiskWrites.size === 0) {
|
|
168
|
-
return;
|
|
169
|
-
}
|
|
170
|
-
const writes = Array.from(pendingDiskWrites.values());
|
|
171
|
-
pendingDiskWrites.clear();
|
|
172
|
-
const keysToSet = [];
|
|
173
|
-
const valuesToSet = [];
|
|
174
|
-
const keysToRemove = [];
|
|
175
|
-
writes.forEach(({
|
|
176
|
-
key,
|
|
177
|
-
value
|
|
178
|
-
}) => {
|
|
179
|
-
if (value === undefined) {
|
|
180
|
-
keysToRemove.push(key);
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
183
|
-
keysToSet.push(key);
|
|
184
|
-
valuesToSet.push(value);
|
|
185
|
-
});
|
|
186
|
-
if (keysToSet.length > 0) {
|
|
187
|
-
adapter.backend.setBatch(keysToSet, valuesToSet, _Storage.StorageScope.Disk);
|
|
188
|
-
}
|
|
189
|
-
if (keysToRemove.length > 0) {
|
|
190
|
-
adapter.backend.removeBatch(keysToRemove, _Storage.StorageScope.Disk);
|
|
191
|
-
}
|
|
157
|
+
durability.flushDiskWrites();
|
|
192
158
|
}
|
|
193
159
|
function flushSecureWrites() {
|
|
194
|
-
|
|
195
|
-
if (pendingSecureWrites.size === 0) {
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
const writes = Array.from(pendingSecureWrites.values());
|
|
199
|
-
pendingSecureWrites.clear();
|
|
200
|
-
const groupedSetWrites = new Map();
|
|
201
|
-
const keysToRemove = [];
|
|
202
|
-
writes.forEach(({
|
|
203
|
-
key,
|
|
204
|
-
value,
|
|
205
|
-
accessControl
|
|
206
|
-
}) => {
|
|
207
|
-
if (value === undefined) {
|
|
208
|
-
keysToRemove.push(key);
|
|
209
|
-
} else {
|
|
210
|
-
const resolvedAccessControl = accessControl ?? secureDefaultAccessControl;
|
|
211
|
-
const existingGroup = groupedSetWrites.get(resolvedAccessControl);
|
|
212
|
-
const group = existingGroup ?? {
|
|
213
|
-
keys: [],
|
|
214
|
-
values: []
|
|
215
|
-
};
|
|
216
|
-
group.keys.push(key);
|
|
217
|
-
group.values.push(value);
|
|
218
|
-
if (!existingGroup) {
|
|
219
|
-
groupedSetWrites.set(resolvedAccessControl, group);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
});
|
|
223
|
-
groupedSetWrites.forEach((group, accessControl) => {
|
|
224
|
-
adapter.backend.setSecureAccessControl(accessControl);
|
|
225
|
-
adapter.backend.setBatch(group.keys, group.values, _Storage.StorageScope.Secure);
|
|
226
|
-
});
|
|
227
|
-
if (keysToRemove.length > 0) {
|
|
228
|
-
adapter.backend.removeBatch(keysToRemove, _Storage.StorageScope.Secure);
|
|
229
|
-
}
|
|
160
|
+
durability.flushSecureWrites();
|
|
230
161
|
}
|
|
231
162
|
function scheduleDiskWrite(key, value) {
|
|
232
|
-
|
|
233
|
-
key,
|
|
234
|
-
value
|
|
235
|
-
});
|
|
236
|
-
if (diskFlushScheduled) {
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
diskFlushScheduled = true;
|
|
240
|
-
(0, _shared.runMicrotask)(flushDiskWrites);
|
|
163
|
+
durability.scheduleDiskWrite(key, value);
|
|
241
164
|
}
|
|
242
165
|
function scheduleSecureWrite(key, value, accessControl) {
|
|
243
|
-
|
|
244
|
-
key,
|
|
245
|
-
value
|
|
246
|
-
};
|
|
247
|
-
if (accessControl !== undefined) {
|
|
248
|
-
pendingWrite.accessControl = accessControl;
|
|
249
|
-
}
|
|
250
|
-
pendingSecureWrites.set(key, pendingWrite);
|
|
251
|
-
if (secureFlushScheduled) {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
secureFlushScheduled = true;
|
|
255
|
-
(0, _shared.runMicrotask)(flushSecureWrites);
|
|
166
|
+
durability.scheduleSecureWrite(key, value, accessControl);
|
|
256
167
|
}
|
|
257
|
-
function
|
|
258
|
-
|
|
168
|
+
function setDiskWritesAsyncMode(enabled) {
|
|
169
|
+
durability.setDiskWritesAsync(enabled);
|
|
170
|
+
}
|
|
171
|
+
function isDiskWritesAsync() {
|
|
172
|
+
return durability.isDiskWritesAsync();
|
|
173
|
+
}
|
|
174
|
+
function getStoredRawValue(key, scope) {
|
|
259
175
|
if (scope === _Storage.StorageScope.Memory) {
|
|
260
176
|
const value = memoryStore.get(key);
|
|
261
177
|
return typeof value === "string" ? value : undefined;
|
|
@@ -268,19 +184,37 @@ function createStorageCore(buildAdapter) {
|
|
|
268
184
|
}
|
|
269
185
|
return adapter.backend.get(key, scope);
|
|
270
186
|
}
|
|
187
|
+
function getRawValue(key, scope) {
|
|
188
|
+
(0, _internal.assertValidScope)(scope);
|
|
189
|
+
if (scope === _Storage.StorageScope.Memory) {
|
|
190
|
+
const value = memoryStore.get(key);
|
|
191
|
+
return typeof value === "string" ? (0, _internal.unescapeCollidingRawValue)(value) : undefined;
|
|
192
|
+
}
|
|
193
|
+
if (scope === _Storage.StorageScope.Disk && hasPendingDiskWrite(key)) {
|
|
194
|
+
const pending = readPendingDiskWrite(key);
|
|
195
|
+
return pending === undefined ? undefined : (0, _internal.unescapeCollidingRawValue)(pending);
|
|
196
|
+
}
|
|
197
|
+
if (scope === _Storage.StorageScope.Secure && hasPendingSecureWrite(key)) {
|
|
198
|
+
const pending = readPendingSecureWrite(key);
|
|
199
|
+
return pending === undefined ? undefined : (0, _internal.unescapeCollidingRawValue)(pending);
|
|
200
|
+
}
|
|
201
|
+
const raw = adapter.backend.get(key, scope);
|
|
202
|
+
return raw === undefined ? undefined : (0, _internal.unescapeCollidingRawValue)(raw);
|
|
203
|
+
}
|
|
271
204
|
function setRawValue(key, value, scope) {
|
|
272
205
|
(0, _internal.assertValidScope)(scope);
|
|
206
|
+
const storedValue = (0, _internal.escapeCollidingRawValue)(value);
|
|
273
207
|
const oldValue = scope === _Storage.StorageScope.Memory ? getEventRawValue(scope, key) : undefined;
|
|
274
208
|
if (scope === _Storage.StorageScope.Memory) {
|
|
275
|
-
memoryStore.set(key,
|
|
209
|
+
memoryStore.set(key, storedValue);
|
|
276
210
|
(0, _shared.notifyKeyListeners)(memoryListeners, key);
|
|
277
211
|
emitKeyChange(scope, key, oldValue, value, "set", "memory");
|
|
278
212
|
return;
|
|
279
213
|
}
|
|
280
214
|
if (scope === _Storage.StorageScope.Disk) {
|
|
281
|
-
cacheRawValue(scope, key,
|
|
282
|
-
if (
|
|
283
|
-
scheduleDiskWrite(key,
|
|
215
|
+
cacheRawValue(scope, key, storedValue);
|
|
216
|
+
if (isDiskWritesAsync()) {
|
|
217
|
+
scheduleDiskWrite(key, storedValue);
|
|
284
218
|
emitKeyChange(scope, key, oldValue, value, "set", adapter.changeSource);
|
|
285
219
|
return;
|
|
286
220
|
}
|
|
@@ -294,8 +228,8 @@ function createStorageCore(buildAdapter) {
|
|
|
294
228
|
adapter.backend.setSecureAccessControl(secureDefaultAccessControl);
|
|
295
229
|
}
|
|
296
230
|
}
|
|
297
|
-
adapter.backend.set(key,
|
|
298
|
-
cacheRawValue(scope, key,
|
|
231
|
+
adapter.backend.set(key, storedValue, scope);
|
|
232
|
+
cacheRawValue(scope, key, storedValue);
|
|
299
233
|
emitKeyChange(scope, key, oldValue, value, "set", adapter.changeSource);
|
|
300
234
|
}
|
|
301
235
|
function removeRawValue(key, scope) {
|
|
@@ -309,7 +243,7 @@ function createStorageCore(buildAdapter) {
|
|
|
309
243
|
}
|
|
310
244
|
if (scope === _Storage.StorageScope.Disk) {
|
|
311
245
|
cacheRawValue(scope, key, undefined);
|
|
312
|
-
if (
|
|
246
|
+
if (isDiskWritesAsync()) {
|
|
313
247
|
scheduleDiskWrite(key, undefined);
|
|
314
248
|
emitKeyChange(scope, key, oldValue, undefined, "remove", adapter.changeSource);
|
|
315
249
|
return;
|
|
@@ -333,9 +267,6 @@ function createStorageCore(buildAdapter) {
|
|
|
333
267
|
const parsed = Number.parseInt(raw, 10);
|
|
334
268
|
return Number.isFinite(parsed) && parsed > 0 ? parsed : 0;
|
|
335
269
|
}
|
|
336
|
-
function writeMigrationVersion(scope, version) {
|
|
337
|
-
setRawValue(_internal.MIGRATION_VERSION_KEY, String(version), scope);
|
|
338
|
-
}
|
|
339
270
|
const internals = {
|
|
340
271
|
getScopedListeners,
|
|
341
272
|
cacheRawValue,
|
|
@@ -344,10 +275,10 @@ function createStorageCore(buildAdapter) {
|
|
|
344
275
|
clearPendingDiskWrite,
|
|
345
276
|
clearPendingSecureWrite,
|
|
346
277
|
clearAllPendingDiskWrites: () => {
|
|
347
|
-
|
|
278
|
+
durability.clearAllPendingDiskWrites();
|
|
348
279
|
},
|
|
349
280
|
clearAllPendingSecureWrites: () => {
|
|
350
|
-
|
|
281
|
+
durability.clearAllPendingSecureWrites();
|
|
351
282
|
},
|
|
352
283
|
flushDiskWrites,
|
|
353
284
|
flushSecureWrites,
|
|
@@ -376,7 +307,9 @@ function createStorageCore(buildAdapter) {
|
|
|
376
307
|
}
|
|
377
308
|
const previousValues = shouldReadPreviousEventValues(scope) ? removeKeys.map(key => getEventRawValue(scope, key)) : [];
|
|
378
309
|
removeKeys.forEach(key => memoryStore.delete(key));
|
|
379
|
-
removeKeys.forEach(key =>
|
|
310
|
+
removeKeys.forEach(key => {
|
|
311
|
+
(0, _shared.notifyKeyListeners)(memoryListeners, key);
|
|
312
|
+
});
|
|
380
313
|
emitBatchChange(scope, "clear", "memory", removeKeys.map((key, index) => (0, _shared.createKeyChange)(scope, key, previousValues[index], undefined, "clear", "memory")));
|
|
381
314
|
return;
|
|
382
315
|
}
|
|
@@ -390,9 +323,11 @@ function createStorageCore(buildAdapter) {
|
|
|
390
323
|
if (removeKeys.length === 0) {
|
|
391
324
|
return;
|
|
392
325
|
}
|
|
393
|
-
const previousValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(removeKeys, scope) : [];
|
|
326
|
+
const previousValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(removeKeys, scope).map(value => value === undefined ? undefined : (0, _internal.unescapeCollidingRawValue)(value)) : [];
|
|
394
327
|
adapter.backend.removeBatch(removeKeys, scope);
|
|
395
|
-
removeKeys.forEach(key =>
|
|
328
|
+
removeKeys.forEach(key => {
|
|
329
|
+
cacheRawValue(scope, key, undefined);
|
|
330
|
+
});
|
|
396
331
|
emitBatchChange(scope, "clear", adapter.changeSource, removeKeys.map((key, index) => (0, _shared.createKeyChange)(scope, key, previousValues[index], undefined, "clear", adapter.changeSource)));
|
|
397
332
|
});
|
|
398
333
|
}
|
|
@@ -462,11 +397,11 @@ function createStorageCore(buildAdapter) {
|
|
|
462
397
|
}
|
|
463
398
|
if (scope === _Storage.StorageScope.Disk) {
|
|
464
399
|
flushDiskWrites();
|
|
465
|
-
|
|
400
|
+
durability.clearAllPendingDiskWrites();
|
|
466
401
|
}
|
|
467
402
|
if (scope === _Storage.StorageScope.Secure) {
|
|
468
403
|
flushSecureWrites();
|
|
469
|
-
|
|
404
|
+
durability.clearAllPendingSecureWrites();
|
|
470
405
|
}
|
|
471
406
|
clearScopeRawCache(scope);
|
|
472
407
|
adapter.backend.clear(scope);
|
|
@@ -560,7 +495,9 @@ function createStorageCore(buildAdapter) {
|
|
|
560
495
|
affectedKeys.forEach(key => {
|
|
561
496
|
memoryStore.delete(key);
|
|
562
497
|
});
|
|
563
|
-
affectedKeys.forEach(key =>
|
|
498
|
+
affectedKeys.forEach(key => {
|
|
499
|
+
(0, _shared.notifyKeyListeners)(memoryListeners, key);
|
|
500
|
+
});
|
|
564
501
|
emitBatchChange(scope, "clearNamespace", "memory", previousValues.map(({
|
|
565
502
|
key,
|
|
566
503
|
value
|
|
@@ -661,7 +598,7 @@ function createStorageCore(buildAdapter) {
|
|
|
661
598
|
keys.forEach((key, idx) => {
|
|
662
599
|
const value = values[idx];
|
|
663
600
|
if (value !== undefined) {
|
|
664
|
-
result[key] = value;
|
|
601
|
+
result[key] = (0, _internal.unescapeCollidingRawValue)(value);
|
|
665
602
|
}
|
|
666
603
|
});
|
|
667
604
|
return result;
|
|
@@ -674,7 +611,7 @@ function createStorageCore(buildAdapter) {
|
|
|
674
611
|
if (scope === _Storage.StorageScope.Memory) {
|
|
675
612
|
for (const key of memoryStore.keys()) {
|
|
676
613
|
const value = memoryStore.get(key);
|
|
677
|
-
if (typeof value === "string") result[key] = value;
|
|
614
|
+
if (typeof value === "string") result[key] = (0, _internal.unescapeCollidingRawValue)(value);
|
|
678
615
|
}
|
|
679
616
|
return result;
|
|
680
617
|
}
|
|
@@ -689,7 +626,7 @@ function createStorageCore(buildAdapter) {
|
|
|
689
626
|
const values = adapter.backend.getBatch(keys, scope);
|
|
690
627
|
keys.forEach((key, idx) => {
|
|
691
628
|
const val = values[idx];
|
|
692
|
-
if (val !== undefined) result[key] = val;
|
|
629
|
+
if (val !== undefined) result[key] = (0, _internal.unescapeCollidingRawValue)(val);
|
|
693
630
|
});
|
|
694
631
|
return result;
|
|
695
632
|
});
|
|
@@ -720,7 +657,7 @@ function createStorageCore(buildAdapter) {
|
|
|
720
657
|
},
|
|
721
658
|
setDiskWritesAsync: enabled => {
|
|
722
659
|
measureOperation("storage:setDiskWritesAsync", _Storage.StorageScope.Disk, () => {
|
|
723
|
-
|
|
660
|
+
setDiskWritesAsyncMode(enabled);
|
|
724
661
|
if (!enabled) {
|
|
725
662
|
flushDiskWrites();
|
|
726
663
|
}
|
|
@@ -737,22 +674,16 @@ function createStorageCore(buildAdapter) {
|
|
|
737
674
|
});
|
|
738
675
|
},
|
|
739
676
|
setMetricsObserver: observer => {
|
|
740
|
-
|
|
677
|
+
metrics.setObserver(observer);
|
|
741
678
|
},
|
|
742
679
|
getMetricsSnapshot: () => {
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
totalDurationMs: value.totalDurationMs,
|
|
748
|
-
avgDurationMs: value.count === 0 ? 0 : value.totalDurationMs / value.count,
|
|
749
|
-
maxDurationMs: value.maxDurationMs
|
|
750
|
-
};
|
|
751
|
-
});
|
|
752
|
-
return snapshot;
|
|
680
|
+
return metrics.getSnapshot();
|
|
681
|
+
},
|
|
682
|
+
getScopedMetricsSnapshot: () => {
|
|
683
|
+
return metrics.getScopedSnapshot();
|
|
753
684
|
},
|
|
754
685
|
resetMetrics: () => {
|
|
755
|
-
|
|
686
|
+
metrics.reset();
|
|
756
687
|
},
|
|
757
688
|
getSecureMetadata: key => {
|
|
758
689
|
return measureOperation("storage:getSecureMetadata", _Storage.StorageScope.Secure, () => {
|
|
@@ -803,12 +734,15 @@ function createStorageCore(buildAdapter) {
|
|
|
803
734
|
(0, _internal.assertValidScope)(scope);
|
|
804
735
|
if (keys.length === 0) return;
|
|
805
736
|
const values = keys.map(k => data[k]);
|
|
737
|
+
const storedValues = values.map(_internal.escapeCollidingRawValue);
|
|
806
738
|
const changes = keys.map((key, index) => (0, _shared.createKeyChange)(scope, key, getEventRawValue(scope, key), values[index], "import", scope === _Storage.StorageScope.Memory ? "memory" : adapter.changeSource));
|
|
807
739
|
if (scope === _Storage.StorageScope.Memory) {
|
|
808
740
|
keys.forEach((key, index) => {
|
|
809
|
-
memoryStore.set(key,
|
|
741
|
+
memoryStore.set(key, storedValues[index]);
|
|
742
|
+
});
|
|
743
|
+
keys.forEach(key => {
|
|
744
|
+
(0, _shared.notifyKeyListeners)(memoryListeners, key);
|
|
810
745
|
});
|
|
811
|
-
keys.forEach(key => (0, _shared.notifyKeyListeners)(memoryListeners, key));
|
|
812
746
|
emitBatchChange(scope, "import", "memory", changes);
|
|
813
747
|
return;
|
|
814
748
|
}
|
|
@@ -816,11 +750,13 @@ function createStorageCore(buildAdapter) {
|
|
|
816
750
|
flushSecureWrites();
|
|
817
751
|
adapter.backend.setSecureAccessControl(secureDefaultAccessControl);
|
|
818
752
|
}
|
|
819
|
-
if (scope === _Storage.StorageScope.Disk
|
|
753
|
+
if (scope === _Storage.StorageScope.Disk) {
|
|
820
754
|
flushDiskWrites();
|
|
821
755
|
}
|
|
822
|
-
adapter.backend.setBatch(keys,
|
|
823
|
-
keys.forEach((key, index) =>
|
|
756
|
+
adapter.backend.setBatch(keys, storedValues, scope);
|
|
757
|
+
keys.forEach((key, index) => {
|
|
758
|
+
cacheRawValue(scope, key, storedValues[index]);
|
|
759
|
+
});
|
|
824
760
|
emitBatchChange(scope, "import", adapter.changeSource, changes);
|
|
825
761
|
}, keys.length);
|
|
826
762
|
}
|
|
@@ -869,20 +805,28 @@ function createStorageCore(buildAdapter) {
|
|
|
869
805
|
hasLastValue = false;
|
|
870
806
|
lastExpiresAt = undefined;
|
|
871
807
|
};
|
|
808
|
+
const resolveNonMemoryScope = () => {
|
|
809
|
+
if (nonMemoryScope === null) {
|
|
810
|
+
throw new Error("NitroStorage: this operation requires Disk or Secure scope.");
|
|
811
|
+
}
|
|
812
|
+
return nonMemoryScope;
|
|
813
|
+
};
|
|
872
814
|
const ensureSubscription = () => {
|
|
873
815
|
if (unsubscribe) {
|
|
874
816
|
return;
|
|
875
817
|
}
|
|
876
818
|
const listener = () => {
|
|
877
819
|
invalidateParsedCache();
|
|
878
|
-
listeners.forEach(callback =>
|
|
820
|
+
listeners.forEach(callback => {
|
|
821
|
+
callback();
|
|
822
|
+
});
|
|
879
823
|
};
|
|
880
824
|
if (isMemory) {
|
|
881
825
|
unsubscribe = addKeyListener(memoryListeners, storageKey, listener);
|
|
882
826
|
return;
|
|
883
827
|
}
|
|
884
|
-
adapter.ensureScopeSubscription(
|
|
885
|
-
unsubscribe = addKeyListener(getScopedListeners(
|
|
828
|
+
adapter.ensureScopeSubscription(resolveNonMemoryScope());
|
|
829
|
+
unsubscribe = addKeyListener(getScopedListeners(resolveNonMemoryScope()), storageKey, listener);
|
|
886
830
|
};
|
|
887
831
|
const readStoredRaw = () => {
|
|
888
832
|
if (isMemory) {
|
|
@@ -893,28 +837,29 @@ function createStorageCore(buildAdapter) {
|
|
|
893
837
|
memoryExpiration.delete(storageKey);
|
|
894
838
|
memoryStore.delete(storageKey);
|
|
895
839
|
(0, _shared.notifyKeyListeners)(memoryListeners, storageKey);
|
|
896
|
-
emitKeyChange(config.scope, storageKey, typeof expiredRaw === "string" ? expiredRaw : undefined, undefined, "expire", "memory");
|
|
840
|
+
emitKeyChange(config.scope, storageKey, typeof expiredRaw === "string" ? (0, _internal.unescapeCollidingRawValue)(expiredRaw) : undefined, undefined, "expire", "memory");
|
|
897
841
|
onExpired?.(storageKey);
|
|
898
842
|
return undefined;
|
|
899
843
|
}
|
|
900
844
|
}
|
|
901
|
-
|
|
845
|
+
const memoryStored = memoryStore.get(storageKey);
|
|
846
|
+
return typeof memoryStored === "string" ? (0, _internal.unescapeCollidingRawValue)(memoryStored) : memoryStored;
|
|
902
847
|
}
|
|
903
848
|
migrateRenamesIfNeeded();
|
|
904
849
|
if (nonMemoryScope === _Storage.StorageScope.Disk) {
|
|
905
|
-
const pending =
|
|
850
|
+
const pending = durability.readPendingDiskWrite(storageKey);
|
|
906
851
|
if (pending !== undefined) {
|
|
907
|
-
return pending
|
|
852
|
+
return pending;
|
|
908
853
|
}
|
|
909
854
|
}
|
|
910
855
|
if (nonMemoryScope === _Storage.StorageScope.Secure && !isBiometric) {
|
|
911
|
-
const pending =
|
|
856
|
+
const pending = durability.readPendingSecureWrite(storageKey);
|
|
912
857
|
if (pending !== undefined) {
|
|
913
|
-
return pending
|
|
858
|
+
return pending;
|
|
914
859
|
}
|
|
915
860
|
}
|
|
916
861
|
if (readCache) {
|
|
917
|
-
const cache = getScopeRawCache(
|
|
862
|
+
const cache = getScopeRawCache(resolveNonMemoryScope());
|
|
918
863
|
const cached = cache.get(storageKey);
|
|
919
864
|
if (cached !== undefined || cache.has(storageKey)) {
|
|
920
865
|
return cached;
|
|
@@ -924,7 +869,7 @@ function createStorageCore(buildAdapter) {
|
|
|
924
869
|
return readBackendRaw(() => adapter.backend.getSecureBiometric(storageKey));
|
|
925
870
|
}
|
|
926
871
|
const raw = readBackendRaw(() => adapter.backend.get(storageKey, config.scope));
|
|
927
|
-
cacheRawValue(
|
|
872
|
+
cacheRawValue(resolveNonMemoryScope(), storageKey, raw);
|
|
928
873
|
return raw;
|
|
929
874
|
};
|
|
930
875
|
const readBackendRaw = read => {
|
|
@@ -933,7 +878,7 @@ function createStorageCore(buildAdapter) {
|
|
|
933
878
|
} catch (error) {
|
|
934
879
|
onReadError?.(error);
|
|
935
880
|
if (fallbackToCacheOnReadError) {
|
|
936
|
-
const cached = getScopeRawCache(
|
|
881
|
+
const cached = getScopeRawCache(resolveNonMemoryScope()).get(storageKey);
|
|
937
882
|
if (cached !== undefined) {
|
|
938
883
|
return cached;
|
|
939
884
|
}
|
|
@@ -949,9 +894,9 @@ function createStorageCore(buildAdapter) {
|
|
|
949
894
|
emitKeyChange(config.scope, storageKey, oldValue, rawValue, "set", adapter.changeSource);
|
|
950
895
|
return;
|
|
951
896
|
}
|
|
952
|
-
cacheRawValue(
|
|
897
|
+
cacheRawValue(resolveNonMemoryScope(), storageKey, rawValue);
|
|
953
898
|
if (nonMemoryScope === _Storage.StorageScope.Disk) {
|
|
954
|
-
if (coalesceDiskWrites ||
|
|
899
|
+
if (coalesceDiskWrites || isDiskWritesAsync()) {
|
|
955
900
|
scheduleDiskWrite(storageKey, rawValue);
|
|
956
901
|
emitKeyChange(config.scope, storageKey, oldValue, rawValue, "set", adapter.changeSource);
|
|
957
902
|
return;
|
|
@@ -1020,9 +965,9 @@ function createStorageCore(buildAdapter) {
|
|
|
1020
965
|
emitKeyChange(config.scope, storageKey, oldValue, undefined, operation, adapter.changeSource);
|
|
1021
966
|
return;
|
|
1022
967
|
}
|
|
1023
|
-
cacheRawValue(
|
|
968
|
+
cacheRawValue(resolveNonMemoryScope(), storageKey, undefined);
|
|
1024
969
|
if (nonMemoryScope === _Storage.StorageScope.Disk) {
|
|
1025
|
-
if (coalesceDiskWrites ||
|
|
970
|
+
if (coalesceDiskWrites || isDiskWritesAsync()) {
|
|
1026
971
|
scheduleDiskWrite(storageKey, undefined);
|
|
1027
972
|
emitKeyChange(config.scope, storageKey, oldValue, undefined, operation, adapter.changeSource);
|
|
1028
973
|
return;
|
|
@@ -1046,7 +991,8 @@ function createStorageCore(buildAdapter) {
|
|
|
1046
991
|
if (memoryExpiration) {
|
|
1047
992
|
memoryExpiration.set(storageKey, Date.now() + (expirationTtlMs ?? 0));
|
|
1048
993
|
}
|
|
1049
|
-
|
|
994
|
+
const storedValue = typeof value === "string" ? (0, _internal.escapeCollidingRawValue)(value) : value;
|
|
995
|
+
memoryStore.set(storageKey, storedValue);
|
|
1050
996
|
(0, _shared.notifyKeyListeners)(memoryListeners, storageKey);
|
|
1051
997
|
emitKeyChange(config.scope, storageKey, oldValue, typeof value === "string" ? value : undefined, "set", "memory");
|
|
1052
998
|
return;
|
|
@@ -1097,7 +1043,9 @@ function createStorageCore(buildAdapter) {
|
|
|
1097
1043
|
onExpired?.(storageKey);
|
|
1098
1044
|
lastValue = ensureValidatedValue(defaultValue, false);
|
|
1099
1045
|
hasLastValue = true;
|
|
1100
|
-
listeners.forEach(cb =>
|
|
1046
|
+
listeners.forEach(cb => {
|
|
1047
|
+
cb();
|
|
1048
|
+
});
|
|
1101
1049
|
return lastValue;
|
|
1102
1050
|
}
|
|
1103
1051
|
}
|
|
@@ -1133,7 +1081,9 @@ function createStorageCore(buildAdapter) {
|
|
|
1133
1081
|
onExpired?.(storageKey);
|
|
1134
1082
|
lastValue = ensureValidatedValue(defaultValue, false);
|
|
1135
1083
|
hasLastValue = true;
|
|
1136
|
-
listeners.forEach(cb =>
|
|
1084
|
+
listeners.forEach(cb => {
|
|
1085
|
+
cb();
|
|
1086
|
+
});
|
|
1137
1087
|
return lastValue;
|
|
1138
1088
|
}
|
|
1139
1089
|
deserializableRaw = parsed.payload;
|
|
@@ -1151,7 +1101,10 @@ function createStorageCore(buildAdapter) {
|
|
|
1151
1101
|
};
|
|
1152
1102
|
const getCurrentVersion = () => {
|
|
1153
1103
|
const raw = readStoredRaw();
|
|
1154
|
-
|
|
1104
|
+
if (raw === undefined) {
|
|
1105
|
+
return (0, _internal.toVersionToken)(undefined);
|
|
1106
|
+
}
|
|
1107
|
+
return (0, _internal.toVersionToken)(typeof raw === "string" ? (0, _internal.unescapeCollidingRawValue)(raw) : raw);
|
|
1155
1108
|
};
|
|
1156
1109
|
const get = () => measureOperation("item:get", config.scope, () => getInternal());
|
|
1157
1110
|
const getWithVersion = () => measureOperation("item:getWithVersion", config.scope, () => ({
|
|
@@ -1217,15 +1170,13 @@ function createStorageCore(buildAdapter) {
|
|
|
1217
1170
|
if (isMemory) return memoryStore.has(storageKey);
|
|
1218
1171
|
if (isBiometric) return adapter.backend.hasSecureBiometric(storageKey);
|
|
1219
1172
|
if (nonMemoryScope === _Storage.StorageScope.Disk) {
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
return pending.value !== undefined;
|
|
1173
|
+
if (durability.hasPendingDiskWrite(storageKey)) {
|
|
1174
|
+
return durability.readPendingDiskWrite(storageKey) !== undefined;
|
|
1223
1175
|
}
|
|
1224
1176
|
}
|
|
1225
1177
|
if (nonMemoryScope === _Storage.StorageScope.Secure) {
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
return pending.value !== undefined;
|
|
1178
|
+
if (durability.hasPendingSecureWrite(storageKey)) {
|
|
1179
|
+
return durability.readPendingSecureWrite(storageKey) !== undefined;
|
|
1229
1180
|
}
|
|
1230
1181
|
}
|
|
1231
1182
|
return adapter.backend.has(storageKey, config.scope);
|
|
@@ -1238,7 +1189,7 @@ function createStorageCore(buildAdapter) {
|
|
|
1238
1189
|
if (listeners.size === 0 && unsubscribe) {
|
|
1239
1190
|
unsubscribe();
|
|
1240
1191
|
if (!isMemory) {
|
|
1241
|
-
adapter.maybeCleanupScopeSubscription(
|
|
1192
|
+
adapter.maybeCleanupScopeSubscription(resolveNonMemoryScope());
|
|
1242
1193
|
}
|
|
1243
1194
|
unsubscribe = null;
|
|
1244
1195
|
}
|
|
@@ -1276,11 +1227,20 @@ function createStorageCore(buildAdapter) {
|
|
|
1276
1227
|
deserialize,
|
|
1277
1228
|
_triggerListeners: () => {
|
|
1278
1229
|
invalidateParsedCache();
|
|
1279
|
-
listeners.forEach(listener =>
|
|
1230
|
+
listeners.forEach(listener => {
|
|
1231
|
+
listener();
|
|
1232
|
+
});
|
|
1280
1233
|
},
|
|
1281
1234
|
_invalidateParsedCacheOnly: () => {
|
|
1282
1235
|
invalidateParsedCache();
|
|
1283
1236
|
},
|
|
1237
|
+
_deleteMemoryEntry: () => {
|
|
1238
|
+
if (memoryExpiration) {
|
|
1239
|
+
memoryExpiration.delete(storageKey);
|
|
1240
|
+
}
|
|
1241
|
+
memoryStore.delete(storageKey);
|
|
1242
|
+
invalidateParsedCache();
|
|
1243
|
+
},
|
|
1284
1244
|
_hasValidation: validate !== undefined,
|
|
1285
1245
|
_hasExpiration: expiration !== undefined,
|
|
1286
1246
|
_readCacheEnabled: readCache,
|
|
@@ -1323,16 +1283,16 @@ function createStorageCore(buildAdapter) {
|
|
|
1323
1283
|
const keyIndexes = [];
|
|
1324
1284
|
items.forEach((item, index) => {
|
|
1325
1285
|
if (scope === _Storage.StorageScope.Disk) {
|
|
1326
|
-
const pending =
|
|
1286
|
+
const pending = durability.readPendingDiskWrite(item.key);
|
|
1327
1287
|
if (pending !== undefined) {
|
|
1328
|
-
rawValues[index] = pending
|
|
1288
|
+
rawValues[index] = pending;
|
|
1329
1289
|
return;
|
|
1330
1290
|
}
|
|
1331
1291
|
}
|
|
1332
1292
|
if (scope === _Storage.StorageScope.Secure) {
|
|
1333
|
-
const pending =
|
|
1293
|
+
const pending = durability.readPendingSecureWrite(item.key);
|
|
1334
1294
|
if (pending !== undefined) {
|
|
1335
|
-
rawValues[index] = pending
|
|
1295
|
+
rawValues[index] = pending;
|
|
1336
1296
|
return;
|
|
1337
1297
|
}
|
|
1338
1298
|
}
|
|
@@ -1384,7 +1344,9 @@ function createStorageCore(buildAdapter) {
|
|
|
1384
1344
|
items.forEach(({
|
|
1385
1345
|
item,
|
|
1386
1346
|
value
|
|
1387
|
-
}) =>
|
|
1347
|
+
}) => {
|
|
1348
|
+
item.set(value);
|
|
1349
|
+
});
|
|
1388
1350
|
return;
|
|
1389
1351
|
}
|
|
1390
1352
|
const changes = items.map(({
|
|
@@ -1402,7 +1364,9 @@ function createStorageCore(buildAdapter) {
|
|
|
1402
1364
|
});
|
|
1403
1365
|
items.forEach(({
|
|
1404
1366
|
item
|
|
1405
|
-
}) =>
|
|
1367
|
+
}) => {
|
|
1368
|
+
(0, _shared.notifyKeyListeners)(memoryListeners, item.key);
|
|
1369
|
+
});
|
|
1406
1370
|
emitBatchChange(scope, "setBatch", "memory", changes);
|
|
1407
1371
|
return;
|
|
1408
1372
|
}
|
|
@@ -1422,14 +1386,16 @@ function createStorageCore(buildAdapter) {
|
|
|
1422
1386
|
items.forEach(({
|
|
1423
1387
|
item,
|
|
1424
1388
|
value
|
|
1425
|
-
}) =>
|
|
1389
|
+
}) => {
|
|
1390
|
+
item.set(value);
|
|
1391
|
+
});
|
|
1426
1392
|
return;
|
|
1427
1393
|
}
|
|
1428
1394
|
flushSecureWrites();
|
|
1429
1395
|
const keys = secureEntries.map(({
|
|
1430
1396
|
item
|
|
1431
1397
|
}) => item.key);
|
|
1432
|
-
const oldValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(keys, scope) : [];
|
|
1398
|
+
const oldValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(keys, scope).map(value => value === undefined ? undefined : (0, _internal.unescapeCollidingRawValue)(value)) : [];
|
|
1433
1399
|
const groupedByAccessControl = new Map();
|
|
1434
1400
|
secureEntries.forEach(({
|
|
1435
1401
|
item,
|
|
@@ -1451,7 +1417,9 @@ function createStorageCore(buildAdapter) {
|
|
|
1451
1417
|
groupedByAccessControl.forEach((group, accessControl) => {
|
|
1452
1418
|
adapter.backend.setSecureAccessControl(accessControl);
|
|
1453
1419
|
adapter.backend.setBatch(group.keys, group.values, scope);
|
|
1454
|
-
group.keys.forEach((key, index) =>
|
|
1420
|
+
group.keys.forEach((key, index) => {
|
|
1421
|
+
cacheRawValue(scope, key, group.values[index]);
|
|
1422
|
+
});
|
|
1455
1423
|
});
|
|
1456
1424
|
emitBatchChange(scope, "setBatch", adapter.changeSource, secureEntries.map(({
|
|
1457
1425
|
item,
|
|
@@ -1467,14 +1435,18 @@ function createStorageCore(buildAdapter) {
|
|
|
1467
1435
|
items.forEach(({
|
|
1468
1436
|
item,
|
|
1469
1437
|
value
|
|
1470
|
-
}) =>
|
|
1438
|
+
}) => {
|
|
1439
|
+
item.set(value);
|
|
1440
|
+
});
|
|
1471
1441
|
return;
|
|
1472
1442
|
}
|
|
1473
1443
|
const keys = items.map(entry => entry.item.key);
|
|
1474
1444
|
const values = items.map(entry => entry.item.serialize(entry.value));
|
|
1475
|
-
const oldValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(keys, scope) : [];
|
|
1445
|
+
const oldValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(keys, scope).map(value => value === undefined ? undefined : (0, _internal.unescapeCollidingRawValue)(value)) : [];
|
|
1476
1446
|
adapter.backend.setBatch(keys, values, scope);
|
|
1477
|
-
keys.forEach((key, index) =>
|
|
1447
|
+
keys.forEach((key, index) => {
|
|
1448
|
+
cacheRawValue(scope, key, values[index]);
|
|
1449
|
+
});
|
|
1478
1450
|
emitBatchChange(scope, "setBatch", adapter.changeSource, keys.map((key, index) => (0, _shared.createKeyChange)(scope, key, oldValues[index], values[index], "setBatch", adapter.changeSource)));
|
|
1479
1451
|
}, items.length);
|
|
1480
1452
|
}
|
|
@@ -1483,7 +1455,12 @@ function createStorageCore(buildAdapter) {
|
|
|
1483
1455
|
(0, _internal.assertBatchScope)(items, scope);
|
|
1484
1456
|
if (scope === _Storage.StorageScope.Memory) {
|
|
1485
1457
|
const changes = items.map(item => (0, _shared.createKeyChange)(scope, item.key, getEventRawValue(scope, item.key), undefined, "removeBatch", "memory"));
|
|
1486
|
-
items.forEach(item =>
|
|
1458
|
+
items.forEach(item => {
|
|
1459
|
+
asInternal(item)._deleteMemoryEntry();
|
|
1460
|
+
});
|
|
1461
|
+
items.forEach(item => {
|
|
1462
|
+
(0, _shared.notifyKeyListeners)(memoryListeners, item.key);
|
|
1463
|
+
});
|
|
1487
1464
|
emitBatchChange(scope, "removeBatch", "memory", changes);
|
|
1488
1465
|
return;
|
|
1489
1466
|
}
|
|
@@ -1494,9 +1471,11 @@ function createStorageCore(buildAdapter) {
|
|
|
1494
1471
|
if (scope === _Storage.StorageScope.Secure) {
|
|
1495
1472
|
flushSecureWrites();
|
|
1496
1473
|
}
|
|
1497
|
-
const oldValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(keys, scope) : [];
|
|
1474
|
+
const oldValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(keys, scope).map(value => value === undefined ? undefined : (0, _internal.unescapeCollidingRawValue)(value)) : [];
|
|
1498
1475
|
adapter.backend.removeBatch(keys, scope);
|
|
1499
|
-
keys.forEach(key =>
|
|
1476
|
+
keys.forEach(key => {
|
|
1477
|
+
cacheRawValue(scope, key, undefined);
|
|
1478
|
+
});
|
|
1500
1479
|
emitBatchChange(scope, "removeBatch", adapter.changeSource, keys.map((key, index) => (0, _shared.createKeyChange)(scope, key, oldValues[index], undefined, "removeBatch", adapter.changeSource)));
|
|
1501
1480
|
}, items.length);
|
|
1502
1481
|
}
|
|
@@ -1515,23 +1494,17 @@ function createStorageCore(buildAdapter) {
|
|
|
1515
1494
|
const currentVersion = readMigrationVersion(scope);
|
|
1516
1495
|
const versions = Array.from(registeredMigrations.keys()).filter(version => version > currentVersion).sort((a, b) => a - b);
|
|
1517
1496
|
let appliedVersion = currentVersion;
|
|
1518
|
-
const context = {
|
|
1519
|
-
scope,
|
|
1520
|
-
getRaw: key => getRawValue(key, scope),
|
|
1521
|
-
setRaw: (key, value) => setRawValue(key, value, scope),
|
|
1522
|
-
removeRaw: key => removeRawValue(key, scope)
|
|
1523
|
-
};
|
|
1524
1497
|
versions.forEach(version => {
|
|
1525
1498
|
const migration = registeredMigrations.get(version);
|
|
1526
1499
|
if (!migration) {
|
|
1527
1500
|
return;
|
|
1528
1501
|
}
|
|
1529
|
-
|
|
1502
|
+
runTransaction(scope, tx => {
|
|
1503
|
+
migration(tx);
|
|
1504
|
+
tx.setRaw(_internal.MIGRATION_VERSION_KEY, String(version));
|
|
1505
|
+
});
|
|
1530
1506
|
appliedVersion = version;
|
|
1531
1507
|
});
|
|
1532
|
-
if (appliedVersion !== currentVersion) {
|
|
1533
|
-
writeMigrationVersion(scope, appliedVersion);
|
|
1534
|
-
}
|
|
1535
1508
|
return appliedVersion;
|
|
1536
1509
|
});
|
|
1537
1510
|
}
|
|
@@ -1567,7 +1540,7 @@ function createStorageCore(buildAdapter) {
|
|
|
1567
1540
|
}
|
|
1568
1541
|
rollback.set(key, {
|
|
1569
1542
|
kind: "raw",
|
|
1570
|
-
value:
|
|
1543
|
+
value: getStoredRawValue(key, scope),
|
|
1571
1544
|
...(scope === _Storage.StorageScope.Secure && internal?._secureAccessControl !== undefined ? {
|
|
1572
1545
|
accessControl: internal._secureAccessControl
|
|
1573
1546
|
} : {})
|
|
@@ -1604,6 +1577,8 @@ function createStorageCore(buildAdapter) {
|
|
|
1604
1577
|
return transaction(tx);
|
|
1605
1578
|
} catch (error) {
|
|
1606
1579
|
const rollbackEntries = Array.from(rollback.entries()).reverse();
|
|
1580
|
+
const rollbackSource = scope === _Storage.StorageScope.Memory ? "memory" : adapter.changeSource;
|
|
1581
|
+
const preRollbackValues = rollbackEntries.length > 0 ? rollbackEntries.map(([key]) => getEventRawValue(scope, key)) : [];
|
|
1607
1582
|
if (scope === _Storage.StorageScope.Memory) {
|
|
1608
1583
|
rollbackEntries.forEach(([key, record]) => {
|
|
1609
1584
|
if (record.value === NOT_SET) {
|
|
@@ -1655,13 +1630,20 @@ function createStorageCore(buildAdapter) {
|
|
|
1655
1630
|
adapter.backend.setSecureAccessControl(accessControl);
|
|
1656
1631
|
}
|
|
1657
1632
|
adapter.backend.setBatch(group.keys, group.values, scope);
|
|
1658
|
-
group.keys.forEach((key, index) =>
|
|
1633
|
+
group.keys.forEach((key, index) => {
|
|
1634
|
+
cacheRawValue(scope, key, group.values[index]);
|
|
1635
|
+
});
|
|
1659
1636
|
});
|
|
1660
1637
|
if (keysToRemove.length > 0) {
|
|
1661
1638
|
adapter.backend.removeBatch(keysToRemove, scope);
|
|
1662
|
-
keysToRemove.forEach(key =>
|
|
1639
|
+
keysToRemove.forEach(key => {
|
|
1640
|
+
cacheRawValue(scope, key, undefined);
|
|
1641
|
+
});
|
|
1663
1642
|
}
|
|
1664
1643
|
}
|
|
1644
|
+
if (rollbackEntries.length > 0) {
|
|
1645
|
+
emitBatchChange(scope, "rollback", rollbackSource, rollbackEntries.map(([key], index) => (0, _shared.createKeyChange)(scope, key, preRollbackValues[index], getEventRawValue(scope, key), "rollback", rollbackSource)));
|
|
1646
|
+
}
|
|
1665
1647
|
throw error;
|
|
1666
1648
|
}
|
|
1667
1649
|
});
|
|
@@ -1739,12 +1721,15 @@ function createStorageCore(buildAdapter) {
|
|
|
1739
1721
|
});
|
|
1740
1722
|
const has = id => item.get()[id] === true;
|
|
1741
1723
|
const add = id => {
|
|
1742
|
-
|
|
1724
|
+
const current = item.get();
|
|
1725
|
+
if (current[id] === true) {
|
|
1743
1726
|
return;
|
|
1744
1727
|
}
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
}
|
|
1728
|
+
const next = {
|
|
1729
|
+
...current
|
|
1730
|
+
};
|
|
1731
|
+
next[id] = true;
|
|
1732
|
+
item.set(next);
|
|
1748
1733
|
};
|
|
1749
1734
|
const deleteId = id => {
|
|
1750
1735
|
const current = item.get();
|
|
@@ -1773,7 +1758,9 @@ function createStorageCore(buildAdapter) {
|
|
|
1773
1758
|
toggle,
|
|
1774
1759
|
values: () => Object.keys(item.get()),
|
|
1775
1760
|
size: () => Object.keys(item.get()).length,
|
|
1776
|
-
clear: () =>
|
|
1761
|
+
clear: () => {
|
|
1762
|
+
item.set({});
|
|
1763
|
+
},
|
|
1777
1764
|
reset: item.reset,
|
|
1778
1765
|
subscribe: item.subscribe,
|
|
1779
1766
|
scope: item.scope,
|