react-native-nitro-storage 0.1.4 → 0.3.1
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 +432 -345
- package/android/src/main/cpp/AndroidStorageAdapterCpp.cpp +191 -3
- package/android/src/main/cpp/AndroidStorageAdapterCpp.hpp +21 -41
- package/android/src/main/java/com/nitrostorage/AndroidStorageAdapter.kt +181 -29
- package/android/src/main/java/com/nitrostorage/NitroStoragePackage.kt +2 -2
- package/app.plugin.js +9 -7
- package/cpp/bindings/HybridStorage.cpp +239 -10
- package/cpp/bindings/HybridStorage.hpp +10 -0
- package/cpp/core/NativeStorageAdapter.hpp +22 -0
- package/ios/IOSStorageAdapterCpp.hpp +25 -0
- package/ios/IOSStorageAdapterCpp.mm +315 -33
- package/lib/commonjs/Storage.types.js +23 -1
- package/lib/commonjs/Storage.types.js.map +1 -1
- package/lib/commonjs/index.js +680 -68
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +801 -133
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/internal.js +112 -0
- package/lib/commonjs/internal.js.map +1 -0
- package/lib/module/Storage.types.js +22 -0
- package/lib/module/Storage.types.js.map +1 -1
- package/lib/module/index.js +660 -71
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +766 -125
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/internal.js +100 -0
- package/lib/module/internal.js.map +1 -0
- package/lib/typescript/Storage.nitro.d.ts +10 -0
- package/lib/typescript/Storage.nitro.d.ts.map +1 -1
- package/lib/typescript/Storage.types.d.ts +20 -0
- package/lib/typescript/Storage.types.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +68 -9
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +79 -13
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/internal.d.ts +21 -0
- package/lib/typescript/internal.d.ts.map +1 -0
- package/lib/typescript/migration.d.ts +2 -3
- package/lib/typescript/migration.d.ts.map +1 -1
- package/nitrogen/generated/shared/c++/HybridStorageSpec.cpp +10 -0
- package/nitrogen/generated/shared/c++/HybridStorageSpec.hpp +10 -0
- package/package.json +22 -8
- package/src/Storage.nitro.ts +11 -2
- package/src/Storage.types.ts +22 -0
- package/src/index.ts +943 -84
- package/src/index.web.ts +1082 -137
- package/src/internal.ts +144 -0
- package/src/migration.ts +3 -3
package/src/internal.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { StorageScope } from "./Storage.types";
|
|
2
|
+
|
|
3
|
+
export const MIGRATION_VERSION_KEY = "__nitro_storage_migration_version__";
|
|
4
|
+
export const NATIVE_BATCH_MISSING_SENTINEL =
|
|
5
|
+
"__nitro_storage_batch_missing__::v1";
|
|
6
|
+
const PRIMITIVE_FAST_PATH_PREFIX = "__nitro_storage_primitive__:";
|
|
7
|
+
const NAMESPACE_SEPARATOR = ":";
|
|
8
|
+
|
|
9
|
+
export type StoredEnvelope = {
|
|
10
|
+
__nitroStorageEnvelope: true;
|
|
11
|
+
expiresAt: number;
|
|
12
|
+
payload: string;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function isStoredEnvelope(value: unknown): value is StoredEnvelope {
|
|
16
|
+
if (typeof value !== "object" || value === null) {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const candidate = value as Partial<StoredEnvelope>;
|
|
21
|
+
return (
|
|
22
|
+
candidate.__nitroStorageEnvelope === true &&
|
|
23
|
+
typeof candidate.expiresAt === "number" &&
|
|
24
|
+
typeof candidate.payload === "string"
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function assertValidScope(scope: StorageScope): void {
|
|
29
|
+
if (
|
|
30
|
+
scope !== StorageScope.Memory &&
|
|
31
|
+
scope !== StorageScope.Disk &&
|
|
32
|
+
scope !== StorageScope.Secure
|
|
33
|
+
) {
|
|
34
|
+
throw new Error(`Invalid storage scope: ${String(scope)}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export type ScopedBatchItem = {
|
|
39
|
+
key: string;
|
|
40
|
+
scope: StorageScope;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export function assertBatchScope(
|
|
44
|
+
items: readonly ScopedBatchItem[],
|
|
45
|
+
scope: StorageScope,
|
|
46
|
+
): void {
|
|
47
|
+
const mismatchedItem = items.find((item) => item.scope !== scope);
|
|
48
|
+
if (!mismatchedItem) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const expectedScope = StorageScope[scope] ?? String(scope);
|
|
53
|
+
const actualScope =
|
|
54
|
+
StorageScope[mismatchedItem.scope] ?? String(mismatchedItem.scope);
|
|
55
|
+
|
|
56
|
+
throw new Error(
|
|
57
|
+
`Batch scope mismatch for "${mismatchedItem.key}": expected ${expectedScope}, received ${actualScope}.`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function decodeNativeBatchValue(
|
|
62
|
+
value: string | undefined,
|
|
63
|
+
): string | undefined {
|
|
64
|
+
if (value === NATIVE_BATCH_MISSING_SENTINEL) {
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return value;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function prefixKey(namespace: string | undefined, key: string): string {
|
|
72
|
+
if (!namespace) return key;
|
|
73
|
+
return `${namespace}${NAMESPACE_SEPARATOR}${key}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function isNamespaced(key: string, namespace: string): boolean {
|
|
77
|
+
return key.startsWith(`${namespace}${NAMESPACE_SEPARATOR}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function serializeWithPrimitiveFastPath<T>(value: T): string {
|
|
81
|
+
if (value === null) {
|
|
82
|
+
return `${PRIMITIVE_FAST_PATH_PREFIX}l`;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
switch (typeof value) {
|
|
86
|
+
case "string":
|
|
87
|
+
return `${PRIMITIVE_FAST_PATH_PREFIX}s:${value}`;
|
|
88
|
+
case "number":
|
|
89
|
+
if (Number.isFinite(value)) {
|
|
90
|
+
return `${PRIMITIVE_FAST_PATH_PREFIX}n:${value}`;
|
|
91
|
+
}
|
|
92
|
+
break;
|
|
93
|
+
case "boolean":
|
|
94
|
+
return `${PRIMITIVE_FAST_PATH_PREFIX}b:${value ? "1" : "0"}`;
|
|
95
|
+
case "undefined":
|
|
96
|
+
return `${PRIMITIVE_FAST_PATH_PREFIX}u`;
|
|
97
|
+
default:
|
|
98
|
+
break;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const serialized = JSON.stringify(value);
|
|
102
|
+
if (serialized === undefined) {
|
|
103
|
+
throw new Error(
|
|
104
|
+
"Unable to serialize value with default serializer. Provide a custom serialize function.",
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
return serialized;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function deserializeWithPrimitiveFastPath<T>(value: string): T {
|
|
111
|
+
if (value.startsWith(PRIMITIVE_FAST_PATH_PREFIX)) {
|
|
112
|
+
const encodedValue = value.slice(PRIMITIVE_FAST_PATH_PREFIX.length);
|
|
113
|
+
if (encodedValue === "u") {
|
|
114
|
+
return undefined as T;
|
|
115
|
+
}
|
|
116
|
+
if (encodedValue === "l") {
|
|
117
|
+
return null as T;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const separatorIndex = encodedValue.indexOf(":");
|
|
121
|
+
if (separatorIndex > 0) {
|
|
122
|
+
const tag = encodedValue.slice(0, separatorIndex);
|
|
123
|
+
const payload = encodedValue.slice(separatorIndex + 1);
|
|
124
|
+
if (tag === "s") {
|
|
125
|
+
return payload as T;
|
|
126
|
+
}
|
|
127
|
+
if (tag === "b") {
|
|
128
|
+
return (payload === "1") as T;
|
|
129
|
+
}
|
|
130
|
+
if (tag === "n") {
|
|
131
|
+
const parsed = Number(payload);
|
|
132
|
+
if (Number.isFinite(parsed)) {
|
|
133
|
+
return parsed as T;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
try {
|
|
140
|
+
return JSON.parse(value) as T;
|
|
141
|
+
} catch {
|
|
142
|
+
return value as T;
|
|
143
|
+
}
|
|
144
|
+
}
|
package/src/migration.ts
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
import type { StorageItem } from "./index";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
export type MMKVLike = {
|
|
4
4
|
getString: (key: string) => string | undefined;
|
|
5
5
|
getNumber: (key: string) => number | undefined;
|
|
6
6
|
getBoolean: (key: string) => boolean | undefined;
|
|
7
7
|
contains: (key: string) => boolean;
|
|
8
8
|
delete: (key: string) => void;
|
|
9
9
|
getAllKeys: () => string[];
|
|
10
|
-
}
|
|
10
|
+
};
|
|
11
11
|
|
|
12
12
|
export function migrateFromMMKV<T>(
|
|
13
13
|
mmkv: MMKVLike,
|
|
14
14
|
item: StorageItem<T>,
|
|
15
|
-
deleteFromMMKV = false
|
|
15
|
+
deleteFromMMKV = false,
|
|
16
16
|
): boolean {
|
|
17
17
|
const key = item.key;
|
|
18
18
|
if (!mmkv.contains(key)) {
|