react-native-nitro-storage 0.3.0 → 0.3.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.
Files changed (53) hide show
  1. package/README.md +594 -247
  2. package/android/CMakeLists.txt +2 -0
  3. package/android/src/main/cpp/AndroidStorageAdapterCpp.cpp +102 -11
  4. package/android/src/main/cpp/AndroidStorageAdapterCpp.hpp +16 -0
  5. package/android/src/main/java/com/nitrostorage/AndroidStorageAdapter.kt +154 -34
  6. package/android/src/main/java/com/nitrostorage/NitroStoragePackage.kt +2 -2
  7. package/cpp/bindings/HybridStorage.cpp +176 -21
  8. package/cpp/bindings/HybridStorage.hpp +29 -2
  9. package/cpp/core/NativeStorageAdapter.hpp +16 -0
  10. package/ios/IOSStorageAdapterCpp.hpp +20 -0
  11. package/ios/IOSStorageAdapterCpp.mm +239 -32
  12. package/lib/commonjs/Storage.types.js +23 -1
  13. package/lib/commonjs/Storage.types.js.map +1 -1
  14. package/lib/commonjs/index.js +292 -75
  15. package/lib/commonjs/index.js.map +1 -1
  16. package/lib/commonjs/index.web.js +473 -86
  17. package/lib/commonjs/index.web.js.map +1 -1
  18. package/lib/commonjs/internal.js +10 -0
  19. package/lib/commonjs/internal.js.map +1 -1
  20. package/lib/commonjs/storage-hooks.js +36 -0
  21. package/lib/commonjs/storage-hooks.js.map +1 -0
  22. package/lib/module/Storage.types.js +22 -0
  23. package/lib/module/Storage.types.js.map +1 -1
  24. package/lib/module/index.js +264 -75
  25. package/lib/module/index.js.map +1 -1
  26. package/lib/module/index.web.js +445 -86
  27. package/lib/module/index.web.js.map +1 -1
  28. package/lib/module/internal.js +8 -0
  29. package/lib/module/internal.js.map +1 -1
  30. package/lib/module/storage-hooks.js +30 -0
  31. package/lib/module/storage-hooks.js.map +1 -0
  32. package/lib/typescript/Storage.nitro.d.ts +12 -0
  33. package/lib/typescript/Storage.nitro.d.ts.map +1 -1
  34. package/lib/typescript/Storage.types.d.ts +20 -0
  35. package/lib/typescript/Storage.types.d.ts.map +1 -1
  36. package/lib/typescript/index.d.ts +33 -10
  37. package/lib/typescript/index.d.ts.map +1 -1
  38. package/lib/typescript/index.web.d.ts +45 -10
  39. package/lib/typescript/index.web.d.ts.map +1 -1
  40. package/lib/typescript/internal.d.ts +2 -0
  41. package/lib/typescript/internal.d.ts.map +1 -1
  42. package/lib/typescript/storage-hooks.d.ts +10 -0
  43. package/lib/typescript/storage-hooks.d.ts.map +1 -0
  44. package/nitrogen/generated/shared/c++/HybridStorageSpec.cpp +12 -0
  45. package/nitrogen/generated/shared/c++/HybridStorageSpec.hpp +12 -0
  46. package/package.json +8 -3
  47. package/src/Storage.nitro.ts +13 -2
  48. package/src/Storage.types.ts +22 -0
  49. package/src/index.ts +382 -123
  50. package/src/index.web.ts +618 -134
  51. package/src/internal.ts +14 -4
  52. package/src/migration.ts +1 -1
  53. package/src/storage-hooks.ts +48 -0
@@ -1,12 +1,14 @@
1
1
  #include "HybridStorage.hpp"
2
2
  #include <stdexcept>
3
3
 
4
+ #ifndef NITRO_STORAGE_DISABLE_PLATFORM_ADAPTER
4
5
  #if __APPLE__
5
6
  #include "../../ios/IOSStorageAdapterCpp.hpp"
6
7
  #elif __ANDROID__
