react-native-nitro-storage 0.5.0 → 0.5.2
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 +42 -8
- package/docs/api-reference.md +95 -31
- package/docs/batch-transactions-migrations.md +23 -9
- package/docs/benchmarks.md +1 -1
- package/docs/recipes.md +30 -9
- package/docs/secure-storage.md +20 -1
- package/lib/commonjs/index.js +214 -13
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +166 -11
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/indexeddb-backend.js +7 -0
- package/lib/commonjs/indexeddb-backend.js.map +1 -1
- package/lib/commonjs/storage-events.js +117 -0
- package/lib/commonjs/storage-events.js.map +1 -0
- package/lib/module/index.js +214 -13
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +166 -11
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/indexeddb-backend.js +7 -0
- package/lib/module/indexeddb-backend.js.map +1 -1
- package/lib/module/storage-events.js +112 -0
- package/lib/module/storage-events.js.map +1 -0
- package/lib/typescript/index.d.ts +14 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +14 -0
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/indexeddb-backend.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/package.json +5 -4
- package/src/index.ts +534 -13
- package/src/index.web.ts +459 -22
- package/src/indexeddb-backend.ts +8 -0
- package/src/storage-events.ts +184 -0
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/react-native-nitro-storage)
|
|
4
4
|
[](LICENSE)
|
|
5
5
|
[](https://reactnative.dev/)
|
|
6
|
-
[](https://nitro.margelo.com/)
|
|
7
7
|
|
|
8
8
|
One storage layer for render-time state, persisted app state, and native secrets.
|
|
9
9
|
|
|
@@ -42,6 +42,7 @@ Use it when you want one storage API for React Native and web, with fast synchro
|
|
|
42
42
|
| Move existing MMKV data | `migrateFromMMKV` |
|
|
43
43
|
| Persist storage on web | `setWebDiskStorageBackend` or `createIndexedDBBackend` |
|
|
44
44
|
| Inspect secure backend state | `getSecurityCapabilities`, `getSecureMetadata`, metadata APIs |
|
|
45
|
+
| Connect external state/debug code | `subscribeNamespace`, `subscribePrefix`, `setEventObserver` |
|
|
45
46
|
|
|
46
47
|
## Use It When
|
|
47
48
|
|
|
@@ -56,7 +57,7 @@ Use a database or server-state cache instead when you need relational queries, c
|
|
|
56
57
|
- Three scopes: in-memory session state, persisted disk state, and platform secure storage.
|
|
57
58
|
- Secure storage backed by iOS Keychain and Android Keystore/EncryptedSharedPreferences.
|
|
58
59
|
- React hooks without providers: `useStorage`, `useStorageSelector`, and `useSetStorage`.
|
|
59
|
-
- Batch reads/writes, namespace cleanup, raw import/export, transactions, and migrations.
|
|
60
|
+
- Batch reads/writes, namespace cleanup, raw import/export, event subscriptions, transactions, and migrations.
|
|
60
61
|
- Web parity with configurable Disk/Secure backends and an IndexedDB backend.
|
|
61
62
|
- MMKV migration helper for moving existing keys without rewriting app code first.
|
|
62
63
|
|
|
@@ -188,6 +189,37 @@ runTransaction(StorageScope.Disk, (tx) => {
|
|
|
188
189
|
});
|
|
189
190
|
```
|
|
190
191
|
|
|
192
|
+
Create a raw snapshot for backups or test fixtures, then restore it later:
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
import { StorageScope, storage } from "react-native-nitro-storage";
|
|
196
|
+
|
|
197
|
+
const snapshot = storage.export(StorageScope.Disk);
|
|
198
|
+
|
|
199
|
+
storage.import(snapshot, StorageScope.Disk);
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
`storage.export(StorageScope.Secure)` returns raw secret values. Do not log Secure exports or include them in diagnostics, analytics, crash reports, or support bundles.
|
|
203
|
+
|
|
204
|
+
Subscribe to storage changes outside React:
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
import { StorageScope, storage } from "react-native-nitro-storage";
|
|
208
|
+
|
|
209
|
+
const unsubscribe = storage.subscribeNamespace(
|
|
210
|
+
"settings",
|
|
211
|
+
StorageScope.Disk,
|
|
212
|
+
(event) => {
|
|
213
|
+
if (event.type === "batch") {
|
|
214
|
+
console.log("settings changed", event.changes.length);
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
console.log(event.key, event.operation);
|
|
219
|
+
},
|
|
220
|
+
);
|
|
221
|
+
```
|
|
222
|
+
|
|
191
223
|
## Storage Scopes
|
|
192
224
|
|
|
193
225
|
| Scope | Backing store | Best for |
|
|
@@ -243,7 +275,7 @@ import {
|
|
|
243
275
|
The main building blocks are:
|
|
244
276
|
|
|
245
277
|
- `createStorageItem<T>(config)` for typed values.
|
|
246
|
-
- `storage` for raw reads, namespace cleanup, secure metadata, metrics, and runtime capability checks.
|
|
278
|
+
- `storage` for raw reads, namespace cleanup, events, secure metadata, metrics, and runtime capability checks.
|
|
247
279
|
- `getBatch`, `setBatch`, and `removeBatch` for multi-key work.
|
|
248
280
|
- `runTransaction` for synchronous rollback on failure.
|
|
249
281
|
- `registerMigration` and `migrateToLatest` for versioned local data migrations.
|
|
@@ -265,7 +297,7 @@ Peer dependencies:
|
|
|
265
297
|
|
|
266
298
|
- `react >=18.2.0`
|
|
267
299
|
- `react-native >=0.75.0`
|
|
268
|
-
- `react-native-nitro-modules >=0.35.
|
|
300
|
+
- `react-native-nitro-modules >=0.35.5`
|
|
269
301
|
|
|
270
302
|
## Security Model
|
|
271
303
|
|
|
@@ -355,9 +387,11 @@ bun run format:check -- --filter=react-native-nitro-storage
|
|
|
355
387
|
bun run typecheck -- --filter=react-native-nitro-storage
|
|
356
388
|
bun run test:types -- --filter=react-native-nitro-storage
|
|
357
389
|
bun run test -- --filter=react-native-nitro-storage
|
|
390
|
+
bun run test:coverage -- --filter=react-native-nitro-storage
|
|
358
391
|
bun run test:cpp -- --filter=react-native-nitro-storage
|
|
359
|
-
bun run --
|
|
360
|
-
|
|
392
|
+
bun run test:cpp:coverage -- --filter=react-native-nitro-storage
|
|
393
|
+
(cd packages/react-native-nitro-storage && bun run check:pack)
|
|
394
|
+
bun run publish-package:dry -- --yes --with-coverage
|
|
361
395
|
```
|
|
362
396
|
|
|
363
397
|
## Development
|
|
@@ -377,8 +411,8 @@ Release checks:
|
|
|
377
411
|
```sh
|
|
378
412
|
bun run build -- --filter=react-native-nitro-storage
|
|
379
413
|
bun run benchmark -- --filter=react-native-nitro-storage
|
|
380
|
-
|
|
381
|
-
|
|
414
|
+
(cd packages/react-native-nitro-storage && bun run check:pack)
|
|
415
|
+
bun run publish-package:dry -- --yes
|
|
382
416
|
```
|
|
383
417
|
|
|
384
418
|
## License
|
package/docs/api-reference.md
CHANGED
|
@@ -44,9 +44,20 @@ const item = createStorageItem<T>({
|
|
|
44
44
|
| `delete()` | Remove the key. |
|
|
45
45
|
| `has()` | Check whether the key exists. |
|
|
46
46
|
| `subscribe(callback)` | Subscribe to item changes. Returns an unsubscribe function. |
|
|
47
|
+
| `subscribeSelector(...)` | Subscribe to a selected value with an equality check. |
|
|
47
48
|
| `serialize(value)` | Serialize a value with the item encoder. |
|
|
48
49
|
| `deserialize(value)` | Deserialize a raw string with the item decoder. |
|
|
49
50
|
|
|
51
|
+
```ts
|
|
52
|
+
const unsubscribe = profileItem.subscribeSelector(
|
|
53
|
+
(profile) => profile.name,
|
|
54
|
+
(name, previousName) => {
|
|
55
|
+
console.log("Profile name changed", { name, previousName });
|
|
56
|
+
},
|
|
57
|
+
{ fireImmediately: true },
|
|
58
|
+
);
|
|
59
|
+
```
|
|
60
|
+
|
|
50
61
|
## React Hooks
|
|
51
62
|
|
|
52
63
|
```ts
|
|
@@ -61,37 +72,84 @@ See [react-hooks.md](react-hooks.md).
|
|
|
61
72
|
|
|
62
73
|
`storage` exposes raw and cross-item utilities:
|
|
63
74
|
|
|
64
|
-
| Method
|
|
65
|
-
|
|
|
66
|
-
| `clear(scope)`
|
|
67
|
-
| `clearAll()`
|
|
68
|
-
| `clearNamespace(namespace, scope)`
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
77
|
-
| `
|
|
78
|
-
| `
|
|
79
|
-
| `
|
|
80
|
-
| `
|
|
81
|
-
| `
|
|
82
|
-
| `
|
|
83
|
-
| `
|
|
84
|
-
| `
|
|
85
|
-
| `
|
|
86
|
-
| `
|
|
87
|
-
| `
|
|
88
|
-
| `
|
|
89
|
-
| `
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
|
|
94
|
-
|
|
75
|
+
| Method | Purpose |
|
|
76
|
+
| ------------------------------------------------ | ------------------------------------------------------------- |
|
|
77
|
+
| `clear(scope)` | Clear one scope. |
|
|
78
|
+
| `clearAll()` | Clear Memory, Disk, and Secure scopes. |
|
|
79
|
+
| `clearNamespace(namespace, scope)` | Remove keys under `namespace:`. |
|
|
80
|
+
| `subscribe(scope, listener)` | Subscribe to raw scope-level change events. |
|
|
81
|
+
| `subscribeKey(scope, key, listener)` | Subscribe to raw events for one key. |
|
|
82
|
+
| `subscribePrefix(scope, prefix, listener)` | Subscribe to raw events for matching key prefixes. |
|
|
83
|
+
| `subscribeNamespace(namespace, scope, listener)` | Subscribe to raw events for `namespace:` keys. |
|
|
84
|
+
| `setEventObserver(observer)` | Receive all change events for devtools or logging. |
|
|
85
|
+
| `clearBiometric()` | Clear biometric Secure entries. |
|
|
86
|
+
| `has(key, scope)` | Check for a raw key. |
|
|
87
|
+
| `getAllKeys(scope)` | List raw keys. |
|
|
88
|
+
| `getKeysByPrefix(prefix, scope)` | List raw keys with a prefix. |
|
|
89
|
+
| `getByPrefix(prefix, scope)` | Read raw string values by prefix. |
|
|
90
|
+
| `getAll(scope)` | Read all raw string values in a scope. |
|
|
91
|
+
| `size(scope)` | Return approximate scope entry count. |
|
|
92
|
+
| `setAccessControl(accessControl)` | Set the default Secure access control level. |
|
|
93
|
+
| `setSecureWritesAsync(enabled)` | Toggle Android secure writes between sync and async modes. |
|
|
94
|
+
| `setDiskWritesAsync(enabled)` | Toggle coalesced Disk write behavior. |
|
|
95
|
+
| `flushDiskWrites()` | Flush pending Disk writes. |
|
|
96
|
+
| `flushSecureWrites()` | Flush pending Secure writes. |
|
|
97
|
+
| `setKeychainAccessGroup(group)` | Configure iOS Keychain access group. |
|
|
98
|
+
| `setMetricsObserver(observer)` | Receive operation timing events. |
|
|
99
|
+
| `getMetricsSnapshot()` | Read aggregated metrics. |
|
|
100
|
+
| `resetMetrics()` | Clear metrics counters. |
|
|
101
|
+
| `getCapabilities()` | Read runtime storage capabilities. |
|
|
102
|
+
| `getSecurityCapabilities()` | Read secure backend capability metadata. |
|
|
103
|
+
| `getSecureMetadata(key)` | Read secure metadata for one key without returning its value. |
|
|
104
|
+
| `getAllSecureMetadata()` | Read secure metadata for all secure keys without values. |
|
|
105
|
+
| `getString(key, scope)` | Read a raw string. |
|
|
106
|
+
| `setString(key, value, scope)` | Write a raw string. |
|
|
107
|
+
| `deleteString(key, scope)` | Remove a raw key. |
|
|
108
|
+
| `export(scope)` | Snapshot raw strings from one scope. |
|
|
109
|
+
| `import(data, scope)` | Bulk import raw strings. |
|
|
110
|
+
|
|
111
|
+
Raw string APIs bypass item serialization and validation. Prefer `StorageItem<T>` unless you are migrating, exporting/importing, or writing a custom integration.
|
|
112
|
+
|
|
113
|
+
```ts
|
|
114
|
+
const diskSnapshot = storage.export(StorageScope.Disk);
|
|
115
|
+
storage.import(diskSnapshot, StorageScope.Disk);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Secure exports contain raw secret values. Do not log `storage.export(StorageScope.Secure)` output or attach it to diagnostics, analytics, crash reports, or support bundles.
|
|
119
|
+
|
|
120
|
+
## Event Subscriptions
|
|
121
|
+
|
|
122
|
+
Use raw subscriptions when integrating Nitro Storage with state managers, sync engines, debug tooling, or non-React code.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
const unsubscribe = storage.subscribeNamespace(
|
|
126
|
+
"auth",
|
|
127
|
+
StorageScope.Secure,
|
|
128
|
+
(event) => {
|
|
129
|
+
if (event.type === "batch") {
|
|
130
|
+
console.log(
|
|
131
|
+
"Auth keys changed",
|
|
132
|
+
event.changes.map((change) => change.key),
|
|
133
|
+
);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
console.log("Auth key changed", event.key, event.operation);
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
For whole-app debug tooling, install one observer:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
storage.setEventObserver((event) => {
|
|
146
|
+
if (event.scope !== StorageScope.Secure) {
|
|
147
|
+
console.log(event);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
Local batch APIs emit one `type: "batch"` envelope to scope and prefix/namespace listeners. Key subscribers receive the matching per-key change so direct key integrations do not need to unpack batch envelopes. Secure events can include raw secret values; do not log Secure event payloads in production.
|
|
95
153
|
|
|
96
154
|
## Batch Operations
|
|
97
155
|
|
|
@@ -201,6 +259,12 @@ Common public types:
|
|
|
201
259
|
- `StorageMetricsEvent`
|
|
202
260
|
- `StorageMetricsObserver`
|
|
203
261
|
- `StorageMetricSummary`
|
|
262
|
+
- `StorageChangeEvent`
|
|
263
|
+
- `StorageKeyChangeEvent`
|
|
264
|
+
- `StorageBatchChangeEvent`
|
|
265
|
+
- `StorageChangeOperation`
|
|
266
|
+
- `StorageChangeSource`
|
|
267
|
+
- `StorageEventListener`
|
|
204
268
|
- `MigrationContext`
|
|
205
269
|
- `Migration`
|
|
206
270
|
- `TransactionContext`
|
|
@@ -44,6 +44,22 @@ setBatch(
|
|
|
44
44
|
|
|
45
45
|
Memory-scope batch writes are two-phase: all values are written first, then listeners are notified. Items with validation or TTL fall back to per-item writes so those rules still run.
|
|
46
46
|
|
|
47
|
+
Scope and prefix subscriptions receive one batch event for raw batch writes and removes:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
const unsubscribe = storage.subscribePrefix(
|
|
51
|
+
StorageScope.Disk,
|
|
52
|
+
"settings:",
|
|
53
|
+
(event) => {
|
|
54
|
+
if (event.type === "batch") {
|
|
55
|
+
event.changes.forEach((change) => {
|
|
56
|
+
console.log(change.key, change.operation);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
);
|
|
61
|
+
```
|
|
62
|
+
|
|
47
63
|
## Batch Removes
|
|
48
64
|
|
|
49
65
|
```ts
|
|
@@ -52,24 +68,22 @@ import { removeBatch, StorageScope } from "react-native-nitro-storage";
|
|
|
52
68
|
removeBatch([themeItem, localeItem], StorageScope.Disk);
|
|
53
69
|
```
|
|
54
70
|
|
|
55
|
-
## Raw Import
|
|
71
|
+
## Raw Import and Export
|
|
56
72
|
|
|
57
|
-
`storage.import(data, scope)` writes raw strings.
|
|
73
|
+
`storage.export(scope)` returns raw strings, and `storage.import(data, scope)` writes raw strings. These APIs do not serialize values.
|
|
58
74
|
|
|
59
75
|
```ts
|
|
60
76
|
import { storage, StorageScope } from "react-native-nitro-storage";
|
|
61
77
|
|
|
62
|
-
storage.
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"flags:paywall": "control",
|
|
66
|
-
},
|
|
67
|
-
StorageScope.Disk,
|
|
68
|
-
);
|
|
78
|
+
const snapshot = storage.export(StorageScope.Disk);
|
|
79
|
+
|
|
80
|
+
storage.import(snapshot, StorageScope.Disk);
|
|
69
81
|
```
|
|
70
82
|
|
|
71
83
|
For Memory scope, import is atomic: all keys are written before listeners fire. For Disk and Secure, import delegates to native or web batch paths.
|
|
72
84
|
|
|
85
|
+
Secure exports contain raw secret values. Do not log them or include them in diagnostics, analytics, crash reports, or support bundles.
|
|
86
|
+
|
|
73
87
|
## Transactions
|
|
74
88
|
|
|
75
89
|
Use `runTransaction(scope, callback)` when several raw or item writes should roll back together if the callback throws.
|
package/docs/benchmarks.md
CHANGED
|
@@ -30,7 +30,7 @@ bun run test -- --filter=react-native-nitro-storage
|
|
|
30
30
|
bun run test:cpp -- --filter=react-native-nitro-storage
|
|
31
31
|
bun run build -- --filter=react-native-nitro-storage
|
|
32
32
|
bun run benchmark -- --filter=react-native-nitro-storage
|
|
33
|
-
|
|
33
|
+
(cd packages/react-native-nitro-storage && bun run check:pack)
|
|
34
34
|
npm publish --dry-run
|
|
35
35
|
```
|
|
36
36
|
|
package/docs/recipes.md
CHANGED
|
@@ -205,19 +205,15 @@ tokenItem.set("token");
|
|
|
205
205
|
storage.flushSecureWrites();
|
|
206
206
|
```
|
|
207
207
|
|
|
208
|
-
## Raw Import
|
|
208
|
+
## Raw Import and Export
|
|
209
209
|
|
|
210
210
|
```ts
|
|
211
|
-
storage.
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
"settings:locale": "en-US",
|
|
215
|
-
},
|
|
216
|
-
StorageScope.Disk,
|
|
217
|
-
);
|
|
211
|
+
const snapshot = storage.export(StorageScope.Disk);
|
|
212
|
+
|
|
213
|
+
storage.import(snapshot, StorageScope.Disk);
|
|
218
214
|
```
|
|
219
215
|
|
|
220
|
-
Raw import writes strings exactly as
|
|
216
|
+
Raw export/import reads and writes strings exactly as stored. It does not run item serializers. Secure exports contain raw secret values, so do not log them or attach them to diagnostics.
|
|
221
217
|
|
|
222
218
|
## Snapshot and Cleanup
|
|
223
219
|
|
|
@@ -259,6 +255,31 @@ const snapshot = storage.getMetricsSnapshot();
|
|
|
259
255
|
storage.resetMetrics();
|
|
260
256
|
```
|
|
261
257
|
|
|
258
|
+
## Event Logging
|
|
259
|
+
|
|
260
|
+
```ts
|
|
261
|
+
const unsubscribe = storage.subscribePrefix(
|
|
262
|
+
StorageScope.Disk,
|
|
263
|
+
"settings:",
|
|
264
|
+
(event) => {
|
|
265
|
+
if (event.type === "batch") {
|
|
266
|
+
console.log("settings changed", event.changes.length);
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
console.log(event.key, event.operation);
|
|
271
|
+
},
|
|
272
|
+
);
|
|
273
|
+
|
|
274
|
+
storage.setEventObserver((event) => {
|
|
275
|
+
if (event.scope !== StorageScope.Secure) {
|
|
276
|
+
console.log(event.type, event.operation);
|
|
277
|
+
}
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Use `subscribePrefix()` or `subscribeNamespace()` for targeted integrations. Use `setEventObserver()` for devtools-style logging. Secure events can include raw secret values, so filter them out of logs.
|
|
282
|
+
|
|
262
283
|
## Capability Checks
|
|
263
284
|
|
|
264
285
|
```ts
|
package/docs/secure-storage.md
CHANGED
|
@@ -114,6 +114,25 @@ const allKeys = storage.getAllSecureMetadata();
|
|
|
114
114
|
|
|
115
115
|
`getSecureMetadata()` and `getAllSecureMetadata()` never return stored secret values. They report key existence, storage kind, backend name, access-control metadata, and whether a metadata path accidentally exposed a value.
|
|
116
116
|
|
|
117
|
+
## Secure Export Warning
|
|
118
|
+
|
|
119
|
+
`storage.export(StorageScope.Secure)` returns raw secret values so it can round-trip with `storage.import(data, StorageScope.Secure)`.
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import { storage, StorageScope } from "react-native-nitro-storage";
|
|
123
|
+
|
|
124
|
+
const secureSnapshot = storage.export(StorageScope.Secure);
|
|
125
|
+
storage.import(secureSnapshot, StorageScope.Secure);
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Only keep Secure exports in memory for the shortest possible workflow. Do not log them or include them in diagnostics, analytics, crash reports, or support bundles.
|
|
129
|
+
|
|
130
|
+
## Secure Event Warning
|
|
131
|
+
|
|
132
|
+
Secure scope event subscriptions and `storage.setEventObserver()` can receive raw secret values in `oldValue`, `newValue`, or batch `changes`.
|
|
133
|
+
|
|
134
|
+
Use Secure events for in-memory coordination only. Do not log Secure event payloads or send them to analytics, crash reporting, support bundles, or devtools sessions that persist outside the device.
|
|
135
|
+
|
|
117
136
|
## Locked Keychain Errors
|
|
118
137
|
|
|
119
138
|
```ts
|
|
@@ -165,7 +184,7 @@ Before releasing secure-storage changes, run:
|
|
|
165
184
|
```sh
|
|
166
185
|
bun run test -- --filter=react-native-nitro-storage
|
|
167
186
|
bun run test:cpp -- --filter=react-native-nitro-storage
|
|
168
|
-
|
|
187
|
+
(cd packages/react-native-nitro-storage && bun run check:pack)
|
|
169
188
|
```
|
|
170
189
|
|
|
171
190
|
Also run an end-to-end auth flow on a locked/unlocked real device when changing biometric or Keychain behavior.
|