react-native-nitro-storage 0.5.9 → 0.6.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 +28 -0
- package/README.md +171 -7
- package/cpp/bindings/HybridStorage.cpp +25 -9
- package/cpp/bindings/HybridStorage.hpp +5 -0
- package/lib/commonjs/index.js +19 -2
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +19 -2
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/shared.js.map +1 -1
- package/lib/commonjs/storage-core.js +306 -10
- package/lib/commonjs/storage-core.js.map +1 -1
- package/lib/commonjs/storage-events.js.map +1 -1
- package/lib/commonjs/storage-hooks.js +16 -1
- package/lib/commonjs/storage-hooks.js.map +1 -1
- package/lib/commonjs/testing.js +267 -0
- package/lib/commonjs/testing.js.map +1 -0
- package/lib/module/index.js +5 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +5 -1
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/shared.js.map +1 -1
- package/lib/module/storage-core.js +307 -11
- package/lib/module/storage-core.js.map +1 -1
- package/lib/module/storage-events.js.map +1 -1
- package/lib/module/storage-hooks.js +15 -2
- package/lib/module/storage-hooks.js.map +1 -1
- package/lib/module/testing.js +188 -0
- package/lib/module/testing.js.map +1 -0
- package/lib/typescript/index.d.ts +22 -4
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +22 -4
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/shared.d.ts +1 -0
- package/lib/typescript/shared.d.ts.map +1 -1
- package/lib/typescript/storage-core.d.ts +51 -2
- package/lib/typescript/storage-core.d.ts.map +1 -1
- package/lib/typescript/storage-events.d.ts +1 -1
- package/lib/typescript/storage-events.d.ts.map +1 -1
- package/lib/typescript/storage-hooks.d.ts +18 -1
- package/lib/typescript/storage-hooks.d.ts.map +1 -1
- package/lib/typescript/testing.d.ts +148 -0
- package/lib/typescript/testing.d.ts.map +1 -0
- package/package.json +7 -1
- package/src/index.ts +16 -2
- package/src/index.web.ts +16 -2
- package/src/shared.ts +1 -0
- package/src/storage-core.ts +446 -11
- package/src/storage-events.ts +2 -0
- package/src/storage-hooks.ts +42 -3
- package/src/testing.ts +270 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_Storage","require","_internal","_storageRuntime","isUpdater","valueOrFn","typedKeys","record","Object","keys","assertEnumInteger","value","min","max","label","Number","isFinite","Error","Math","trunc","assertAccessControlLevel","level","assertBiometricLevel","runMicrotask","exports","queueMicrotask","task","Promise","resolve","then","now","performance","Date","notifyKeyListeners","registry","key","listeners","get","listener","notifyAllListeners","values","createKeyChange","scope","oldValue","newValue","operation","source","type","SECURE_EVENT_REDACTED_VALUE","redactSecureKeyChange","event","StorageScope","Secure","undefined","canUseRawBatchPath","item","_hasExpiration","_hasValidation","_isBiometric","_secureAccessControl","canUseSecureRawBatchPath","defaultSerialize","serializeWithPrimitiveFastPath","defaultDeserialize","deserializeWithPrimitiveFastPath","isKeychainLockedError","err","isLockedStorageErrorCode","getStorageErrorCode"],"sourceRoot":"../../src","sources":["shared.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"names":["_Storage","require","_internal","_storageRuntime","isUpdater","valueOrFn","typedKeys","record","Object","keys","assertEnumInteger","value","min","max","label","Number","isFinite","Error","Math","trunc","assertAccessControlLevel","level","assertBiometricLevel","runMicrotask","exports","queueMicrotask","task","Promise","resolve","then","now","performance","Date","notifyKeyListeners","registry","key","listeners","get","listener","notifyAllListeners","values","createKeyChange","scope","oldValue","newValue","operation","source","type","SECURE_EVENT_REDACTED_VALUE","redactSecureKeyChange","event","StorageScope","Secure","undefined","canUseRawBatchPath","item","_hasExpiration","_hasValidation","_isBiometric","_secureAccessControl","canUseSecureRawBatchPath","defaultSerialize","serializeWithPrimitiveFastPath","defaultDeserialize","deserializeWithPrimitiveFastPath","isKeychainLockedError","err","isLockedStorageErrorCode","getStorageErrorCode"],"sourceRoot":"../../src","sources":["shared.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -8,11 +8,14 @@ var _shared = require("./shared");
|
|
|
8
8
|
var _Storage = require("./Storage.types");
|
|
9
9
|
var _internal = require("./internal");
|
|
10
10
|
var _storageEvents = require("./storage-events");
|
|
11
|
+
const EMPTY_KEYS = Object.freeze([]);
|
|
11
12
|
function asInternal(item) {
|
|
12
13
|
return item;
|
|
13
14
|
}
|
|
14
15
|
function createStorageCore(buildAdapter) {
|
|
15
16
|
const registeredMigrations = new Map();
|
|
17
|
+
const itemGroups = new Map();
|
|
18
|
+
const registeredKeyCounts = new Map();
|
|
16
19
|
const memoryStore = new Map();
|
|
17
20
|
const memoryListeners = new Map();
|
|
18
21
|
const scopedListeners = new Map([[_Storage.StorageScope.Disk, new Map()], [_Storage.StorageScope.Secure, new Map()]]);
|
|
@@ -359,6 +362,40 @@ function createStorageCore(buildAdapter) {
|
|
|
359
362
|
}
|
|
360
363
|
};
|
|
361
364
|
const adapter = buildAdapter(internals);
|
|
365
|
+
function resolveKeyRef(ref) {
|
|
366
|
+
return typeof ref === "string" ? ref : ref.key;
|
|
367
|
+
}
|
|
368
|
+
function clearScopeExcept(scope, exceptRefs) {
|
|
369
|
+
measureOperation("storage:clearExcept", scope, () => {
|
|
370
|
+
(0, _internal.assertValidScope)(scope);
|
|
371
|
+
const keep = new Set(exceptRefs.map(resolveKeyRef));
|
|
372
|
+
if (scope === _Storage.StorageScope.Memory) {
|
|
373
|
+
const removeKeys = Array.from(memoryStore.keys()).filter(key => !keep.has(key));
|
|
374
|
+
if (removeKeys.length === 0) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
const previousValues = shouldReadPreviousEventValues(scope) ? removeKeys.map(key => getEventRawValue(scope, key)) : [];
|
|
378
|
+
removeKeys.forEach(key => memoryStore.delete(key));
|
|
379
|
+
removeKeys.forEach(key => (0, _shared.notifyKeyListeners)(memoryListeners, key));
|
|
380
|
+
emitBatchChange(scope, "clear", "memory", removeKeys.map((key, index) => (0, _shared.createKeyChange)(scope, key, previousValues[index], undefined, "clear", "memory")));
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
if (scope === _Storage.StorageScope.Disk) {
|
|
384
|
+
flushDiskWrites();
|
|
385
|
+
}
|
|
386
|
+
if (scope === _Storage.StorageScope.Secure) {
|
|
387
|
+
flushSecureWrites();
|
|
388
|
+
}
|
|
389
|
+
const removeKeys = adapter.backend.getAllKeys(scope).filter(key => !keep.has(key));
|
|
390
|
+
if (removeKeys.length === 0) {
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
const previousValues = shouldReadPreviousEventValues(scope) ? adapter.backend.getBatch(removeKeys, scope) : [];
|
|
394
|
+
adapter.backend.removeBatch(removeKeys, scope);
|
|
395
|
+
removeKeys.forEach(key => cacheRawValue(scope, key, undefined));
|
|
396
|
+
emitBatchChange(scope, "clear", adapter.changeSource, removeKeys.map((key, index) => (0, _shared.createKeyChange)(scope, key, previousValues[index], undefined, "clear", adapter.changeSource)));
|
|
397
|
+
});
|
|
398
|
+
}
|
|
362
399
|
const storage = {
|
|
363
400
|
subscribe: (scope, listener) => {
|
|
364
401
|
(0, _internal.assertValidScope)(scope);
|
|
@@ -410,7 +447,11 @@ function createStorageCore(buildAdapter) {
|
|
|
410
447
|
adapter.maybeCleanupScopeSubscription(_Storage.StorageScope.Disk);
|
|
411
448
|
adapter.maybeCleanupScopeSubscription(_Storage.StorageScope.Secure);
|
|
412
449
|
},
|
|
413
|
-
clear: scope => {
|
|
450
|
+
clear: (scope, options) => {
|
|
451
|
+
if (options?.except && options.except.length > 0) {
|
|
452
|
+
clearScopeExcept(scope, options.except);
|
|
453
|
+
return;
|
|
454
|
+
}
|
|
414
455
|
measureOperation("storage:clear", scope, () => {
|
|
415
456
|
const previousValues = shouldReadPreviousEventValues(scope) ? storage.getAll(scope) : {};
|
|
416
457
|
if (scope === _Storage.StorageScope.Memory) {
|
|
@@ -439,6 +480,71 @@ function createStorageCore(buildAdapter) {
|
|
|
439
480
|
storage.clear(_Storage.StorageScope.Secure);
|
|
440
481
|
}, 3);
|
|
441
482
|
},
|
|
483
|
+
clearGroup: group => {
|
|
484
|
+
const items = itemGroups.get(group);
|
|
485
|
+
if (!items || items.size === 0) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
measureOperation("storage:clearGroup", _Storage.StorageScope.Memory, () => {
|
|
489
|
+
const byScope = new Map();
|
|
490
|
+
for (const item of items) {
|
|
491
|
+
const scoped = byScope.get(item.scope);
|
|
492
|
+
if (scoped) {
|
|
493
|
+
scoped.push(item);
|
|
494
|
+
} else {
|
|
495
|
+
byScope.set(item.scope, [item]);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
byScope.forEach((groupItems, scope) => {
|
|
499
|
+
removeBatch(groupItems, scope);
|
|
500
|
+
});
|
|
501
|
+
}, items.size);
|
|
502
|
+
},
|
|
503
|
+
getGroupItems: group => {
|
|
504
|
+
const items = itemGroups.get(group);
|
|
505
|
+
return items ? Array.from(items) : [];
|
|
506
|
+
},
|
|
507
|
+
subscribeExpired: (scope, listener) => {
|
|
508
|
+
return storage.subscribe(scope, event => {
|
|
509
|
+
if (event.type === "key") {
|
|
510
|
+
if (event.operation === "expire") {
|
|
511
|
+
listener(event);
|
|
512
|
+
}
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
event.changes.forEach(change => {
|
|
516
|
+
if (change.operation === "expire") {
|
|
517
|
+
listener(change);
|
|
518
|
+
}
|
|
519
|
+
});
|
|
520
|
+
});
|
|
521
|
+
},
|
|
522
|
+
findDuplicateKeys: () => {
|
|
523
|
+
const duplicates = [];
|
|
524
|
+
registeredKeyCounts.forEach((count, registryKey) => {
|
|
525
|
+
if (count <= 1) {
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
const separatorIndex = registryKey.indexOf(":");
|
|
529
|
+
duplicates.push({
|
|
530
|
+
scope: Number(registryKey.slice(0, separatorIndex)),
|
|
531
|
+
key: registryKey.slice(separatorIndex + 1),
|
|
532
|
+
count
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
return duplicates;
|
|
536
|
+
},
|
|
537
|
+
getRegisteredKeys: () => {
|
|
538
|
+
const result = [];
|
|
539
|
+
registeredKeyCounts.forEach((_count, registryKey) => {
|
|
540
|
+
const separatorIndex = registryKey.indexOf(":");
|
|
541
|
+
result.push({
|
|
542
|
+
scope: Number(registryKey.slice(0, separatorIndex)),
|
|
543
|
+
key: registryKey.slice(separatorIndex + 1)
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
return result;
|
|
547
|
+
},
|
|
442
548
|
clearNamespace: (namespace, scope) => {
|
|
443
549
|
measureOperation("storage:clearNamespace", scope, () => {
|
|
444
550
|
(0, _internal.assertValidScope)(scope);
|
|
@@ -738,6 +844,10 @@ function createStorageCore(buildAdapter) {
|
|
|
738
844
|
const coalesceSecureWrites = config.scope === _Storage.StorageScope.Secure && config.coalesceSecureWrites === true && !isBiometric;
|
|
739
845
|
const defaultValue = config.defaultValue;
|
|
740
846
|
const nonMemoryScope = config.scope === _Storage.StorageScope.Disk ? _Storage.StorageScope.Disk : config.scope === _Storage.StorageScope.Secure ? _Storage.StorageScope.Secure : null;
|
|
847
|
+
const renameFromKeys = config.renameFrom === undefined ? EMPTY_KEYS : typeof config.renameFrom === "string" ? [config.renameFrom] : config.renameFrom;
|
|
848
|
+
const fallbackToCacheOnReadError = config.fallbackToCacheOnReadError === true;
|
|
849
|
+
const onReadError = config.onReadError;
|
|
850
|
+
let renamesMigrated = isMemory || renameFromKeys.length === 0;
|
|
741
851
|
if (expiration && expiration.ttlMs <= 0) {
|
|
742
852
|
throw new Error("expiration.ttlMs must be greater than 0.");
|
|
743
853
|
}
|
|
@@ -779,15 +889,18 @@ function createStorageCore(buildAdapter) {
|
|
|
779
889
|
if (memoryExpiration) {
|
|
780
890
|
const expiresAt = memoryExpiration.get(storageKey);
|
|
781
891
|
if (expiresAt !== undefined && expiresAt <= Date.now()) {
|
|
892
|
+
const expiredRaw = memoryStore.get(storageKey);
|
|
782
893
|
memoryExpiration.delete(storageKey);
|
|
783
894
|
memoryStore.delete(storageKey);
|
|
784
895
|
(0, _shared.notifyKeyListeners)(memoryListeners, storageKey);
|
|
896
|
+
emitKeyChange(config.scope, storageKey, typeof expiredRaw === "string" ? expiredRaw : undefined, undefined, "expire", "memory");
|
|
785
897
|
onExpired?.(storageKey);
|
|
786
898
|
return undefined;
|
|
787
899
|
}
|
|
788
900
|
}
|
|
789
901
|
return memoryStore.get(storageKey);
|
|
790
902
|
}
|
|
903
|
+
migrateRenamesIfNeeded();
|
|
791
904
|
if (nonMemoryScope === _Storage.StorageScope.Disk) {
|
|
792
905
|
const pending = pendingDiskWrites.get(storageKey);
|
|
793
906
|
if (pending !== undefined) {
|
|
@@ -808,12 +921,27 @@ function createStorageCore(buildAdapter) {
|
|
|
808
921
|
}
|
|
809
922
|
}
|
|
810
923
|
if (isBiometric) {
|
|
811
|
-
return adapter.backend.getSecureBiometric(storageKey);
|
|
924
|
+
return readBackendRaw(() => adapter.backend.getSecureBiometric(storageKey));
|
|
812
925
|
}
|
|
813
|
-
const raw = adapter.backend.get(storageKey, config.scope);
|
|
926
|
+
const raw = readBackendRaw(() => adapter.backend.get(storageKey, config.scope));
|
|
814
927
|
cacheRawValue(nonMemoryScope, storageKey, raw);
|
|
815
928
|
return raw;
|
|
816
929
|
};
|
|
930
|
+
const readBackendRaw = read => {
|
|
931
|
+
try {
|
|
932
|
+
return read();
|
|
933
|
+
} catch (error) {
|
|
934
|
+
onReadError?.(error);
|
|
935
|
+
if (fallbackToCacheOnReadError) {
|
|
936
|
+
const cached = getScopeRawCache(nonMemoryScope).get(storageKey);
|
|
937
|
+
if (cached !== undefined) {
|
|
938
|
+
return cached;
|
|
939
|
+
}
|
|
940
|
+
return typeof lastRaw === "string" ? lastRaw : undefined;
|
|
941
|
+
}
|
|
942
|
+
throw error;
|
|
943
|
+
}
|
|
944
|
+
};
|
|
817
945
|
const writeStoredRaw = rawValue => {
|
|
818
946
|
const oldValue = undefined;
|
|
819
947
|
if (isBiometric) {
|
|
@@ -844,32 +972,73 @@ function createStorageCore(buildAdapter) {
|
|
|
844
972
|
adapter.backend.set(storageKey, rawValue, config.scope);
|
|
845
973
|
emitKeyChange(config.scope, storageKey, oldValue, rawValue, "set", adapter.changeSource);
|
|
846
974
|
};
|
|
847
|
-
const
|
|
975
|
+
const migrateRenamesIfNeeded = () => {
|
|
976
|
+
if (renamesMigrated) {
|
|
977
|
+
return;
|
|
978
|
+
}
|
|
979
|
+
try {
|
|
980
|
+
const hasCurrent = isBiometric ? adapter.backend.hasSecureBiometric(storageKey) : adapter.backend.has(storageKey, config.scope);
|
|
981
|
+
if (hasCurrent) {
|
|
982
|
+
for (const legacyKey of renameFromKeys) {
|
|
983
|
+
if (isBiometric) {
|
|
984
|
+
if (adapter.backend.hasSecureBiometric(legacyKey)) {
|
|
985
|
+
adapter.backend.deleteSecureBiometric(legacyKey);
|
|
986
|
+
}
|
|
987
|
+
} else if (adapter.backend.has(legacyKey, config.scope)) {
|
|
988
|
+
adapter.backend.remove(legacyKey, config.scope);
|
|
989
|
+
}
|
|
990
|
+
}
|
|
991
|
+
renamesMigrated = true;
|
|
992
|
+
return;
|
|
993
|
+
}
|
|
994
|
+
for (const legacyKey of renameFromKeys) {
|
|
995
|
+
const legacyRaw = isBiometric ? adapter.backend.getSecureBiometric(legacyKey) : adapter.backend.get(legacyKey, config.scope);
|
|
996
|
+
if (legacyRaw === undefined) {
|
|
997
|
+
continue;
|
|
998
|
+
}
|
|
999
|
+
writeStoredRaw(legacyRaw);
|
|
1000
|
+
if (isBiometric) {
|
|
1001
|
+
adapter.backend.deleteSecureBiometric(legacyKey);
|
|
1002
|
+
} else {
|
|
1003
|
+
adapter.backend.remove(legacyKey, config.scope);
|
|
1004
|
+
}
|
|
1005
|
+
break;
|
|
1006
|
+
}
|
|
1007
|
+
renamesMigrated = true;
|
|
1008
|
+
} catch (error) {
|
|
1009
|
+
if ((0, _shared.isKeychainLockedError)(error)) {
|
|
1010
|
+
onReadError?.(error);
|
|
1011
|
+
return;
|
|
1012
|
+
}
|
|
1013
|
+
throw error;
|
|
1014
|
+
}
|
|
1015
|
+
};
|
|
1016
|
+
const removeStoredRaw = (operation = "remove") => {
|
|
848
1017
|
const oldValue = getEventRawValue(config.scope, storageKey);
|
|
849
1018
|
if (isBiometric) {
|
|
850
1019
|
adapter.backend.deleteSecureBiometric(storageKey);
|
|
851
|
-
emitKeyChange(config.scope, storageKey, oldValue, undefined,
|
|
1020
|
+
emitKeyChange(config.scope, storageKey, oldValue, undefined, operation, adapter.changeSource);
|
|
852
1021
|
return;
|
|
853
1022
|
}
|
|
854
1023
|
cacheRawValue(nonMemoryScope, storageKey, undefined);
|
|
855
1024
|
if (nonMemoryScope === _Storage.StorageScope.Disk) {
|
|
856
1025
|
if (coalesceDiskWrites || diskWritesAsync) {
|
|
857
1026
|
scheduleDiskWrite(storageKey, undefined);
|
|
858
|
-
emitKeyChange(config.scope, storageKey, oldValue, undefined,
|
|
1027
|
+
emitKeyChange(config.scope, storageKey, oldValue, undefined, operation, adapter.changeSource);
|
|
859
1028
|
return;
|
|
860
1029
|
}
|
|
861
1030
|
clearPendingDiskWrite(storageKey);
|
|
862
1031
|
}
|
|
863
1032
|
if (coalesceSecureWrites) {
|
|
864
1033
|
scheduleSecureWrite(storageKey, undefined, secureAccessControl ?? secureDefaultAccessControl);
|
|
865
|
-
emitKeyChange(config.scope, storageKey, oldValue, undefined,
|
|
1034
|
+
emitKeyChange(config.scope, storageKey, oldValue, undefined, operation, adapter.changeSource);
|
|
866
1035
|
return;
|
|
867
1036
|
}
|
|
868
1037
|
if (nonMemoryScope === _Storage.StorageScope.Secure) {
|
|
869
1038
|
clearPendingSecureWrite(storageKey);
|
|
870
1039
|
}
|
|
871
1040
|
adapter.backend.remove(storageKey, config.scope);
|
|
872
|
-
emitKeyChange(config.scope, storageKey, oldValue, undefined,
|
|
1041
|
+
emitKeyChange(config.scope, storageKey, oldValue, undefined, operation, adapter.changeSource);
|
|
873
1042
|
};
|
|
874
1043
|
const writeValueWithoutValidation = value => {
|
|
875
1044
|
if (isMemory) {
|
|
@@ -923,7 +1092,7 @@ function createStorageCore(buildAdapter) {
|
|
|
923
1092
|
if (lastExpiresAt > Date.now()) {
|
|
924
1093
|
return lastValue;
|
|
925
1094
|
}
|
|
926
|
-
removeStoredRaw();
|
|
1095
|
+
removeStoredRaw("expire");
|
|
927
1096
|
invalidateParsedCache();
|
|
928
1097
|
onExpired?.(storageKey);
|
|
929
1098
|
lastValue = ensureValidatedValue(defaultValue, false);
|
|
@@ -959,7 +1128,7 @@ function createStorageCore(buildAdapter) {
|
|
|
959
1128
|
if ((0, _internal.isStoredEnvelope)(parsed)) {
|
|
960
1129
|
envelopeExpiresAt = parsed.expiresAt;
|
|
961
1130
|
if (parsed.expiresAt <= Date.now()) {
|
|
962
|
-
removeStoredRaw();
|
|
1131
|
+
removeStoredRaw("expire");
|
|
963
1132
|
invalidateParsedCache();
|
|
964
1133
|
onExpired?.(storageKey);
|
|
965
1134
|
lastValue = ensureValidatedValue(defaultValue, false);
|
|
@@ -1023,6 +1192,27 @@ function createStorageCore(buildAdapter) {
|
|
|
1023
1192
|
removeStoredRaw();
|
|
1024
1193
|
});
|
|
1025
1194
|
};
|
|
1195
|
+
const merge = partial => {
|
|
1196
|
+
set(prev => {
|
|
1197
|
+
if (prev === null || typeof prev !== "object") {
|
|
1198
|
+
return partial;
|
|
1199
|
+
}
|
|
1200
|
+
return {
|
|
1201
|
+
...prev,
|
|
1202
|
+
...partial
|
|
1203
|
+
};
|
|
1204
|
+
});
|
|
1205
|
+
};
|
|
1206
|
+
const reset = () => {
|
|
1207
|
+
deleteItem();
|
|
1208
|
+
};
|
|
1209
|
+
const setOrDelete = value => {
|
|
1210
|
+
if (value === null || value === undefined) {
|
|
1211
|
+
deleteItem();
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
set(value);
|
|
1215
|
+
};
|
|
1026
1216
|
const hasItem = () => measureOperation("item:has", config.scope, () => {
|
|
1027
1217
|
if (isMemory) return memoryStore.has(storageKey);
|
|
1028
1218
|
if (isBiometric) return adapter.backend.hasSecureBiometric(storageKey);
|
|
@@ -1075,6 +1265,9 @@ function createStorageCore(buildAdapter) {
|
|
|
1075
1265
|
getWithVersion,
|
|
1076
1266
|
set,
|
|
1077
1267
|
setIfVersion,
|
|
1268
|
+
merge,
|
|
1269
|
+
reset,
|
|
1270
|
+
setOrDelete,
|
|
1078
1271
|
delete: deleteItem,
|
|
1079
1272
|
has: hasItem,
|
|
1080
1273
|
subscribe,
|
|
@@ -1097,9 +1290,22 @@ function createStorageCore(buildAdapter) {
|
|
|
1097
1290
|
...(secureAccessControl !== undefined ? {
|
|
1098
1291
|
_secureAccessControl: secureAccessControl
|
|
1099
1292
|
} : {}),
|
|
1293
|
+
...(config.group !== undefined ? {
|
|
1294
|
+
_group: config.group
|
|
1295
|
+
} : {}),
|
|
1100
1296
|
scope: config.scope,
|
|
1101
1297
|
key: storageKey
|
|
1102
1298
|
};
|
|
1299
|
+
if (config.group !== undefined) {
|
|
1300
|
+
let groupSet = itemGroups.get(config.group);
|
|
1301
|
+
if (!groupSet) {
|
|
1302
|
+
groupSet = new Set();
|
|
1303
|
+
itemGroups.set(config.group, groupSet);
|
|
1304
|
+
}
|
|
1305
|
+
groupSet.add(storageItem);
|
|
1306
|
+
}
|
|
1307
|
+
const registryKey = `${config.scope}:${storageKey}`;
|
|
1308
|
+
registeredKeyCounts.set(registryKey, (registeredKeyCounts.get(registryKey) ?? 0) + 1);
|
|
1103
1309
|
return storageItem;
|
|
1104
1310
|
}
|
|
1105
1311
|
function getBatch(items, scope) {
|
|
@@ -1484,14 +1690,104 @@ function createStorageCore(buildAdapter) {
|
|
|
1484
1690
|
} : {}),
|
|
1485
1691
|
...(expirationConfig !== undefined ? {
|
|
1486
1692
|
expiration: expirationConfig
|
|
1693
|
+
} : {}),
|
|
1694
|
+
...(itemConfig.renameFrom !== undefined ? {
|
|
1695
|
+
renameFrom: itemConfig.renameFrom
|
|
1696
|
+
} : {}),
|
|
1697
|
+
...(options?.group !== undefined ? {
|
|
1698
|
+
group: options.group
|
|
1699
|
+
} : {}),
|
|
1700
|
+
...(options?.fallbackToCacheOnReadError !== undefined ? {
|
|
1701
|
+
fallbackToCacheOnReadError: options.fallbackToCacheOnReadError
|
|
1487
1702
|
} : {})
|
|
1488
1703
|
});
|
|
1489
1704
|
}
|
|
1490
1705
|
return result;
|
|
1491
1706
|
}
|
|
1707
|
+
function memoryItem(config) {
|
|
1708
|
+
return createStorageItem({
|
|
1709
|
+
...config,
|
|
1710
|
+
scope: _Storage.StorageScope.Memory
|
|
1711
|
+
});
|
|
1712
|
+
}
|
|
1713
|
+
function diskItem(config) {
|
|
1714
|
+
return createStorageItem({
|
|
1715
|
+
...config,
|
|
1716
|
+
scope: _Storage.StorageScope.Disk
|
|
1717
|
+
});
|
|
1718
|
+
}
|
|
1719
|
+
function secureItem(config) {
|
|
1720
|
+
return createStorageItem({
|
|
1721
|
+
...config,
|
|
1722
|
+
scope: _Storage.StorageScope.Secure
|
|
1723
|
+
});
|
|
1724
|
+
}
|
|
1725
|
+
function createSetItem(config) {
|
|
1726
|
+
const {
|
|
1727
|
+
defaultValue,
|
|
1728
|
+
...rest
|
|
1729
|
+
} = config;
|
|
1730
|
+
const initial = {};
|
|
1731
|
+
if (defaultValue) {
|
|
1732
|
+
for (const id of defaultValue) {
|
|
1733
|
+
initial[id] = true;
|
|
1734
|
+
}
|
|
1735
|
+
}
|
|
1736
|
+
const item = createStorageItem({
|
|
1737
|
+
...rest,
|
|
1738
|
+
defaultValue: initial
|
|
1739
|
+
});
|
|
1740
|
+
const has = id => item.get()[id] === true;
|
|
1741
|
+
const add = id => {
|
|
1742
|
+
if (item.get()[id] === true) {
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
item.merge({
|
|
1746
|
+
[id]: true
|
|
1747
|
+
});
|
|
1748
|
+
};
|
|
1749
|
+
const deleteId = id => {
|
|
1750
|
+
const current = item.get();
|
|
1751
|
+
if (current[id] !== true) {
|
|
1752
|
+
return;
|
|
1753
|
+
}
|
|
1754
|
+
const next = {
|
|
1755
|
+
...current
|
|
1756
|
+
};
|
|
1757
|
+
delete next[id];
|
|
1758
|
+
item.set(next);
|
|
1759
|
+
};
|
|
1760
|
+
const toggle = id => {
|
|
1761
|
+
if (has(id)) {
|
|
1762
|
+
deleteId(id);
|
|
1763
|
+
return false;
|
|
1764
|
+
}
|
|
1765
|
+
add(id);
|
|
1766
|
+
return true;
|
|
1767
|
+
};
|
|
1768
|
+
return {
|
|
1769
|
+
get: item.get,
|
|
1770
|
+
has,
|
|
1771
|
+
add,
|
|
1772
|
+
delete: deleteId,
|
|
1773
|
+
toggle,
|
|
1774
|
+
values: () => Object.keys(item.get()),
|
|
1775
|
+
size: () => Object.keys(item.get()).length,
|
|
1776
|
+
clear: () => item.set({}),
|
|
1777
|
+
reset: item.reset,
|
|
1778
|
+
subscribe: item.subscribe,
|
|
1779
|
+
scope: item.scope,
|
|
1780
|
+
key: item.key,
|
|
1781
|
+
item
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1492
1784
|
return {
|
|
1493
1785
|
storage,
|
|
1494
1786
|
createStorageItem,
|
|
1787
|
+
memoryItem,
|
|
1788
|
+
diskItem,
|
|
1789
|
+
secureItem,
|
|
1790
|
+
createSetItem,
|
|
1495
1791
|
getBatch,
|
|
1496
1792
|
setBatch,
|
|
1497
1793
|
removeBatch,
|