7
8
  #include "../../android/src/main/cpp/AndroidStorageAdapterCpp.hpp"
8
9
  #include <fbjni/fbjni.h>
9
10
  #endif
11
+ #endif
10
12
 
11
13
  namespace margelo::nitro::NitroStorage {
12
14
 
@@ -16,12 +18,14 @@ constexpr auto kBatchMissingSentinel = "__nitro_storage_batch_missing__::v1";
16
18
 
17
19
  HybridStorage::HybridStorage()
18
20
  : HybridObject(TAG), HybridStorageSpec() {
21
+ #ifndef NITRO_STORAGE_DISABLE_PLATFORM_ADAPTER
19
22
  #if __APPLE__
20
23
  nativeAdapter_ = std::make_shared<::NitroStorage::IOSStorageAdapterCpp>();
21
24
  #elif __ANDROID__
22
25
  auto context = ::NitroStorage::AndroidStorageAdapterJava::getContext();
23
26
  nativeAdapter_ = std::make_shared<::NitroStorage::AndroidStorageAdapterCpp>(context);
24
27
  #endif
28
+ #endif
25
29
  }
26
30
 
27
31
  HybridStorage::HybridStorage(std::shared_ptr<::NitroStorage::NativeStorageAdapter> adapter)
@@ -143,6 +147,65 @@ void HybridStorage::remove(const std::string& key, double scope) {
143
147
  notifyListeners(static_cast<int>(s), key, std::nullopt);
144
148
  }
145
149
 
150
+ bool HybridStorage::has(const std::string& key, double scope) {
151
+ Scope s = toScope(scope);
152
+
153
+ switch (s) {
154
+ case Scope::Memory: {
155
+ std::lock_guard<std::mutex> lock(memoryMutex_);
156
+ return memoryStore_.find(key) != memoryStore_.end();
157
+ }
158
+ case Scope::Disk:
159
+ ensureAdapter();
160
+ return nativeAdapter_->hasDisk(key);
161
+ case Scope::Secure:
162
+ ensureAdapter();
163
+ return nativeAdapter_->hasSecure(key);
164
+ }
165
+ return false;
166
+ }
167
+
168
+ std::vector<std::string> HybridStorage::getAllKeys(double scope) {
169
+ Scope s = toScope(scope);
170
+
171
+ switch (s) {
172
+ case Scope::Memory: {
173
+ std::lock_guard<std::mutex> lock(memoryMutex_);
174
+ std::vector<std::string> keys;
175
+ keys.reserve(memoryStore_.size());
176
+ for (const auto& pair : memoryStore_) {
177
+ keys.push_back(pair.first);
178
+ }
179
+ return keys;
180
+ }
181
+ case Scope::Disk:
182
+ ensureAdapter();
183
+ return nativeAdapter_->getAllKeysDisk();
184
+ case Scope::Secure:
185
+ ensureAdapter();
186
+ return nativeAdapter_->getAllKeysSecure();
187
+ }
188
+ return {};
189
+ }
190
+
191
+ double HybridStorage::size(double scope) {
192
+ Scope s = toScope(scope);
193
+
194
+ switch (s) {
195
+ case Scope::Memory: {
196
+ std::lock_guard<std::mutex> lock(memoryMutex_);
197
+ return static_cast<double>(memoryStore_.size());
198
+ }
199
+ case Scope::Disk:
200
+ ensureAdapter();
201
+ return static_cast<double>(nativeAdapter_->sizeDisk());
202
+ case Scope::Secure:
203
+ ensureAdapter();
204
+ return static_cast<double>(nativeAdapter_->sizeSecure());
205
+ }
206
+ return 0.0;
207
+ }
208
+
146
209
  std::function<void()> HybridStorage::addOnChange(
147
210
  double scope,
148
211
  const std::function<void(const std::string&, const std::optional<std::string>&)>& callback
@@ -239,12 +302,13 @@ void HybridStorage::setBatch(const std::vector<std::string>& keys, const std::ve
239
302
  break;
240
303
  }
241
304
 
305
+ const auto scopeValue = static_cast<int>(s);
306
+ const auto listeners = copyListenersForScope(scopeValue);
242
307
  for (size_t i = 0; i < keys.size(); ++i) {
243
- notifyListeners(static_cast<int>(s), keys[i], values[i]);
308
+ notifyListeners(listeners, keys[i], values[i]);
244
309
  }
245
310
  }
246
311
 
247
-
248
312
  std::vector<std::string> HybridStorage::getBatch(const std::vector<std::string>& keys, double scope) {
249
313
  std::vector<std::string> results;
250
314
  results.reserve(keys.size());
@@ -276,11 +340,7 @@ std::vector<std::string> HybridStorage::getBatch(const std::vector<std::string>&
276
340
  }
277
341
 
278
342
  for (const auto& value : values) {
279
- if (value.has_value()) {
280
- results.push_back(*value);
281
- } else {
282
- results.push_back(kBatchMissingSentinel);
283
- }
343
+ results.push_back(value.has_value() ? *value : std::string(kBatchMissingSentinel));
284
344
  }
285
345
  return results;
286
346
  }
@@ -296,11 +356,7 @@ std::vector<std::string> HybridStorage::getBatch(const std::vector<std::string>&
296
356
  }
297
357
 
298
358
  for (const auto& value : values) {
299
- if (value.has_value()) {
300
- results.push_back(*value);
301
- } else {
302
- results.push_back(kBatchMissingSentinel);
303
- }
359
+ results.push_back(value.has_value() ? *value : std::string(kBatchMissingSentinel));
304
360
  }
305
361
  return results;
306
362
  }
