react-native-nitro-storage 0.8.0 → 0.10.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 +107 -25
- package/README.md +140 -27
- package/android/src/main/cpp/AndroidStorageAdapterCpp.cpp +5 -2
- package/android/src/main/java/com/nitrostorage/AndroidStorageAdapter.kt +240 -34
- package/cpp/bindings/HybridStorage.cpp +109 -293
- package/cpp/bindings/HybridStorage.hpp +17 -10
- package/docs/api-reference.md +75 -19
- package/docs/benchmarks.md +6 -1
- package/docs/keychain-lifecycle-testing.md +36 -0
- package/docs/recipes.md +1 -2
- package/docs/secure-storage.md +45 -9
- package/ios/IOSStorageAdapterCpp.mm +391 -175
- package/lib/commonjs/capabilities.js +3 -1
- package/lib/commonjs/capabilities.js.map +1 -1
- package/lib/commonjs/core/durability.js +110 -43
- package/lib/commonjs/core/durability.js.map +1 -1
- package/lib/commonjs/index.js +15 -5
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.web.js +219 -97
- package/lib/commonjs/index.web.js.map +1 -1
- package/lib/commonjs/internal.js +3 -11
- package/lib/commonjs/internal.js.map +1 -1
- package/lib/commonjs/shared.js +62 -2
- package/lib/commonjs/shared.js.map +1 -1
- package/lib/commonjs/storage-core.js +859 -145
- package/lib/commonjs/storage-core.js.map +1 -1
- package/lib/commonjs/storage-runtime.js +5 -1
- package/lib/commonjs/storage-runtime.js.map +1 -1
- package/lib/commonjs/testing.js +13 -0
- package/lib/commonjs/testing.js.map +1 -1
- package/lib/module/capabilities.js +2 -1
- package/lib/module/capabilities.js.map +1 -1
- package/lib/module/core/durability.js +110 -43
- package/lib/module/core/durability.js.map +1 -1
- package/lib/module/index.js +12 -8
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.web.js +215 -99
- package/lib/module/index.web.js.map +1 -1
- package/lib/module/internal.js +2 -9
- package/lib/module/internal.js.map +1 -1
- package/lib/module/shared.js +60 -2
- package/lib/module/shared.js.map +1 -1
- package/lib/module/storage-core.js +860 -146
- package/lib/module/storage-core.js.map +1 -1
- package/lib/module/storage-runtime.js +4 -1
- package/lib/module/storage-runtime.js.map +1 -1
- package/lib/module/testing.js +8 -1
- package/lib/module/testing.js.map +1 -1
- package/lib/typescript/capabilities.d.ts +2 -1
- package/lib/typescript/capabilities.d.ts.map +1 -1
- package/lib/typescript/core/durability.d.ts +7 -2
- package/lib/typescript/core/durability.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +2 -2
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/index.web.d.ts +3 -29
- package/lib/typescript/index.web.d.ts.map +1 -1
- package/lib/typescript/internal.d.ts +0 -2
- package/lib/typescript/internal.d.ts.map +1 -1
- package/lib/typescript/shared.d.ts +19 -0
- package/lib/typescript/shared.d.ts.map +1 -1
- package/lib/typescript/storage-core.d.ts +12 -3
- package/lib/typescript/storage-core.d.ts.map +1 -1
- package/lib/typescript/storage-runtime.d.ts +2 -1
- package/lib/typescript/storage-runtime.d.ts.map +1 -1
- package/lib/typescript/testing.d.ts +1 -1
- package/lib/typescript/testing.d.ts.map +1 -1
- package/nitrogen/generated/shared/c++/HybridStorageSpec.hpp +1 -1
- package/package.json +3 -3
- package/react-native-nitro-storage.podspec +3 -1
- package/src/capabilities.ts +3 -1
- package/src/core/durability.ts +139 -39
- package/src/index.ts +20 -10
- package/src/index.web.ts +328 -166
- package/src/internal.ts +0 -14
- package/src/shared.ts +85 -0
- package/src/storage-core.ts +1165 -199
- package/src/storage-runtime.ts +6 -0
- package/src/testing.ts +8 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,9 +2,91 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented in this file.
|
|
4
4
|
|
|
5
|
-
The format
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
Breaking changes are always listed first in each release section.
|
|
6
8
|
|
|
7
|
-
## 0.
|
|
9
|
+
## [0.10.0] - 2026-08-25
|
|
10
|
+
|
|
11
|
+
### Breaking changes
|
|
12
|
+
|
|
13
|
+
- None when upgrading from `0.9.x`. Direct upgrades from `0.8.x` or earlier
|
|
14
|
+
still require Nitro Modules `0.37.x` and a native rebuild as described in
|
|
15
|
+
the `0.9.0` entry. This release restores the previous set-item type and
|
|
16
|
+
secure-write defaults for existing consumers.
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
|
|
20
|
+
- Added `isStorageError(error, code)` to select recovery behavior from an exact
|
|
21
|
+
stable storage error code on native and web.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- Restored `SetStorageItem.get()` and its `item` property to the original
|
|
26
|
+
`Record<string, true>` compatibility shape. Added `getTyped()` for new code
|
|
27
|
+
that wants `Partial<Record<TMember, true>>` without forcing a type migration.
|
|
28
|
+
- Restored synchronous Android Secure writes by default. Asynchronous
|
|
29
|
+
`apply()` writes remain available through the explicit
|
|
30
|
+
`storage.setSecureWritesAsync(true)` opt-in and can be drained with
|
|
31
|
+
`storage.flushSecureWrites()`.
|
|
32
|
+
- Enabled raw read-cache lookups now reuse cached missing values in single and
|
|
33
|
+
batch reads without per-item fallback calls.
|
|
34
|
+
|
|
35
|
+
### Deprecated
|
|
36
|
+
|
|
37
|
+
- Deprecated `isKeychainLockedError()`. It remains backward compatible but
|
|
38
|
+
groups `keychain_locked`, `authentication_required`, and `key_invalidated`;
|
|
39
|
+
use `isStorageError()` when deciding whether to retry, authenticate, or
|
|
40
|
+
rebuild a credential.
|
|
41
|
+
|
|
42
|
+
### Documentation
|
|
43
|
+
|
|
44
|
+
- Documented secure-storage recovery semantics and warned against cached
|
|
45
|
+
fallback for authentication tokens unless stale credentials are an explicit
|
|
46
|
+
application policy.
|
|
47
|
+
- Clarified isolated web benchmark limits and corrected capability/API examples.
|
|
48
|
+
|
|
49
|
+
## [0.9.0] - 2026-08-20
|
|
50
|
+
|
|
51
|
+
### Breaking changes
|
|
52
|
+
|
|
53
|
+
- `react-native-nitro-modules` now has a peer range of `>=0.37.0 <0.38.0`.
|
|
54
|
+
Upgrade Nitro Modules and rebuild the native app before using Nitro Storage
|
|
55
|
+
0.9.0; the previous 0.36.x range is not supported.
|
|
56
|
+
- `SetStorageItem.get()` now returns `Partial<Record<TMember, true>>`. Use
|
|
57
|
+
`has()` for membership checks or handle an indexed value as `true | undefined`
|
|
58
|
+
instead of assuming every member exists.
|
|
59
|
+
- Android Secure writes now default to asynchronous `apply()`. Call
|
|
60
|
+
`storage.setSecureWritesAsync(false)` when existing code depends on
|
|
61
|
+
synchronous `commit()` durability, or call `storage.flushSecureWrites()` at
|
|
62
|
+
deterministic persistence boundaries.
|
|
63
|
+
|
|
64
|
+
### Changed
|
|
65
|
+
|
|
66
|
+
- Regenerated the shipped Nitro bindings with Nitro Modules and Nitrogen 0.37.0
|
|
67
|
+
while preserving synchronous JSI storage behavior across native platforms.
|
|
68
|
+
- Native batch reads now preserve missing entries as `undefined`, matching the
|
|
69
|
+
TypeScript contract and allowing stored values that match the old internal
|
|
70
|
+
sentinel string.
|
|
71
|
+
- Secure write flushes now retain failed and unattempted last-write-wins entries
|
|
72
|
+
for retry instead of silently dropping them.
|
|
73
|
+
- iOS legacy Disk migration is conservative and retryable. A valid registry is
|
|
74
|
+
copied into the suite domain and each `standardUserDefaults` source is
|
|
75
|
+
removed only after target persistence is verified; malformed registries,
|
|
76
|
+
fallback or same-domain stores, conflicts, and failed persistence leave the
|
|
77
|
+
source and registry available for recovery.
|
|
78
|
+
|
|
79
|
+
### Fixed
|
|
80
|
+
|
|
81
|
+
- `storage.clearBiometric()` flushes pending Secure writes, clears the JS raw
|
|
82
|
+
cache before listener notification, uses a durable Android biometric clear,
|
|
83
|
+
surfaces failures, and emits the same Secure-scope `clear` event as a Secure
|
|
84
|
+
clear after success.
|
|
85
|
+
- Android biometric corruption is checked and recovered at preference-store
|
|
86
|
+
initialization instead of probing the full encrypted store on each
|
|
87
|
+
existence or deletion hot path.
|
|
88
|
+
|
|
89
|
+
## [0.8.0] - 2026-08-12
|
|
8
90
|
|
|
9
91
|
### Breaking changes
|
|
10
92
|
|
|
@@ -36,7 +118,7 @@ The format follows Keep a Changelog and the project adheres to SemVer.
|
|
|
36
118
|
- The IndexedDB backend reports affected keys when `flush()` fails and starts a best-effort flush on `pagehide` and hidden visibility changes.
|
|
37
119
|
- `setIfVersion()` is documented as optimistic (no backend-level atomicity); CAS guarantees are covered by race tests.
|
|
38
120
|
|
|
39
|
-
## 0.7.0 - 2026-07-30
|
|
121
|
+
## [0.7.0] - 2026-07-30
|
|
40
122
|
|
|
41
123
|
### Changes
|
|
42
124
|
|
|
@@ -47,7 +129,7 @@ The format follows Keep a Changelog and the project adheres to SemVer.
|
|
|
47
129
|
- Enforce Android biometric policy levels with distinct Keystore keys, propagate locked or invalidated biometric failures, and keep secure preference files excluded from backup.
|
|
48
130
|
- Preflight biometric store access before aggregate secure mutations and surface native commit or corruption-recovery failures.
|
|
49
131
|
|
|
50
|
-
## 0.6.0 - 2026-06-15
|
|
132
|
+
## [0.6.0] - 2026-06-15
|
|
51
133
|
|
|
52
134
|
### Added
|
|
53
135
|
|
|
@@ -75,7 +157,7 @@ type changes can affect advanced consumers:
|
|
|
75
157
|
- `StorageChangeOperation` gained the `"expire"` and `"clearGroup"` members. Exhaustive `switch` statements over a change event's `operation` need cases for the new members.
|
|
76
158
|
- `useStorage()` now returns a three-element tuple `[value, setter, actions]` (was two). Array destructuring such as `const [value, setStore] = useStorage(item)` is unaffected; only code that annotated the result with an explicit two-element tuple type needs to widen the annotation.
|
|
77
159
|
|
|
78
|
-
## 0.5.9 - 2026-06-11
|
|
160
|
+
## [0.5.9] - 2026-06-11
|
|
79
161
|
|
|
80
162
|
### Fixed
|
|
81
163
|
|
|
@@ -86,7 +168,7 @@ type changes can affect advanced consumers:
|
|
|
86
168
|
|
|
87
169
|
- Included `CHANGELOG.md` in the packed package docs.
|
|
88
170
|
|
|
89
|
-
## 0.5.8 - 2026-06-11
|
|
171
|
+
## [0.5.8] - 2026-06-11
|
|
90
172
|
|
|
91
173
|
### Changed
|
|
92
174
|
|
|
@@ -97,7 +179,7 @@ type changes can affect advanced consumers:
|
|
|
97
179
|
|
|
98
180
|
- Regenerate Nitrogen output and package build artifacts before pack-content audits so clean release and CI environments validate the actual published tarball.
|
|
99
181
|
|
|
100
|
-
## 0.5.7 - 2026-06-10
|
|
182
|
+
## [0.5.7] - 2026-06-10
|
|
101
183
|
|
|
102
184
|
### Added
|
|
103
185
|
|
|
@@ -115,7 +197,7 @@ type changes can affect advanced consumers:
|
|
|
115
197
|
- Keep native and web public TypeScript entrypoints aligned so IDEs infer storage setters and batch tuple results consistently across React Native and web imports.
|
|
116
198
|
- Keep the README, issue template, package metadata, and release notes aligned with the current `0.5.7` package surface.
|
|
117
199
|
|
|
118
|
-
## 0.5.6 - 2026-05-22
|
|
200
|
+
## [0.5.6] - 2026-05-22
|
|
119
201
|
|
|
120
202
|
### Added
|
|
121
203
|
|
|
@@ -137,7 +219,7 @@ type changes can affect advanced consumers:
|
|
|
137
219
|
- Remove package-owned Android native log spam for expected unavailable biometric storage paths.
|
|
138
220
|
- Modernize Android Gradle assignment syntax to avoid package-owned Gradle warnings.
|
|
139
221
|
|
|
140
|
-
## 0.5.4 - 2026-05-13
|
|
222
|
+
## [0.5.4] - 2026-05-13
|
|
141
223
|
|
|
142
224
|
### Fixed
|
|
143
225
|
|
|
@@ -148,7 +230,7 @@ type changes can affect advanced consumers:
|
|
|
148
230
|
- Publish GitHub Releases to npm through a Trusted Publishing/OIDC workflow.
|
|
149
231
|
- Resolve the package build's TypeScript binary lookup warning during release checks.
|
|
150
232
|
|
|
151
|
-
## 0.5.2 - 2026-04-27
|
|
233
|
+
## [0.5.2] - 2026-04-27
|
|
152
234
|
|
|
153
235
|
### Fixed
|
|
154
236
|
|
|
@@ -156,7 +238,7 @@ type changes can affect advanced consumers:
|
|
|
156
238
|
- Stabilize the release benchmark gate by sampling each benchmark three times while keeping the same regression thresholds.
|
|
157
239
|
- Correct package content check commands in the release documentation for current Bun.
|
|
158
240
|
|
|
159
|
-
## 0.5.1 - 2026-04-24
|
|
241
|
+
## [0.5.1] - 2026-04-24
|
|
160
242
|
|
|
161
243
|
### Added
|
|
162
244
|
|
|
@@ -174,7 +256,7 @@ type changes can affect advanced consumers:
|
|
|
174
256
|
- Document raw import/export workflows and warn that Secure exports expose secret values.
|
|
175
257
|
- Refactor the publish script to validate release docs, report check timings, support coverage gates, and avoid redundant pack dry-runs.
|
|
176
258
|
|
|
177
|
-
## 0.5.0 - 2026-04-18
|
|
259
|
+
## [0.5.0] - 2026-04-18
|
|
178
260
|
|
|
179
261
|
### Added
|
|
180
262
|
|
|
@@ -191,7 +273,7 @@ type changes can affect advanced consumers:
|
|
|
191
273
|
- Expand npm package description and keywords around React Native secure storage, biometric storage, Keychain, Android Keystore, Nitro Modules, MMKV migration, Expo SecureStore, Zustand/Jotai, and IndexedDB.
|
|
192
274
|
- Harden publish dry-runs, package docs syncing, and npm pack content validation.
|
|
193
275
|
|
|
194
|
-
## 0.4.5 - 2026-04-14
|
|
276
|
+
## [0.4.5] - 2026-04-14
|
|
195
277
|
|
|
196
278
|
### Added
|
|
197
279
|
|
|
@@ -236,7 +318,7 @@ type changes can affect advanced consumers:
|
|
|
236
318
|
- Fix web `import()` for Secure scope skipping `flushSecureWrites()` and `setSecureAccessControl()` before writing.
|
|
237
319
|
- Expand ProGuard/R8 keep rules with explicit method-signature patterns so JNI-callable methods survive aggressive R8 shrinking in release builds.
|
|
238
320
|
|
|
239
|
-
## 0.4.1 - 2026-03-04
|
|
321
|
+
## [0.4.1] - 2026-03-04
|
|
240
322
|
|
|
241
323
|
### Added
|
|
242
324
|
|
|
@@ -255,7 +337,7 @@ type changes can affect advanced consumers:
|
|
|
255
337
|
- Bump to **React 19.2.0** and **React Native 0.83.2** across workspace and example.
|
|
256
338
|
- Add `--provenance` flag to `npm publish` for npm supply-chain attestation.
|
|
257
339
|
|
|
258
|
-
## 0.4.0 - 2026-02-25
|
|
340
|
+
## [0.4.0] - 2026-02-25
|
|
259
341
|
|
|
260
342
|
### Added
|
|
261
343
|
|
|
@@ -275,7 +357,7 @@ type changes can affect advanced consumers:
|
|
|
275
357
|
- Keep iOS secure keychain cache/index behavior aligned with new prefix query and biometric-level paths.
|
|
276
358
|
- Expand README/API docs to cover the new public API surface with concrete TypeScript use-case snippets.
|
|
277
359
|
|
|
278
|
-
## 0.3.2 - 2026-02-22
|
|
360
|
+
## [0.3.2] - 2026-02-22
|
|
279
361
|
|
|
280
362
|
### Added
|
|
281
363
|
|
|
@@ -298,7 +380,7 @@ type changes can affect advanced consumers:
|
|
|
298
380
|
- Expand benchmark coverage to include Disk and Secure scope throughput checks and tighten regression thresholds.
|
|
299
381
|
- Expand README coverage so every public feature has a concrete TypeScript use-case example, including secure write flush, biometric/access-control usage, batch bootstrap, and storage utility workflows.
|
|
300
382
|
|
|
301
|
-
## 0.3.1 - 2026-02-16
|
|
383
|
+
## [0.3.1] - 2026-02-16
|
|
302
384
|
|
|
303
385
|
### Changed
|
|
304
386
|
|
|
@@ -315,7 +397,7 @@ type changes can affect advanced consumers:
|
|
|
315
397
|
- Fix global `storage.setAccessControl(...)` handling so non-item raw secure writes keep the configured level instead of being forced back to default.
|
|
316
398
|
- Fix Android secure key enumeration to return deduplicated key sets when secure and biometric stores share key names.
|
|
317
399
|
|
|
318
|
-
## 0.3.0 - 2026-02-15
|
|
400
|
+
## [0.3.0] - 2026-02-15
|
|
319
401
|
|
|
320
402
|
### Added
|
|
321
403
|
|
|
@@ -332,7 +414,7 @@ type changes can affect advanced consumers:
|
|
|
332
414
|
- Route native batch calls through true adapter-level batch APIs (HybridStorage + iOS/Android adapters) instead of per-key loops.
|
|
333
415
|
- Add read-through cache invalidation on scoped/key change events and native/web clear paths.
|
|
334
416
|
|
|
335
|
-
## 0.2.1 - 2026-02-15
|
|
417
|
+
## [0.2.1] - 2026-02-15
|
|
336
418
|
|
|
337
419
|
### Added
|
|
338
420
|
|
|
@@ -353,7 +435,7 @@ type changes can affect advanced consumers:
|
|
|
353
435
|
|
|
354
436
|
- Raise `react` peer dependency floor to `>=18.2.0`.
|
|
355
437
|
|
|
356
|
-
## 0.2.0 - 2026-02-15
|
|
438
|
+
## [0.2.0] - 2026-02-15
|
|
357
439
|
|
|
358
440
|
### Added
|
|
359
441
|
|
|
@@ -376,7 +458,7 @@ type changes can affect advanced consumers:
|
|
|
376
458
|
- Expand README with complete API behavior/throws documentation.
|
|
377
459
|
- Strengthen native and web test coverage for validation, TTL, migrations, and transactions.
|
|
378
460
|
|
|
379
|
-
## 0.1.4 - 2026-02-09
|
|
461
|
+
## [0.1.4] - 2026-02-09
|
|
380
462
|
|
|
381
463
|
### Added
|
|
382
464
|
|
|
@@ -390,13 +472,13 @@ type changes can affect advanced consumers:
|
|
|
390
472
|
|
|
391
473
|
- Bump react-native-nitro-modules to the latest version and raise the peer dependency floor.
|
|
392
474
|
|
|
393
|
-
## 0.1.3 - 2026-01-22
|
|
475
|
+
## [0.1.3] - 2026-01-22
|
|
394
476
|
|
|
395
477
|
### Fixed
|
|
396
478
|
|
|
397
479
|
- Prevent ProGuard from stripping the JNI class in release builds.
|
|
398
480
|
|
|
399
|
-
## 0.1.2 - 2026-01-07
|
|
481
|
+
## [0.1.2] - 2026-01-07
|
|
400
482
|
|
|
401
483
|
### Added
|
|
402
484
|
|
|
@@ -407,7 +489,7 @@ type changes can affect advanced consumers:
|
|
|
407
489
|
|
|
408
490
|
- Point types to the correct path and simplify bob targets.
|
|
409
491
|
|
|
410
|
-
## 0.1.1 - 2025-12-15
|
|
492
|
+
## [0.1.1] - 2025-12-15
|
|
411
493
|
|
|
412
494
|
### Added
|
|
413
495
|
|
|
@@ -420,7 +502,7 @@ type changes can affect advanced consumers:
|
|
|
420
502
|
- Update README screenshots.
|
|
421
503
|
- Add tests for memory item deletion and MMKV migration, and simplify the README.
|
|
422
504
|
|
|
423
|
-
## 0.1.0 - 2025-12-15
|
|
505
|
+
## [0.1.0] - 2025-12-15
|
|
424
506
|
|
|
425
507
|
### Added
|
|
426
508
|
|
package/README.md
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
[](https://www.npmjs.com/package/react-native-nitro-storage)
|
|
5
5
|
[](https://github.com/JoaoPauloCMarra/react-native-nitro-storage/actions/workflows/ci.yml)
|
|
6
6
|
[](https://github.com/JoaoPauloCMarra/react-native-nitro-storage/blob/main/LICENSE)
|
|
7
|
-
[](https://docs.expo.dev/versions/v57.0.0/)
|
|
9
|
-
[](https://reactnative.dev/docs/0.86/getting-started-without-a-framework)
|
|
8
|
+
[](https://docs.expo.dev/versions/v57.0.0/)
|
|
9
|
+
[](https://nitro.margelo.com/)
|
|
10
10
|
[](https://www.typescriptlang.org/)
|
|
11
11
|
|
|
12
12
|
Synchronous Memory, Disk, and Secure storage for React Native, Expo development
|
|
@@ -24,8 +24,10 @@ pagination, conflict resolution, or remote synchronization.
|
|
|
24
24
|
## Contents
|
|
25
25
|
|
|
26
26
|
- [Install](#install)
|
|
27
|
+
- [Requirements and compatibility](#requirements-and-compatibility)
|
|
27
28
|
- [Expo Config](#expo-config)
|
|
28
29
|
- [Quick Start](#quick-start)
|
|
30
|
+
- [Auth Tokens](#auth-tokens)
|
|
29
31
|
- [Typed Storage Items](#typed-storage-items)
|
|
30
32
|
- [Item Ergonomics](#item-ergonomics)
|
|
31
33
|
- [Set Items](#set-items)
|
|
@@ -51,18 +53,41 @@ pagination, conflict resolution, or remote synchronization.
|
|
|
51
53
|
bun add react-native-nitro-storage react-native-nitro-modules
|
|
52
54
|
```
|
|
53
55
|
|
|
56
|
+
## Requirements and compatibility
|
|
57
|
+
|
|
54
58
|
Peer dependencies:
|
|
55
59
|
|
|
56
60
|
| Package | Version |
|
|
57
61
|
| ---------------------------- | ------------------ |
|
|
58
62
|
| `react` | `>=18.2.0` |
|
|
59
63
|
| `react-native` | `>=0.75.0` |
|
|
60
|
-
| `react-native-nitro-modules` | `>=0.
|
|
64
|
+
| `react-native-nitro-modules` | `>=0.37.0 <0.38.0` |
|
|
65
|
+
|
|
66
|
+
Nitro peer requirement: `react-native-nitro-modules >=0.37.0 <0.38.0`.
|
|
61
67
|
|
|
62
|
-
|
|
68
|
+
The package gate uses React Native `0.86.2` and the Strict TypeScript API.
|
|
69
|
+
`check:ci` also compiles the public source against React Native `0.87.0`'s
|
|
70
|
+
Strict TypeScript API; this does not change the runtime baseline. The Expo
|
|
71
|
+
example uses Expo SDK `57.0.16`, React Native
|
|
72
|
+
`0.86.2`, React `19.2.3`, and Nitro Modules `0.37.0`, which is the React Native
|
|
73
|
+
version supported by that Expo SDK. Do not override Expo's React Native version.
|
|
63
74
|
|
|
64
|
-
|
|
65
|
-
|
|
75
|
+
When upgrading from 0.8.x or 0.9.x, upgrade Nitro Modules to the 0.37.x range
|
|
76
|
+
before installing this package, then rebuild the native app so the generated
|
|
77
|
+
Nitro bindings and native runtime use the same major-minor version:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
bun add react-native-nitro-modules@0.37.0 react-native-nitro-storage@0.10.0
|
|
81
|
+
bunx expo prebuild
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`SetStorageItem.get()` retains its original `Record<string, true>` compatibility
|
|
85
|
+
shape. At runtime, absent members are still absent, so use `set.has(member)` for
|
|
86
|
+
membership checks. New code that wants a precise member union can use
|
|
87
|
+
`set.getTyped()`, which returns `Partial<Record<TMember, true>>`.
|
|
88
|
+
|
|
89
|
+
Nitro Storage requires an Expo development build or a bare React Native app;
|
|
90
|
+
Expo Go and native Windows, macOS, and tvOS targets are not supported.
|
|
66
91
|
|
|
67
92
|
For Expo development builds:
|
|
68
93
|
|
|
@@ -129,6 +154,45 @@ const theme = themeItem.get();
|
|
|
129
154
|
const raw = storage.getString("settings:theme", StorageScope.Disk);
|
|
130
155
|
```
|
|
131
156
|
|
|
157
|
+
`storage.getString` / `setString` remain the raw API. Prefer typed items for
|
|
158
|
+
application state.
|
|
159
|
+
|
|
160
|
+
Native storage calls are synchronous JSI operations. Keep values and batches
|
|
161
|
+
small enough for the JavaScript event loop; native and configured web-backend
|
|
162
|
+
failures throw errors. Secure cache fallback is opt-in through
|
|
163
|
+
`fallbackToCacheOnReadError`.
|
|
164
|
+
|
|
165
|
+
## Auth Tokens
|
|
166
|
+
|
|
167
|
+
Use `createSecureAuthStorage` for access and refresh tokens. `renameFrom`
|
|
168
|
+
copies a legacy key on first read and deletes it, so you do not need a custom
|
|
169
|
+
migration helper.
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
import { createSecureAuthStorage } from "react-native-nitro-storage";
|
|
173
|
+
|
|
174
|
+
const auth = createSecureAuthStorage(
|
|
175
|
+
{
|
|
176
|
+
accessToken: { renameFrom: "authToken" },
|
|
177
|
+
refreshToken: { renameFrom: "refreshToken" },
|
|
178
|
+
},
|
|
179
|
+
{ namespace: "auth" },
|
|
180
|
+
);
|
|
181
|
+
|
|
182
|
+
auth.accessToken.set("access-token");
|
|
183
|
+
const current = auth.accessToken.get();
|
|
184
|
+
auth.accessToken.subscribe(() => {});
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
Keep `getString` facades only when the app owns a storage architecture
|
|
188
|
+
boundary. `createSecureAuthStorage` already namespaces keys, notifies
|
|
189
|
+
subscribers, and migrates legacy keys.
|
|
190
|
+
|
|
191
|
+
Do not enable `fallbackToCacheOnReadError` for access or refresh tokens unless
|
|
192
|
+
the application explicitly accepts stale or revoked credentials. Handle
|
|
193
|
+
temporary secure-storage errors and retry from application lifecycle state
|
|
194
|
+
instead.
|
|
195
|
+
|
|
132
196
|
## Typed Storage Items
|
|
133
197
|
|
|
134
198
|
`createStorageItem<T>()` is the recommended API for application code. It keeps
|
|
@@ -194,8 +258,11 @@ loginMethod.setOrDelete(maybeMethod); // null/undefined deletes, value sets
|
|
|
194
258
|
## Set Items
|
|
195
259
|
|
|
196
260
|
`createSetItem()` models set-membership state (seen ids, dismissed prompts)
|
|
197
|
-
without hand-rolling
|
|
198
|
-
|
|
261
|
+
without hand-rolling membership helpers. Its compatibility `get()` result is a
|
|
262
|
+
`Record<string, true>`; absent members are still not stored at runtime. Use
|
|
263
|
+
`getTyped()` when a precise `Partial<Record<TMember, true>>` result is useful.
|
|
264
|
+
Adding an existing member or deleting an absent one is a no-op, so subscribers
|
|
265
|
+
do not re-render.
|
|
199
266
|
|
|
200
267
|
```ts
|
|
201
268
|
import { createSetItem, StorageScope } from "react-native-nitro-storage";
|
|
@@ -331,7 +398,7 @@ import {
|
|
|
331
398
|
StorageScope,
|
|
332
399
|
createSecureAuthStorage,
|
|
333
400
|
createStorageItem,
|
|
334
|
-
|
|
401
|
+
isStorageError,
|
|
335
402
|
storage,
|
|
336
403
|
} from "react-native-nitro-storage";
|
|
337
404
|
|
|
@@ -362,7 +429,7 @@ const auth = createSecureAuthStorage({
|
|
|
362
429
|
try {
|
|
363
430
|
recoveryCode.get();
|
|
364
431
|
} catch (error) {
|
|
365
|
-
if (
|
|
432
|
+
if (isStorageError(error, "keychain_locked")) {
|
|
366
433
|
storage.getSecurityCapabilities();
|
|
367
434
|
}
|
|
368
435
|
}
|
|
@@ -374,6 +441,15 @@ exporting secure values unless you are intentionally doing a short-lived
|
|
|
374
441
|
in-memory migration. `storage.export(StorageScope.Secure)` throws unless you
|
|
375
442
|
explicitly opt into `{ includeSecureValues: true }`.
|
|
376
443
|
|
|
444
|
+
Android secure writes default to synchronous `commit()` durability. Call
|
|
445
|
+
`storage.setSecureWritesAsync(true)` only when asynchronous `apply()` writes are
|
|
446
|
+
acceptable. After opting into async writes, call `storage.flushSecureWrites()`
|
|
447
|
+
before a deterministic persistence boundary. A failed secure flush throws and
|
|
448
|
+
keeps failed or unattempted queued writes available for retry.
|
|
449
|
+
`storage.clearBiometric()`
|
|
450
|
+
flushes pending Secure writes before clearing biometric entries and surfaces
|
|
451
|
+
native clear failures.
|
|
452
|
+
|
|
377
453
|
On Android 11 and newer, `BiometricLevel.BiometryOnly` and
|
|
378
454
|
`BiometricLevel.BiometryOrPasscode` use separate Keystore policies. Android 10
|
|
379
455
|
and older support `BiometryOrPasscode`; `BiometryOnly` throws
|
|
@@ -381,15 +457,21 @@ and older support `BiometryOrPasscode`; `BiometryOnly` throws
|
|
|
381
457
|
biometric-only distinction. Promoting a value to biometric storage removes the
|
|
382
458
|
plain secure copy on every platform, so plain reads cannot return a stale
|
|
383
459
|
value. Secure existence, discovery, and cleanup operations
|
|
384
|
-
can also throw when a protected store is locked or its key is invalidated.
|
|
385
|
-
|
|
386
|
-
|
|
460
|
+
can also throw when a protected store is locked or its key is invalidated. Use
|
|
461
|
+
`isStorageError()` to choose the correct recovery path: retry
|
|
462
|
+
`keychain_locked` after unlock, request user interaction for
|
|
463
|
+
`authentication_required`, and rebuild the affected credential for
|
|
464
|
+
`key_invalidated`.
|
|
387
465
|
|
|
388
466
|
## Batch Operations
|
|
389
467
|
|
|
390
468
|
`getBatch()` preserves tuple value types, so IDEs infer each result from the
|
|
391
469
|
matching item. `setBatch()` validates every item/value pair independently,
|
|
392
470
|
including heterogeneous batches.
|
|
471
|
+
Missing keys use each item's `defaultValue`; the native bridge preserves missing
|
|
472
|
+
entries as `undefined` while reading the batch. With `readCache: true`, item and
|
|
473
|
+
batch reads reuse raw cache entries, including cached missing values, until a
|
|
474
|
+
write, delete, clear, or external change invalidates the entry.
|
|
393
475
|
|
|
394
476
|
```ts
|
|
395
477
|
import { getBatch, removeBatch, setBatch } from "react-native-nitro-storage";
|
|
@@ -506,15 +588,17 @@ import {
|
|
|
506
588
|
} from "react-native-nitro-storage";
|
|
507
589
|
import { createIndexedDBBackend } from "react-native-nitro-storage/indexeddb-backend";
|
|
508
590
|
|
|
509
|
-
const backend = await createIndexedDBBackend(
|
|
510
|
-
dbName: "app-storage",
|
|
511
|
-
storeName: "kv",
|
|
512
|
-
});
|
|
591
|
+
const backend = await createIndexedDBBackend("app-storage", "kv");
|
|
513
592
|
|
|
514
593
|
setWebDiskStorageBackend(backend);
|
|
515
594
|
setWebSecureStorageBackend(backend);
|
|
516
595
|
```
|
|
517
596
|
|
|
597
|
+
Web reads and mutations stay synchronous against the backend's in-memory
|
|
598
|
+
contract; use `flushWebStorageBackends()` for asynchronous persistence
|
|
599
|
+
boundaries. The native entry keeps the web backend setters, getters, and flush
|
|
600
|
+
function as typed no-ops for cross-platform code.
|
|
601
|
+
|
|
518
602
|
Browser storage cannot provide iOS Keychain or Android Keystore guarantees. Web
|
|
519
603
|
Secure scope is only as strong as the backend you configure.
|
|
520
604
|
|
|
@@ -543,14 +627,38 @@ beforeEach(() => {
|
|
|
543
627
|
const { storage, memoryItem } = createNitroStorageMock();
|
|
544
628
|
```
|
|
545
629
|
|
|
630
|
+
## API
|
|
631
|
+
|
|
632
|
+
The package exposes named `storage`, `createStorageItem`, the scoped item
|
|
633
|
+
factories, `createSetItem`, batch operations, migration and transaction helpers,
|
|
634
|
+
secure-auth storage, React hooks, and web backend utilities. Values are bound to
|
|
635
|
+
`Memory`, `Disk`, or `Secure` and support typed single-key operations, raw
|
|
636
|
+
inspection, events and observers, cache and write-flush controls, secure
|
|
637
|
+
metadata, transactional migrations with rename/rollback, and configurable web
|
|
638
|
+
backends. The full reference lives in
|
|
639
|
+
[docs/api-reference.md](docs/api-reference.md).
|
|
640
|
+
|
|
641
|
+
## Error Contract
|
|
642
|
+
|
|
643
|
+
Native and web adapters tag classified failures with stable error codes. Use
|
|
644
|
+
`getStorageErrorCode(error)` or `isStorageError(error, code)` to branch on them:
|
|
645
|
+
`keychain_locked` reports a locked Keychain that a retry can recover after
|
|
646
|
+
authentication, secure-scope write or biometric failures carry their own
|
|
647
|
+
codes, and invalid inputs (bad scope, malformed keys, numeric guard
|
|
648
|
+
violations) are rejected before reaching native storage. Errors never swallow
|
|
649
|
+
the underlying cause silently: the original platform message is preserved on
|
|
650
|
+
the error for diagnostics.
|
|
651
|
+
|
|
546
652
|
## Platform Support
|
|
547
653
|
|
|
548
|
-
| Platform
|
|
549
|
-
|
|
|
550
|
-
| iOS
|
|
551
|
-
| Android
|
|
552
|
-
| Web
|
|
553
|
-
| Expo
|
|
654
|
+
| Platform | Status |
|
|
655
|
+
| ---------------------- | -------------------------------------------------- |
|
|
656
|
+
| iOS | Memory, Disk, and Keychain-backed Secure storage. |
|
|
657
|
+
| Android | Memory, Disk, and Keystore-backed Secure storage. |
|
|
658
|
+
| Web | Memory plus configurable Disk and Secure backends. |
|
|
659
|
+
| Expo development build | Supported with the config plugin. |
|
|
660
|
+
| Expo Go | Not supported for Nitro native modules. |
|
|
661
|
+
| Windows, macOS, tvOS | Not supported by this package. |
|
|
554
662
|
|
|
555
663
|
## Documentation
|
|
556
664
|
|
|
@@ -594,9 +702,14 @@ bun run example:android
|
|
|
594
702
|
bun run example:ios
|
|
595
703
|
```
|
|
596
704
|
|
|
597
|
-
Run native example builds before release when changing plugin, native,
|
|
598
|
-
secure storage, or packaging files.
|
|
599
|
-
package
|
|
705
|
+
Run native example builds locally before release when changing plugin, native,
|
|
706
|
+
Nitro, secure storage, or packaging files. GitHub CI does not build the Android
|
|
707
|
+
or iOS example. The package release path also validates package contents and
|
|
708
|
+
dry-run publish behavior.
|
|
709
|
+
|
|
710
|
+
`bun run benchmark` measures only the built web entry with an isolated private
|
|
711
|
+
localStorage implementation; it is not a native Disk or Secure benchmark. See
|
|
712
|
+
[docs/benchmarks.md](docs/benchmarks.md) for sampling and interpretation limits.
|
|
600
713
|
|
|
601
714
|
## License
|
|
602
715
|
|
|
@@ -40,8 +40,11 @@ std::vector<std::string> fromJavaStringArray(alias_ref<JavaStringArray> values)
|
|
|
40
40
|
result.reserve(size);
|
|
41
41
|
for (jsize i = 0; i < size; ++i) {
|
|
42
42
|
auto currentValue = values->getElement(i);
|
|
43
|
-
//
|
|
44
|
-
|
|
43
|
+
// Null entries are dropped so a missing key can never surface as the
|
|
44
|
+
// empty-string clear sentinel used by change listeners.
|
|
45
|
+
if (currentValue) {
|
|
46
|
+
result.push_back(currentValue->toStdString());
|
|
47
|
+
}
|
|
45
48
|
}
|
|
46
49
|
return result;
|
|
47
50
|
}
|