react-native-nitro-storage 0.7.0 → 0.8.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 +32 -0
- package/README.md +20 -9
- package/SECURITY.md +2 -2
- 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 +217 -233
- 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 +218 -234
- 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 +3 -3
- 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/package.json +3 -2
- 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 +317 -285
- 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
package/src/storage-events.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { StorageScope } from "./Storage.types";
|
|
1
|
+
import type { StorageScope } from "./Storage.types";
|
|
2
2
|
|
|
3
3
|
export type StorageChangeOperation =
|
|
4
4
|
| "set"
|
|
@@ -10,6 +10,7 @@ export type StorageChangeOperation =
|
|
|
10
10
|
| "removeBatch"
|
|
11
11
|
| "import"
|
|
12
12
|
| "expire"
|
|
13
|
+
| "rollback"
|
|
13
14
|
| "external";
|
|
14
15
|
|
|
15
16
|
export type StorageChangeSource = "memory" | "native" | "web" | "external";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { StorageCore } from "./storage-core";
|
|
2
|
+
import type {
|
|
3
|
+
SecurityCapabilities,
|
|
4
|
+
StorageCapabilities,
|
|
5
|
+
} from "./storage-runtime";
|
|
6
|
+
import type { AccessControl, StorageScope } from "./Storage.types";
|
|
7
|
+
|
|
8
|
+
export type PlatformStorage = StorageCore["storage"] & {
|
|
9
|
+
setAccessControl(level: AccessControl): void;
|
|
10
|
+
setSecureWritesAsync(enabled: boolean): void;
|
|
11
|
+
setKeychainAccessGroup(group: string): void;
|
|
12
|
+
getCapabilities(): StorageCapabilities;
|
|
13
|
+
getSecurityCapabilities(): SecurityCapabilities;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export type PlatformScope = StorageScope;
|
package/src/storage-runtime.ts
CHANGED
|
@@ -56,6 +56,15 @@ export type SecureStorageMetadata = {
|
|
|
56
56
|
|
|
57
57
|
const STORAGE_ERROR_TAG_PATTERN = /\[nitro-error:([a-z_]+)\]/;
|
|
58
58
|
|
|
59
|
+
const STORAGE_ERROR_CODES = new Set<StorageErrorCode>([
|
|
60
|
+
"keychain_locked",
|
|
61
|
+
"authentication_required",
|
|
62
|
+
"key_invalidated",
|
|
63
|
+
"storage_corruption",
|
|
64
|
+
"biometric_unavailable",
|
|
65
|
+
"unsupported",
|
|
66
|
+
]);
|
|
67
|
+
|
|
59
68
|
export function getStorageErrorCode(
|
|
60
69
|
err: unknown,
|
|
61
70
|
): StorageErrorCode | undefined {
|
|
@@ -63,56 +72,13 @@ export function getStorageErrorCode(
|
|
|
63
72
|
return undefined;
|
|
64
73
|
}
|
|
65
74
|
|
|
66
|
-
const
|
|
67
|
-
const taggedCode = message.match(STORAGE_ERROR_TAG_PATTERN)?.[1];
|
|
68
|
-
|
|
69
|
-
if (
|
|
70
|
-
taggedCode === "keychain_locked" ||
|
|
71
|
-
taggedCode === "authentication_required" ||
|
|
72
|
-
taggedCode === "key_invalidated" ||
|
|
73
|
-
taggedCode === "storage_corruption" ||
|
|
74
|
-
taggedCode === "biometric_unavailable" ||
|
|
75
|
-
taggedCode === "unsupported"
|
|
76
|
-
) {
|
|
77
|
-
return taggedCode;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
if (message.includes("errSecInteractionNotAllowed")) {
|
|
81
|
-
return "keychain_locked";
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (
|
|
85
|
-
message.includes("UserNotAuthenticatedException") ||
|
|
86
|
-
message.includes("KeyStoreException") ||
|
|
87
|
-
message.includes("android.security.keystore")
|
|
88
|
-
) {
|
|
89
|
-
return "authentication_required";
|
|
90
|
-
}
|
|
75
|
+
const taggedCode = err.message.match(STORAGE_ERROR_TAG_PATTERN)?.[1];
|
|
91
76
|
|
|
92
77
|
if (
|
|
93
|
-
|
|
94
|
-
|
|
78
|
+
taggedCode !== undefined &&
|
|
79
|
+
STORAGE_ERROR_CODES.has(taggedCode as StorageErrorCode)
|
|
95
80
|
) {
|
|
96
|
-
return
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (
|
|
100
|
-
message.includes("AEADBadTagException") ||
|
|
101
|
-
message.toLowerCase().includes("storage corruption") ||
|
|
102
|
-
message.toLowerCase().includes("corrupted storage")
|
|
103
|
-
) {
|
|
104
|
-
return "storage_corruption";
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
if (
|
|
108
|
-
message.toLowerCase().includes("biometric storage unavailable") ||
|
|
109
|
-
message.toLowerCase().includes("biometric storage is not available")
|
|
110
|
-
) {
|
|
111
|
-
return "biometric_unavailable";
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
if (message.toLowerCase().includes("unsupported")) {
|
|
115
|
-
return "unsupported";
|
|
81
|
+
return taggedCode as StorageErrorCode;
|
|
116
82
|
}
|
|
117
83
|
|
|
118
84
|
return undefined;
|
package/src/testing.ts
CHANGED
|
@@ -1,22 +1,27 @@
|
|
|
1
|
-
import { StorageScope, AccessControl } from "./Storage.types";
|
|
2
1
|
import { assertAccessControlLevel } from "./shared";
|
|
3
2
|
import type { NonMemoryScope } from "./shared";
|
|
4
|
-
import type {
|
|
5
|
-
SecurityCapabilities,
|
|
6
|
-
StorageCapabilities,
|
|
7
|
-
} from "./storage-runtime";
|
|
8
3
|
import {
|
|
9
4
|
createStorageCore,
|
|
10
5
|
type StorageCoreAdapter,
|
|
11
6
|
type StorageCoreBackend,
|
|
12
7
|
type StorageCoreInternals,
|
|
13
8
|
} from "./storage-core";
|
|
9
|
+
import type {
|
|
10
|
+
SecurityCapabilities,
|
|
11
|
+
StorageCapabilities,
|
|
12
|
+
} from "./storage-runtime";
|
|
13
|
+
import { StorageScope, AccessControl } from "./Storage.types";
|
|
14
14
|
|
|
15
15
|
export { StorageScope, AccessControl, BiometricLevel } from "./Storage.types";
|
|
16
16
|
export { isKeychainLockedError } from "./shared";
|
|
17
17
|
export { migrateFromMMKV } from "./migration";
|
|
18
18
|
export { getStorageErrorCode } from "./storage-runtime";
|
|
19
19
|
export { createIndexedDBBackend } from "./indexeddb-backend";
|
|
20
|
+
export {
|
|
21
|
+
describeWebBackendCapabilities,
|
|
22
|
+
isIndexedDBWebBackend,
|
|
23
|
+
type WebBackendCapabilities,
|
|
24
|
+
} from "./web-backend-contract";
|
|
20
25
|
export {
|
|
21
26
|
useSetStorage,
|
|
22
27
|
useStorage,
|
|
@@ -66,6 +71,7 @@ export type {
|
|
|
66
71
|
StorageKeyRef,
|
|
67
72
|
TransactionContext,
|
|
68
73
|
} from "./storage-core";
|
|
74
|
+
export type { PlatformScope, PlatformStorage } from "./storage-platform";
|
|
69
75
|
|
|
70
76
|
const TEST_SECURE_BACKEND = "in-memory-test";
|
|
71
77
|
|
|
@@ -144,7 +150,9 @@ function createInMemoryBackend(): InMemoryBackend {
|
|
|
144
150
|
biometricStore.clear();
|
|
145
151
|
},
|
|
146
152
|
resetState: () => {
|
|
147
|
-
stores.forEach((store) =>
|
|
153
|
+
stores.forEach((store) => {
|
|
154
|
+
store.clear();
|
|
155
|
+
});
|
|
148
156
|
biometricStore.clear();
|
|
149
157
|
},
|
|
150
158
|
};
|
|
@@ -159,7 +167,6 @@ function buildTestingModule() {
|
|
|
159
167
|
backend,
|
|
160
168
|
changeSource: "native",
|
|
161
169
|
applyAccessControlOnSecureRawWrite: true,
|
|
162
|
-
flushDiskWritesOnImport: false,
|
|
163
170
|
ensureScopeSubscription: (_scope: NonMemoryScope) => {},
|
|
164
171
|
maybeCleanupScopeSubscription: (_scope: NonMemoryScope) => {},
|
|
165
172
|
onWillEmitChanges: () => {},
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { WebStorageBackend } from "./web-storage-backend";
|
|
2
|
+
|
|
3
|
+
export type WebBackendCapabilities = {
|
|
4
|
+
buffered: boolean;
|
|
5
|
+
flushable: boolean;
|
|
6
|
+
closable: boolean;
|
|
7
|
+
subscribable: boolean;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export function describeWebBackendCapabilities(
|
|
11
|
+
backend: WebStorageBackend | undefined,
|
|
12
|
+
): WebBackendCapabilities {
|
|
13
|
+
if (!backend) {
|
|
14
|
+
return {
|
|
15
|
+
buffered: false,
|
|
16
|
+
flushable: false,
|
|
17
|
+
closable: false,
|
|
18
|
+
subscribable: false,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return {
|
|
23
|
+
buffered: backend.name?.startsWith("indexeddb:") ?? false,
|
|
24
|
+
flushable: typeof backend.flush === "function",
|
|
25
|
+
closable: typeof backend.close === "function",
|
|
26
|
+
subscribable: typeof backend.subscribe === "function",
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export function isIndexedDBWebBackend(
|
|
31
|
+
backend: WebStorageBackend | undefined,
|
|
32
|
+
): boolean {
|
|
33
|
+
return backend?.name?.startsWith("indexeddb:") ?? false;
|
|
34
|
+
}
|