react-native-nitro-storage 0.4.5 → 0.5.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 +254 -945
- package/SECURITY.md +26 -0
- package/docs/api-reference.md +281 -0
- package/docs/batch-transactions-migrations.md +200 -0
- package/docs/benchmarks.md +37 -0
- package/docs/mmkv-migration.md +80 -0
- package/docs/react-hooks.md +113 -0
- package/docs/recipes.md +302 -0
- package/docs/secure-storage.md +190 -0
- package/docs/web-backends.md +141 -0
- package/lib/commonjs/index.js +265 -14
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +220 -11
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/storage-events.js +117 -0
- package/lib/commonjs/storage-events.js.map +1 -0
- package/lib/commonjs/storage-runtime.js.map +1 -1
- package/lib/module/index.js +265 -14
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +220 -11
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/storage-events.js +112 -0
- package/lib/module/storage-events.js.map +1 -0
- package/lib/module/storage-runtime.js.map +1 -1
- package/lib/typescript/index.d.ts +19 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +19 -2
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/storage-events.d.ts +37 -0
- package/lib/typescript/storage-events.d.ts.map +1 -0
- package/lib/typescript/storage-runtime.d.ts +32 -0
- package/lib/typescript/storage-runtime.d.ts.map +1 -1
- package/package.json +25 -11
- package/src/index.ts +601 -14
- package/src/index.web.ts +535 -22
- package/src/storage-events.ts +184 -0
- package/src/storage-runtime.ts +35 -0
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Web Backends
|
|
2
|
+
|
|
3
|
+
Nitro Storage runs on web through synchronous backend contracts. Disk and Secure scopes can use different backends.
|
|
4
|
+
|
|
5
|
+
The default web backend is localStorage-style. Configure custom backends when you need IndexedDB persistence, tests with isolated storage, cross-tab sync, or a platform-specific secret wrapper.
|
|
6
|
+
|
|
7
|
+
## Backend Contract
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import type { WebStorageBackend } from "react-native-nitro-storage";
|
|
11
|
+
|
|
12
|
+
const backend: WebStorageBackend = {
|
|
13
|
+
name: "memory-test-backend",
|
|
14
|
+
getItem: (key) => map.get(key) ?? null,
|
|
15
|
+
setItem: (key, value) => {
|
|
16
|
+
map.set(key, value);
|
|
17
|
+
},
|
|
18
|
+
removeItem: (key) => {
|
|
19
|
+
map.delete(key);
|
|
20
|
+
},
|
|
21
|
+
clear: () => {
|
|
22
|
+
map.clear();
|
|
23
|
+
},
|
|
24
|
+
getAllKeys: () => Array.from(map.keys()),
|
|
25
|
+
};
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Optional methods improve performance and observability:
|
|
29
|
+
|
|
30
|
+
- `getMany(keys)`
|
|
31
|
+
- `setMany(entries)`
|
|
32
|
+
- `removeMany(keys)`
|
|
33
|
+
- `size()`
|
|
34
|
+
- `subscribe(listener)`
|
|
35
|
+
- `flush()`
|
|
36
|
+
- `name`
|
|
37
|
+
|
|
38
|
+
`subscribe(listener)` should report `{ key, newValue }` changes. Use `key: null` when the whole backend is cleared.
|
|
39
|
+
|
|
40
|
+
## Disk Backend
|
|
41
|
+
|
|
42
|
+
```ts
|
|
43
|
+
import {
|
|
44
|
+
setWebDiskStorageBackend,
|
|
45
|
+
storage,
|
|
46
|
+
StorageScope,
|
|
47
|
+
} from "react-native-nitro-storage";
|
|
48
|
+
|
|
49
|
+
setWebDiskStorageBackend(backend);
|
|
50
|
+
storage.setString("theme", "dark", StorageScope.Disk);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Secure Backend
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import {
|
|
57
|
+
setWebSecureStorageBackend,
|
|
58
|
+
storage,
|
|
59
|
+
StorageScope,
|
|
60
|
+
} from "react-native-nitro-storage";
|
|
61
|
+
|
|
62
|
+
setWebSecureStorageBackend(backend);
|
|
63
|
+
storage.setString("auth:refreshToken", "opaque-token", StorageScope.Secure);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Web Secure storage is only as strong as the configured backend. Browser storage does not provide iOS Keychain or Android Keystore guarantees.
|
|
67
|
+
|
|
68
|
+
## Flush Pending Web Writes
|
|
69
|
+
|
|
70
|
+
Backends may persist asynchronously while serving reads synchronously from memory. Use `flushWebStorageBackends()` before assertions or page lifecycle boundaries.
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { flushWebStorageBackends } from "react-native-nitro-storage";
|
|
74
|
+
|
|
75
|
+
await flushWebStorageBackends();
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## IndexedDB Secure Backend
|
|
79
|
+
|
|
80
|
+
`createIndexedDBBackend()` returns a `WebSecureStorageBackend` with a synchronous in-memory cache and asynchronous IndexedDB persistence.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
import { setWebSecureStorageBackend } from "react-native-nitro-storage";
|
|
84
|
+
import { createIndexedDBBackend } from "react-native-nitro-storage/indexeddb-backend";
|
|
85
|
+
|
|
86
|
+
const backend = await createIndexedDBBackend("app-secure", "keyvalue", {
|
|
87
|
+
channelName: "app-secure-sync",
|
|
88
|
+
onError: (error) => {
|
|
89
|
+
console.error("IndexedDB secure storage failed", error);
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
setWebSecureStorageBackend(backend);
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Reads are synchronous because they are served from memory after initial load. Writes update memory first and persist to IndexedDB in the background.
|
|
97
|
+
|
|
98
|
+
## Cross-tab Updates
|
|
99
|
+
|
|
100
|
+
The IndexedDB backend uses `BroadcastChannel` when available. Other tabs receive cache invalidation events and update their in-memory copy.
|
|
101
|
+
|
|
102
|
+
If you provide your own backend, implement `subscribe(listener)` to keep Nitro Storage caches aligned with external writes.
|
|
103
|
+
|
|
104
|
+
## Testing Backend
|
|
105
|
+
|
|
106
|
+
```ts
|
|
107
|
+
import type { WebStorageBackend } from "react-native-nitro-storage";
|
|
108
|
+
|
|
109
|
+
export function createMemoryBackend(): WebStorageBackend {
|
|
110
|
+
const values = new Map<string, string>();
|
|
111
|
+
const listeners = new Set<
|
|
112
|
+
(event: { key: string | null; newValue: string | null }) => void
|
|
113
|
+
>();
|
|
114
|
+
|
|
115
|
+
function emit(key: string | null, newValue: string | null) {
|
|
116
|
+
listeners.forEach((listener) => listener({ key, newValue }));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
name: "memory",
|
|
121
|
+
getItem: (key) => values.get(key) ?? null,
|
|
122
|
+
setItem: (key, value) => {
|
|
123
|
+
values.set(key, value);
|
|
124
|
+
emit(key, value);
|
|
125
|
+
},
|
|
126
|
+
removeItem: (key) => {
|
|
127
|
+
values.delete(key);
|
|
128
|
+
emit(key, null);
|
|
129
|
+
},
|
|
130
|
+
clear: () => {
|
|
131
|
+
values.clear();
|
|
132
|
+
emit(null, null);
|
|
133
|
+
},
|
|
134
|
+
getAllKeys: () => Array.from(values.keys()),
|
|
135
|
+
subscribe: (listener) => {
|
|
136
|
+
listeners.add(listener);
|
|
137
|
+
return () => listeners.delete(listener);
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
```
|