@@ -309,7 +365,6 @@ std::vector<std::string> HybridStorage::getBatch(const std::vector<std::string>&
309
365
  return results;
310
366
  }
311
367
 
312
-
313
368
  void HybridStorage::removeBatch(const std::vector<std::string>& keys, double scope) {
314
369
  Scope s = toScope(scope);
315
370
 
@@ -343,16 +398,100 @@ void HybridStorage::removeBatch(const std::vector<std::string>& keys, double sco
343
398
  break;
344
399
  }
345
400
 
401
+ const auto scopeValue = static_cast<int>(s);
402
+ const auto listeners = copyListenersForScope(scopeValue);
346
403
  for (const auto& key : keys) {
347
- notifyListeners(static_cast<int>(s), key, std::nullopt);
404
+ notifyListeners(listeners, key, std::nullopt);
348
405
  }
349
406
  }
350
407
 
351
- void HybridStorage::notifyListeners(
352
- int scope,
353
- const std::string& key,
354
- const std::optional<std::string>& value
355
- ) {
408
+ void HybridStorage::removeByPrefix(const std::string& prefix, double scope) {
409
+ if (prefix.empty()) {
410
+ return;
411
+ }
412
+
413
+ const auto keys = getAllKeys(scope);
414
+ std::vector<std::string> prefixedKeys;
415
+ prefixedKeys.reserve(keys.size());
416
+ for (const auto& key : keys) {
417
+ if (key.rfind(prefix, 0) == 0) {
418
+ prefixedKeys.push_back(key);
419
+ }
420
+ }
421
+
422
+ if (prefixedKeys.empty()) {
423
+ return;
424
+ }
425
+
426
+ removeBatch(prefixedKeys, scope);
427
+ }
428
+
429
+ // --- Configuration ---
430
+
431
+ void HybridStorage::setSecureAccessControl(double level) {
432
+ ensureAdapter();
433
+ nativeAdapter_->setSecureAccessControl(static_cast<int>(level));
434
+ }
435
+
436
+ void HybridStorage::setSecureWritesAsync(bool enabled) {
437
+ ensureAdapter();
438
+ nativeAdapter_->setSecureWritesAsync(enabled);
439
+ }
440
+
441
+ void HybridStorage::setKeychainAccessGroup(const std::string& group) {
442
+ ensureAdapter();
443
+ nativeAdapter_->setKeychainAccessGroup(group);
444
+ }
445
+
446
+ // --- Biometric ---
447
+
448
+ void HybridStorage::setSecureBiometric(const std::string& key, const std::string& value) {
449
+ ensureAdapter();
450
+ try {
451
+ nativeAdapter_->setSecureBiometric(key, value);
452
+ notifyListeners(static_cast<int>(Scope::Secure), key, value);
453
+ } catch (const std::exception& e) {
454
+ throw std::runtime_error(std::string("NitroStorage: Biometric set failed: ") + e.what());
455
+ }
456
+ }
457
+
458
+ std::optional<std::string> HybridStorage::getSecureBiometric(const std::string& key) {
459
+ ensureAdapter();
460
+ try {
461
+ return nativeAdapter_->getSecureBiometric(key);
462
+ } catch (const std::exception& e) {
463
+ throw std::runtime_error(std::string("NitroStorage: Biometric get failed: ") + e.what());
464
+ }
465
+ }
466
+
467
+ void HybridStorage::deleteSecureBiometric(const std::string& key) {
468
+ ensureAdapter();
469
+ try {
470
+ nativeAdapter_->deleteSecureBiometric(key);
471
+ notifyListeners(static_cast<int>(Scope::Secure), key, std::nullopt);
472
+ } catch (const std::exception& e) {
473
+ throw std::runtime_error(std::string("NitroStorage: Biometric delete failed: ") + e.what());
474
+ }
475
+ }
476
+
477
+ bool HybridStorage::hasSecureBiometric(const std::string& key) {
478
+ ensureAdapter();
479
+ return nativeAdapter_->hasSecureBiometric(key);
480
+ }
481
+
482
+ void HybridStorage::clearSecureBiometric() {
483
+ ensureAdapter();
484
+ try {
485
+ nativeAdapter_->clearSecureBiometric();
486
+ notifyListeners(static_cast<int>(Scope::Secure), "", std::nullopt);
487
+ } catch (const std::exception& e) {
488
+ throw std::runtime_error(std::string("NitroStorage: Biometric clear failed: ") + e.what());
489
+ }
490
+ }
491
+
492
+ // --- Internal ---
493
+
494
+ std::vector<HybridStorage::Listener> HybridStorage::copyListenersForScope(int scope) {
356
495
  std::vector<Listener> listenersCopy;
357
496
  {
358
497
  std::lock_guard<std::mutex> lock(listenersMutex_);
@@ -362,8 +501,15 @@ void HybridStorage::notifyListeners(
362
501
  listenersCopy = it->second;
363
502
  }
364
503
  }
365
-
366
- for (const auto& listener : listenersCopy) {
504
+ return listenersCopy;
505
+ }
506
+
507
+ void HybridStorage::notifyListeners(
508
+ const std::vector<Listener>& listeners,
509
+ const std::string& key,
510
+ const std::optional<std::string>& value
511
+ ) {
512
+ for (const auto& listener : listeners) {
367
513
  try {
368
514
  listener.callback(key, value);
369
515
  } catch (...) {
@@ -372,6 +518,15 @@ void HybridStorage::notifyListeners(
372
518
  }
373
519
  }
374
520
 
521
+ void HybridStorage::notifyListeners(
522
+ int scope,
523
+ const std::string& key,
524
+ const std::optional<std::string>& value
525
+ ) {
526
+ const auto listeners = copyListenersForScope(scope);
527
+ notifyListeners(listeners, key, value);
528
+ }
529
+
375
530
  void HybridStorage::ensureAdapter() const {
376
531
  if (!nativeAdapter_) {
377
532
  throw std::runtime_error("NitroStorage: Native adapter not initialized");
@@ -3,6 +3,7 @@
3
3
  #include "HybridStorageSpec.hpp"
4
4
  #include "../core/NativeStorageAdapter.hpp"
5
5
  #include <unordered_map>
6
+ #include <map>
6
7
  #include <mutex>
7
8
  #include <functional>
8
9
  #include <memory>
@@ -10,6 +11,14 @@
10
11
 
11
12
  namespace margelo::nitro::NitroStorage {
12
13
 
14
+ #ifdef NITRO_STORAGE_USE_ORDERED_MAP_FOR_TESTS
15
+ template <typename Key, typename Value>
16
+ using HybridStorageMap = std::map<Key, Value>;
17
+ #else
18
+ template <typename Key, typename Value>
19
+ using HybridStorageMap = std::unordered_map<Key, Value>;
20
+ #endif
21
+
13
22
  class HybridStorage : public HybridStorageSpec {
14
23
  public:
15
24
  HybridStorage();
@@ -20,13 +29,25 @@ public:
20
29
  std::optional<std::string> get(const std::string& key, double scope) override;
21
30
  void remove(const std::string& key, double scope) override;
22
31
  void clear(double scope) override;
32
+ bool has(const std::string& key, double scope) override;
33
+ std::vector<std::string> getAllKeys(double scope) override;
34
+ double size(double scope) override;
23
35
  void setBatch(const std::vector<std::string>& keys, const std::vector<std::string>& values, double scope) override;
24
36
  std::vector<std::string> getBatch(const std::vector<std::string>& keys, double scope) override;
25
37
  void removeBatch(const std::vector<std::string>& keys, double scope) override;
38
+ void removeByPrefix(const std::string& prefix, double scope) override;
26
39
  std::function<void()> addOnChange(
27
40
  double scope,
28
41
  const std::function<void(const std::string&, const std::optional<std::string>&)>& callback
29
42
  ) override;
43
+ void setSecureAccessControl(double level) override;
44
+ void setSecureWritesAsync(bool enabled) override;
45
+ void setKeychainAccessGroup(const std::string& group) override;
46
+ void setSecureBiometric(const std::string& key, const std::string& value) override;
47
+ std::optional<std::string> getSecureBiometric(const std::string& key) override;
48
+ void deleteSecureBiometric(const std::string& key) override;
49
+ bool hasSecureBiometric(const std::string& key) override;
50
+ void clearSecureBiometric() override;
30
51
 
31
52
  private:
32
53
  enum class Scope {
@@ -40,15 +61,21 @@ private:
40
61
  std::function<void(const std::string&, const std::optional<std::string>&)> callback;
41
62
  };
42
63
 
43
- std::unordered_map<std::string, std::string> memoryStore_;
64
+ HybridStorageMap<std::string, std::string> memoryStore_;
44
65
  std::mutex memoryMutex_;
45
66
 
46
67
  std::shared_ptr<::NitroStorage::NativeStorageAdapter> nativeAdapter_;
47
68
 
48
- std::unordered_map<int, std::vector<Listener>> listeners_;
69
+ HybridStorageMap<int, std::vector<Listener>> listeners_;
49
70
  std::mutex listenersMutex_;
50
71
  size_t nextListenerId_ = 0;
51
72
 
73
+ std::vector<Listener> copyListenersForScope(int scope);
74
+ void notifyListeners(
75
+ const std::vector<Listener>& listeners,
76
+ const std::string& key,
77
+ const std::optional<std::string>& value
78
+ );
52
79
  void notifyListeners(int scope, const std::string& key, const std::optional<std::string>& value);
53
80
  void ensureAdapter() const;
54
81
  Scope toScope(double scopeValue);
@@ -13,6 +13,9 @@ public:
13
13
  virtual void setDisk(const std::string& key, const std::string& value) = 0;
14
14
  virtual std::optional<std::string> getDisk(const std::string& key) = 0;
15
15
  virtual void deleteDisk(const std::string& key) = 0;
16
+ virtual bool hasDisk(const std::string& key) = 0;
17
+ virtual std::vector<std::string> getAllKeysDisk() = 0;
18
+ virtual size_t sizeDisk() = 0;
16
19
  virtual void setDiskBatch(const std::vector<std::string>& keys, const std::vector<std::string>& values) = 0;
17
20
  virtual std::vector<std::optional<std::string>> getDiskBatch(const std::vector<std::string>& keys) = 0;
18
21
  virtual void deleteDiskBatch(const std::vector<std::string>& keys) = 0;
@@ -20,12 +23,25 @@ public:
20
23
  virtual void setSecure(const std::string& key, const std::string& value) = 0;
21
24
  virtual std::optional<std::string> getSecure(const std::string& key) = 0;
22
25
  virtual void deleteSecure(const std::string& key) = 0;
26
+ virtual bool hasSecure(const std::string& key) = 0;
27
+ virtual std::vector<std::string> getAllKeysSecure() = 0;
28
+ virtual size_t sizeSecure() = 0;
23
29
  virtual void setSecureBatch(const std::vector<std::string>& keys, const std::vector<std::string>& values) = 0;
24
30
  virtual std::vector<std::optional<std::string>> getSecureBatch(const std::vector<std::string>& keys) = 0;
25
31
  virtual void deleteSecureBatch(const std::vector<std::string>& keys) = 0;
26
32
 
27
33
  virtual void clearDisk() = 0;
28
34
  virtual void clearSecure() = 0;
35
+
36
+ virtual void setSecureAccessControl(int level) = 0;
37
+ virtual void setSecureWritesAsync(bool enabled) = 0;
38
+ virtual void setKeychainAccessGroup(const std::string& group) = 0;
39
+
40
+ virtual void setSecureBiometric(const std::string& key, const std::string& value) = 0;
41
+ virtual std::optional<std::string> getSecureBiometric(const std::string& key) = 0;
42
+ virtual void deleteSecureBiometric(const std::string& key) = 0;
43
+ virtual bool hasSecureBiometric(const std::string& key) = 0;
44
+ virtual void clearSecureBiometric() = 0;
29
45
  };
30
46
 
31
47
  } // namespace NitroStorage
@@ -12,6 +12,9 @@ public:
12
12
  void setDisk(const std::string& key, const std::string& value) override;
13
13
  std::optional<std::string> getDisk(const std::string& key) override;
14
14
  void deleteDisk(const std::string& key) override;
15
+ bool hasDisk(const std::string& key) override;
16
+ std::vector<std::string> getAllKeysDisk() override;
17
+ size_t sizeDisk() override;
15
18
  void setDiskBatch(const std::vector<std::string>& keys, const std::vector<std::string>& values) override;
16
19
  std::vector<std::optional<std::string>> getDiskBatch(const std::vector<std::string>& keys) override;
17
20
  void deleteDiskBatch(const std::vector<std::string>& keys) override;
@@ -19,12 +22,29 @@ public:
19
22
  void setSecure(const std::string& key, const std::string& value) override;
20
23
  std::optional<std::string> getSecure(const std::string& key) override;
21
24
  void deleteSecure(const std::string& key) override;
25
+ bool hasSecure(const std::string& key) override;
26
+ std::vector<std::string> getAllKeysSecure() override;
27
+ size_t sizeSecure() override;
22
28
  void setSecureBatch(const std::vector<std::string>& keys, const std::vector<std::string>& values) override;
23
29
  std::vector<std::optional<std::string>> getSecureBatch(const std::vector<std::string>& keys) override;
24
30
  void deleteSecureBatch(const std::vector<std::string>& keys) override;
25
31
 
26
32
  void clearDisk() override;
27
33
  void clearSecure() override;
34
+
35
+ void setSecureAccessControl(int level) override;
36
+ void setSecureWritesAsync(bool enabled) override;
37
+ void setKeychainAccessGroup(const std::string& group) override;
38
+
39
+ void setSecureBiometric(const std::string& key, const std::string& value) override;
40
+ std::optional<std::string> getSecureBiometric(const std::string& key) override;
41
+ void deleteSecureBiometric(const std::string& key) override;
42
+ bool hasSecureBiometric(const std::string& key) override;
43
+ void clearSecureBiometric() override;
44
+
45
+ private:
46
+ int accessControlLevel_ = 0;
47
+ std::string keychainAccessGroup_;
28
48
  };
29
49
 
30
50
  } // namespace NitroStorage