react-native-nitro-storage 0.1.0 → 0.1.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 CHANGED
@@ -139,17 +139,25 @@ const value = counterAtom.get(); // 42, instantly
139
139
 
140
140
  _Replaces: Zustand, Jotai, Redux_
141
141
 
142
- Fast, in-memory state. Perfect for global app state that doesn't need persistence.
142
+ Fast, in-memory state. **Now Pure JS** - can store complex objects, functions, and React nodes!
143
143
 
144
144
  ```typescript
145
- const userAtom = createStorageItem<User | null>({
146
- key: "current-user",
145
+ // Store a function
146
+ const callbackAtom = createStorageItem({
147
+ key: "on-click",
147
148
  scope: StorageScope.Memory,
148
- defaultValue: null,
149
+ defaultValue: () => console.log("Clicked!"),
150
+ });
151
+
152
+ // Store a React Component
153
+ const modalAtom = createStorageItem({
154
+ key: "active-modal",
155
+ scope: StorageScope.Memory,
156
+ defaultValue: <View />,
149
157
  });
150
158
  ```
151
159
 
152
- **Performance:** < 0.001ms per operation
160
+ **Performance:** < 0.001ms per operation (Zero JSI overhead)
153
161
 
154
162
  ### **Disk Storage**
155
163
 
@@ -299,6 +307,53 @@ const unsubscribe = counterAtom.subscribe(() => {
299
307
  unsubscribe();
300
308
  ```
301
309
 
310
+ ### Functional Updates
311
+
312
+ Update state based on the previous value, just like `useState`.
313
+
314
+ ```typescript
315
+ // Increment counter
316
+ counterAtom.set((prev) => prev + 1);
317
+ ```
318
+
319
+ ### Optimized Writes
320
+
321
+ Use `useSetStorage` to set values without subscribing to updates (avoids re-renders).
322
+
323
+ ```typescript
324
+ import { useSetStorage } from "react-native-nitro-storage";
325
+
326
+ function IncrementButton() {
327
+ const setCount = useSetStorage(counterAtom);
328
+ return <Button onPress={() => setCount((c) => c + 1)} title="+" />;
329
+ }
330
+ ```
331
+
332
+ ### Clearing Data
333
+
334
+ Clear all data in `Memory` scope (Native scopes coming soon).
335
+
336
+ ```typescript
337
+ import { storage } from "react-native-nitro-storage";
338
+
339
+ // Clear all memory state (e.g. on logout)
340
+ storage.clearAll();
341
+
342
+ // Or specific scope
343
+ storage.clear(StorageScope.Memory);
344
+ ```
345
+
346
+ ### Migration from MMKV
347
+
348
+ Easily migrate data from `react-native-mmkv` to Nitro Storage.
349
+
350
+ ```typescript
351
+ import { migrateFromMMKV } from "react-native-nitro-storage/src/migration";
352
+
353
+ // Migrate 'user-settings' and delete from MMKV
354
+ migrateFromMMKV(mmkvInstance, settingsAtom, true);
355
+ ```
356
+
302
357
  ---
303
358
 
304
359
  ## 📊 Performance Benchmarks
@@ -344,7 +399,7 @@ Creates a storage atom.
344
399
  **Methods:**
345
400
 
346
401
  - `get(): T` - Get current value (synchronous)
347
- - `set(value: T): void` - Set new value (synchronous)
402
+ - `set(value: T | ((prev: T) => T)): void` - Set new value (synchronous)
348
403
  - `delete(): void` - Remove value (synchronous)
349
404
  - `subscribe(callback: () => void): () => void` - Subscribe to changes
350
405
 
@@ -352,7 +407,18 @@ Creates a storage atom.
352
407
 
353
408
  React hook using `useSyncExternalStore` for automatic re-renders.
354
409
 
355
- **Returns:** `[value: T, setValue: (value: T) => void]`
410
+ **Returns:** `[value: T, setValue: (value: T | ((prev: T) => T)) => void]`
411
+
412
+ ### `useSetStorage<T>(item: StorageItem<T>)`
413
+
414
+ Returns the setter function only. Does not subscribe to updates.
415
+
416
+ **Returns:** `(value: T | ((prev: T) => T)) => void`
417
+
418
+ ### `storage` Object
419
+
420
+ - `clearAll()`: Clears all `Memory` storage.
421
+ - `clear(scope: StorageScope.Memory)`: Clears specific scope.
356
422
 
357
423
  ---
358
424
 
@@ -1,33 +1,39 @@
1
- cmake_minimum_required(VERSION 3.22.1)
1
+ cmake_minimum_required(VERSION 3.18.0)
2
+
2
3
  project(NitroStorage)
3
4
 
5
+ set(CMAKE_VERBOSE_MAKEFILE ON)
4
6
  set(CMAKE_CXX_STANDARD 20)
5
- set(CMAKE_CXX_STANDARD_REQUIRED ON)
6
- set(CMAKE_C_STANDARD 11)
7
- set(CMAKE_C_STANDARD_REQUIRED ON)
8
-
9
- # Define the path to our C++ sources
10
- set(CPP_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../cpp")
11
7
 
12
- # Collect source files
13
- file(GLOB CORE_SOURCES "${CPP_ROOT}/core/*.cpp")
14
- file(GLOB BINDING_SOURCES "${CPP_ROOT}/bindings/*.cpp")
8
+ # 1. Define source files (Manual implementation)
9
+ file(GLOB SOURCES
10
+ "../cpp/bindings/*.cpp"
11
+ "../cpp/core/*.cpp"
12
+ "./src/main/cpp/*.cpp"
13
+ )
15
14
 
16
- # Create the shared library with our sources
17
- add_library(${PROJECT_NAME} SHARED
18
- ${CORE_SOURCES}
19
- ${BINDING_SOURCES}
20
- # JNI adapter
21
- src/main/cpp/cpp-adapter.cpp
22
- src/main/cpp/AndroidStorageAdapterCpp.cpp
15
+ # 2. Create the library target
16
+ add_library(
17
+ NitroStorage
18
+ SHARED
19
+ ${SOURCES}
23
20
  )
24
21
 
25
- # Include directories
26
- target_include_directories(${PROJECT_NAME} PRIVATE
27
- "${CPP_ROOT}/core"
28
- "${CPP_ROOT}/bindings"
29
- "src/main/cpp"
22
+ # 3. Include directories for manual sources
23
+ target_include_directories(
24
+ NitroStorage
25
+ PRIVATE
26
+ "../cpp/core"
27
+ "../cpp/bindings"
28
+ "./src/main/cpp"
30
29
  )
31
30
 
32
- # Include Nitro autolinking (adds nitrogen sources, definitions, and links)
33
- include(${CMAKE_CURRENT_SOURCE_DIR}/../nitrogen/generated/android/NitroStorage+autolinking.cmake)
31
+ # 4. Include Nitrogen Autolinking (adds generated sources, finding packages, linking libs)
32
+ include("../nitrogen/generated/android/NitroStorage+autolinking.cmake")
33
+
34
+ # 5. Link standard Android libraries
35
+ target_link_libraries(
36
+ NitroStorage
37
+ android
38
+ log
39
+ )
@@ -1,6 +1,7 @@
1
1
  #include <jni.h>
2
- #include "NitroStorageOnLoad.hpp"
2
+ #include <fbjni/fbjni.h>
3
+ #include "../../../nitrogen/generated/android/NitroStorageOnLoad.hpp"
3
4
 
4
- JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
5
+ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void*) {
5
6
  return margelo::nitro::NitroStorage::initialize(vm);
6
7
  }
@@ -24,14 +24,7 @@ HybridStorage::HybridStorage(std::shared_ptr<::NitroStorage::NativeStorageAdapte
24
24
  : HybridObject(TAG), HybridStorageSpec(), nativeAdapter_(std::move(adapter)) {}
25
25
 
26
26
  HybridStorage::Scope HybridStorage::toScope(double scopeValue) {
27
- int intScope = static_cast<int>(scopeValue);
28
- if (intScope < 0 || intScope > 2) {
29
- throw std::invalid_argument(
30
- "Invalid storage scope: " + std::to_string(intScope) +
31
- ". Must be 0 (Memory), 1 (Disk), or 2 (Secure)"
32
- );
33
- }
34
- return static_cast<Scope>(intScope);
27
+ return static_cast<Scope>(static_cast<int>(scopeValue));
35
28
  }
36
29
 
37
30
  void HybridStorage::set(const std::string& key, const std::string& value, double scope) {
@@ -100,8 +93,8 @@ std::function<void()> HybridStorage::addOnChange(
100
93
  const std::function<void(const std::string&, const std::optional<std::string>&)>& callback
101
94
  ) {
102
95
  int intScope = static_cast<int>(scope);
103
-
104
96
  size_t listenerId;
97
+
105
98
  {
106
99
  std::lock_guard<std::mutex> lock(listenersMutex_);
107
100
  listenerId = nextListenerId_++;
@@ -111,14 +104,12 @@ std::function<void()> HybridStorage::addOnChange(
111
104
  return [this, intScope, listenerId]() {
112
105
  std::lock_guard<std::mutex> lock(listenersMutex_);
113
106
  auto& scopeListeners = listeners_[intScope];
114
- scopeListeners.erase(
115
- std::remove_if(
116
- scopeListeners.begin(),
117
- scopeListeners.end(),
118
- [listenerId](const Listener& l) { return l.id == listenerId; }
119
- ),
120
- scopeListeners.end()
121
- );
107
+ for (auto it = scopeListeners.begin(); it != scopeListeners.end(); ++it) {
108
+ if (it->id == listenerId) {
109
+ scopeListeners.erase(it);
110
+ break;
111
+ }
112
+ }
122
113
  };
123
114
  }
124
115
 
@@ -132,6 +123,7 @@ void HybridStorage::notifyListeners(
132
123
  std::lock_guard<std::mutex> lock(listenersMutex_);
133
124
  auto it = listeners_.find(scope);
134
125
  if (it != listeners_.end()) {
126
+ listenersCopy.reserve(it->second.size());
135
127
  listenersCopy = it->second;
136
128
  }
137
129
  }
@@ -4,124 +4,75 @@
4
4
 
5
5
  namespace NitroStorage {
6
6
 
7
- IOSStorageAdapterCpp::IOSStorageAdapterCpp() {}
7
+ static NSString* const kKeychainService = @"com.nitrostorage.keychain";
8
8
 
9
+ IOSStorageAdapterCpp::IOSStorageAdapterCpp() {}
9
10
  IOSStorageAdapterCpp::~IOSStorageAdapterCpp() {}
10
11
 
11
12
  void IOSStorageAdapterCpp::setDisk(const std::string& key, const std::string& value) {
12
- NSString* nsKey = [NSString stringWithUTF8String:key.c_str()];
13
- NSString* nsValue = [NSString stringWithUTF8String:value.c_str()];
14
- [[NSUserDefaults standardUserDefaults] setObject:nsValue forKey:nsKey];
13
+ [[NSUserDefaults standardUserDefaults] setObject:[NSString stringWithUTF8String:value.c_str()]
14
+ forKey:[NSString stringWithUTF8String:key.c_str()]];
15
15
  }
16
16
 
17
17
  std::optional<std::string> IOSStorageAdapterCpp::getDisk(const std::string& key) {
18
- NSString* nsKey = [NSString stringWithUTF8String:key.c_str()];
19
- NSString* result = [[NSUserDefaults standardUserDefaults] stringForKey:nsKey];
20
-
21
- if (result) {
22
- const char* utf8String = [result UTF8String];
23
- if (utf8String) {
24
- std::string value;
25
- value.reserve([result lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
26
- value.assign(utf8String);
27
- return value;
28
- }
29
- }
30
- return std::nullopt;
18
+ NSString* result = [[NSUserDefaults standardUserDefaults] stringForKey:[NSString stringWithUTF8String:key.c_str()]];
19
+ if (!result) return std::nullopt;
20
+ return std::string([result UTF8String]);
31
21
  }
32
22
 
33
23
  void IOSStorageAdapterCpp::deleteDisk(const std::string& key) {
34
- NSString* nsKey = [NSString stringWithUTF8String:key.c_str()];
35
- [[NSUserDefaults standardUserDefaults] removeObjectForKey:nsKey];
24
+ [[NSUserDefaults standardUserDefaults] removeObjectForKey:[NSString stringWithUTF8String:key.c_str()]];
36
25
  }
37
26
 
38
27
  void IOSStorageAdapterCpp::setSecure(const std::string& key, const std::string& value) {
39
28
  NSString* nsKey = [NSString stringWithUTF8String:key.c_str()];
40
- NSString* nsValue = [NSString stringWithUTF8String:value.c_str()];
41
- NSData* data = [nsValue dataUsingEncoding:NSUTF8StringEncoding];
42
-
43
- NSString* service = @"com.nitrostorage.keychain";
44
-
29
+ NSData* data = [[NSString stringWithUTF8String:value.c_str()] dataUsingEncoding:NSUTF8StringEncoding];
30
+
45
31
  NSDictionary* query = @{
46
32
  (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
47
- (__bridge id)kSecAttrService: service,
33
+ (__bridge id)kSecAttrService: kKeychainService,
48
34
  (__bridge id)kSecAttrAccount: nsKey
49
35
  };
50
-
36
+
51
37
  NSDictionary* updateAttributes = @{
52
38
  (__bridge id)kSecValueData: data
53
39
  };
40
+
41
+ OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)updateAttributes);
54
42
 
55
- // Try to update first (atomic operation)
56
- OSStatus updateStatus = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)updateAttributes);
57
-
58
- if (updateStatus == errSecItemNotFound) {
59
- // Item doesn't exist, add it
60
- NSDictionary* addQuery = @{
61
- (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
62
- (__bridge id)kSecAttrService: service,
63
- (__bridge id)kSecAttrAccount: nsKey,
64
- (__bridge id)kSecValueData: data,
65
- (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenUnlocked
66
- };
67
-
68
- OSStatus addStatus = SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL);
69
- if (addStatus != errSecSuccess) {
70
- NSLog(@"NitroStorage: Failed to add to Keychain for key '%@'. Error: %d", nsKey, (int)addStatus);
71
- }
72
- } else if (updateStatus != errSecSuccess) {
73
- NSLog(@"NitroStorage: Failed to update Keychain item '%@'. Error: %d", nsKey, (int)updateStatus);
43
+ if (status == errSecItemNotFound) {
44
+ NSMutableDictionary* addQuery = [query mutableCopy];
45
+ addQuery[(__bridge id)kSecValueData] = data;
46
+ addQuery[(__bridge id)kSecAttrAccessible] = (__bridge id)kSecAttrAccessibleWhenUnlocked;
47
+ SecItemAdd((__bridge CFDictionaryRef)addQuery, NULL);
74
48
  }
75
49
  }
76
50
 
77
51
  std::optional<std::string> IOSStorageAdapterCpp::getSecure(const std::string& key) {
78
- NSString* nsKey = [NSString stringWithUTF8String:key.c_str()];
79
- NSString* service = @"com.nitrostorage.keychain";
80
-
81
52
  NSDictionary* query = @{
82
53
  (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
83
- (__bridge id)kSecAttrService: service,
84
- (__bridge id)kSecAttrAccount: nsKey,
54
+ (__bridge id)kSecAttrService: kKeychainService,
55
+ (__bridge id)kSecAttrAccount: [NSString stringWithUTF8String:key.c_str()],
85
56
  (__bridge id)kSecReturnData: @YES,
86
57
  (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitOne
87
58
  };
88
-
59
+
89
60
  CFTypeRef result = NULL;
90
- OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
91
-
92
- if (status == errSecSuccess && result) {
61
+ if (SecItemCopyMatching((__bridge CFDictionaryRef)query, &result) == errSecSuccess && result) {
93
62
  NSData* data = (__bridge_transfer NSData*)result;
94
- NSString* nsValue = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
95
- if (nsValue) {
96
- const char* utf8String = [nsValue UTF8String];
97
- if (utf8String) {
98
- std::string value;
99
- value.reserve([nsValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
100
- value.assign(utf8String);
101
- return value;
102
- }
103
- }
104
- } else if (status != errSecItemNotFound) {
105
- NSLog(@"NitroStorage: Failed to read from Keychain for key '%@'. Error: %d", nsKey, (int)status);
63
+ NSString* str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
64
+ if (str) return std::string([str UTF8String]);
106
65
  }
107
-
108
66
  return std::nullopt;
109
67
  }
110
68
 
111
69
  void IOSStorageAdapterCpp::deleteSecure(const std::string& key) {
112
- NSString* nsKey = [NSString stringWithUTF8String:key.c_str()];
113
- NSString* service = @"com.nitrostorage.keychain";
114
-
115
70
  NSDictionary* query = @{
116
71
  (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
117
- (__bridge id)kSecAttrService: service,
118
- (__bridge id)kSecAttrAccount: nsKey
72
+ (__bridge id)kSecAttrService: kKeychainService,
73
+ (__bridge id)kSecAttrAccount: [NSString stringWithUTF8String:key.c_str()]
119
74
  };
120
-
121
- OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
122
- if (status != errSecSuccess && status != errSecItemNotFound) {
123
- NSLog(@"NitroStorage: Failed to delete from Keychain for key '%@'. Error: %d", nsKey, (int)status);
124
- }
75
+ SecItemDelete((__bridge CFDictionaryRef)query);
125
76
  }
126
77
 
127
78
  } // namespace NitroStorage
@@ -10,6 +10,8 @@ Object.defineProperty(exports, "StorageScope", {
10
10
  }
11
11
  });
12
12
  exports.createStorageItem = createStorageItem;
13
+ exports.storage = void 0;
14
+ exports.useSetStorage = useSetStorage;
13
15
  exports.useStorage = useStorage;
14
16
  var _react = require("react");
15
17
  var _reactNativeNitroModules = require("react-native-nitro-modules");
@@ -21,6 +23,19 @@ function getStorageModule() {
21
23
  }
22
24
  return _storageModule;
23
25
  }
26
+ const memoryStore = new Map();
27
+ const memoryListeners = new Set();
28
+ function notifyMemoryListeners(key, value) {
29
+ memoryListeners.forEach(listener => listener(key, value));
30
+ }
31
+ const storage = exports.storage = {
32
+ clear: scope => {
33
+ memoryStore.clear();
34
+ },
35
+ clearAll: () => {
36
+ storage.clear(_StorageNitro.StorageScope.Memory);
37
+ }
38
+ };
24
39
  function defaultSerialize(value) {
25
40
  return JSON.stringify(value);
26
41
  }
@@ -30,21 +45,37 @@ function defaultDeserialize(value) {
30
45
  function createStorageItem(config) {
31
46
  const serialize = config.serialize ?? defaultSerialize;
32
47
  const deserialize = config.deserialize ?? defaultDeserialize;
48
+ const isMemory = config.scope === _StorageNitro.StorageScope.Memory;
33
49
  const listeners = new Set();
34
50
  let unsubscribe = null;
35
51
  const ensureSubscription = () => {
36
52
  if (!unsubscribe) {
37
- unsubscribe = getStorageModule().addOnChange(config.scope, key => {
38
- if (key === config.key) {
39
- listeners.forEach(listener => listener());
40
- }
41
- });
53
+ if (isMemory) {
54
+ const listener = key => {
55
+ if (key === config.key) {
56
+ listeners.forEach(l => l());
57
+ }
58
+ };
59
+ memoryListeners.add(listener);
60
+ unsubscribe = () => memoryListeners.delete(listener);
61
+ } else {
62
+ unsubscribe = getStorageModule().addOnChange(config.scope, key => {
63
+ if (key === config.key) {
64
+ listeners.forEach(listener => listener());
65
+ }
66
+ });
67
+ }
42
68
  }
43
69
  };
44
70
  let lastRaw;
45
71
  let lastValue;
46
72
  const get = () => {
47
- const raw = getStorageModule().get(config.key, config.scope);
73
+ let raw;
74
+ if (isMemory) {
75
+ raw = memoryStore.get(config.key);
76
+ } else {
77
+ raw = getStorageModule().get(config.key, config.scope);
78
+ }
48
79
  if (raw === lastRaw && lastValue !== undefined) {
49
80
  return lastValue;
50
81
  }
@@ -52,16 +83,32 @@ function createStorageItem(config) {
52
83
  if (raw === undefined) {
53
84
  lastValue = config.defaultValue;
54
85
  } else {
55
- lastValue = deserialize(raw);
86
+ if (isMemory) {
87
+ lastValue = raw;
88
+ } else {
89
+ lastValue = deserialize(raw);
90
+ }
56
91
  }
57
92
  return lastValue;
58
93
  };
59
- const set = value => {
60
- const serialized = serialize(value);
61
- getStorageModule().set(config.key, serialized, config.scope);
94
+ const set = valueOrFn => {
95
+ const currentValue = get();
96
+ const newValue = valueOrFn instanceof Function ? valueOrFn(currentValue) : valueOrFn;
97
+ if (isMemory) {
98
+ memoryStore.set(config.key, newValue);
99
+ notifyMemoryListeners(config.key, newValue);
100
+ } else {
101
+ const serialized = serialize(newValue);
102
+ getStorageModule().set(config.key, serialized, config.scope);
103
+ }
62
104
  };
63
105
  const deleteItem = () => {
64
- getStorageModule().remove(config.key, config.scope);
106
+ if (isMemory) {
107
+ memoryStore.delete(config.key);
108
+ notifyMemoryListeners(config.key, undefined);
109
+ } else {
110
+ getStorageModule().remove(config.key, config.scope);
111
+ }
65
112
  };
66
113
  const subscribe = callback => {
67
114
  ensureSubscription();
@@ -78,11 +125,16 @@ function createStorageItem(config) {
78
125
  get,
79
126
  set,
80
127
  delete: deleteItem,
81
- subscribe
128
+ subscribe,
129
+ scope: config.scope,
130
+ key: config.key
82
131
  };
83
132
  }
84
133
  function useStorage(item) {
85
134
  const value = (0, _react.useSyncExternalStore)(item.subscribe, item.get, item.get);
86
135
  return [value, item.set];
87
136
  }
137
+ function useSetStorage(item) {
138
+ return item.set;
139
+ }
88
140
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_react","require","_reactNativeNitroModules","_StorageNitro","_storageModule","getStorageModule","NitroModules","createHybridObject","defaultSerialize","value","JSON","stringify","defaultDeserialize","parse","createStorageItem","config","serialize","deserialize","listeners","Set","unsubscribe","ensureSubscription","addOnChange","scope","key","forEach","listener","lastRaw","lastValue","get","raw","undefined","defaultValue","set","serialized","deleteItem","remove","subscribe","callback","add","delete","size","useStorage","item","useSyncExternalStore"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_react","require","_reactNativeNitroModules","_StorageNitro","_storageModule","getStorageModule","NitroModules","createHybridObject","memoryStore","Map","memoryListeners","Set","notifyMemoryListeners","key","value","forEach","listener","storage","exports","clear","scope","clearAll","StorageScopeEnum","Memory","defaultSerialize","JSON","stringify","defaultDeserialize","parse","createStorageItem","config","serialize","deserialize","isMemory","listeners","unsubscribe","ensureSubscription","l","add","delete","addOnChange","lastRaw","lastValue","get","raw","undefined","defaultValue","set","valueOrFn","currentValue","newValue","Function","serialized","deleteItem","remove","subscribe","callback","size","useStorage","item","useSyncExternalStore","useSetStorage"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.migrateFromMMKV = migrateFromMMKV;
7
+ function migrateFromMMKV(mmkv, item, deleteFromMMKV = false) {
8
+ const key = item.key;
9
+ if (!mmkv.contains(key)) {
10
+ return false;
11
+ }
12
+ const value = mmkv.getString(key);
13
+ if (value !== undefined) {
14
+ try {
15
+ const parsed = JSON.parse(value);
16
+ item.set(parsed);
17
+ } catch {
18
+ item.set(value);
19
+ }
20
+ if (deleteFromMMKV) {
21
+ mmkv.delete(key);
22
+ }
23
+ return true;
24
+ }
25
+ const num = mmkv.getNumber(key);
26
+ if (num !== undefined) {
27
+ item.set(num);
28
+ if (deleteFromMMKV) mmkv.delete(key);
29
+ return true;
30
+ }
31
+ const bool = mmkv.getBoolean(key);
32
+ if (bool !== undefined) {
33
+ item.set(bool);
34
+ if (deleteFromMMKV) mmkv.delete(key);
35
+ return true;
36
+ }
37
+ return false;
38
+ }
39
+ //# sourceMappingURL=migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["migrateFromMMKV","mmkv","item","deleteFromMMKV","key","contains","value","getString","undefined","parsed","JSON","parse","set","delete","num","getNumber","bool","getBoolean"],"sourceRoot":"../../src","sources":["migration.ts"],"mappings":";;;;;;AAWO,SAASA,eAAeA,CAC7BC,IAAc,EACdC,IAAoB,EACpBC,cAAc,GAAG,KAAK,EACb;EACT,MAAMC,GAAG,GAAGF,IAAI,CAACE,GAAG;EACpB,IAAI,CAACH,IAAI,CAACI,QAAQ,CAACD,GAAG,CAAC,EAAE;IACvB,OAAO,KAAK;EACd;EAEA,MAAME,KAAK,GAAGL,IAAI,CAACM,SAAS,CAACH,GAAG,CAAC;EAEjC,IAAIE,KAAK,KAAKE,SAAS,EAAE;IACvB,IAAI;MACF,MAAMC,MAAM,GAAGC,IAAI,CAACC,KAAK,CAACL,KAAK,CAAC;MAChCJ,IAAI,CAACU,GAAG,CAACH,MAAM,CAAC;IAClB,CAAC,CAAC,MAAM;MACNP,IAAI,CAACU,GAAG,CAACN,KAAU,CAAC;IACtB;IAEA,IAAIH,cAAc,EAAE;MAClBF,IAAI,CAACY,MAAM,CAACT,GAAG,CAAC;IAClB;IACA,OAAO,IAAI;EACb;EAEA,MAAMU,GAAG,GAAGb,IAAI,CAACc,SAAS,CAACX,GAAG,CAAC;EAC/B,IAAIU,GAAG,KAAKN,SAAS,EAAE;IACrBN,IAAI,CAACU,GAAG,CAACE,GAAQ,CAAC;IAClB,IAAIX,cAAc,EAAEF,IAAI,CAACY,MAAM,CAACT,GAAG,CAAC;IACpC,OAAO,IAAI;EACb;EAEA,MAAMY,IAAI,GAAGf,IAAI,CAACgB,UAAU,CAACb,GAAG,CAAC;EACjC,IAAIY,IAAI,KAAKR,SAAS,EAAE;IACtBN,IAAI,CAACU,GAAG,CAACI,IAAS,CAAC;IACnB,IAAIb,cAAc,EAAEF,IAAI,CAACY,MAAM,CAACT,GAAG,CAAC;IACpC,OAAO,IAAI;EACb;EAEA,OAAO,KAAK;AACd","ignoreList":[]}
@@ -2,6 +2,7 @@
2
2
 
3
3
  import { useSyncExternalStore } from "react";
4
4
  import { NitroModules } from "react-native-nitro-modules";
5
+ import { StorageScope as StorageScopeEnum } from "./Storage.nitro.js";
5
6
  export { StorageScope } from "./Storage.nitro.js";
6
7
  let _storageModule = null;
7
8
  function getStorageModule() {
@@ -10,6 +11,19 @@ function getStorageModule() {
10
11
  }
11
12
  return _storageModule;
12
13
  }
14
+ const memoryStore = new Map();
15
+ const memoryListeners = new Set();
16
+ function notifyMemoryListeners(key, value) {
17
+ memoryListeners.forEach(listener => listener(key, value));
18
+ }
19
+ export const storage = {
20
+ clear: scope => {
21
+ memoryStore.clear();
22
+ },
23
+ clearAll: () => {
24
+ storage.clear(StorageScopeEnum.Memory);
25
+ }
26
+ };
13
27
  function defaultSerialize(value) {
14
28
  return JSON.stringify(value);
15
29
  }
@@ -19,21 +33,37 @@ function defaultDeserialize(value) {
19
33
  export function createStorageItem(config) {
20
34
  const serialize = config.serialize ?? defaultSerialize;
21
35
  const deserialize = config.deserialize ?? defaultDeserialize;
36
+ const isMemory = config.scope === StorageScopeEnum.Memory;
22
37
  const listeners = new Set();
23
38
  let unsubscribe = null;
24
39
  const ensureSubscription = () => {
25
40
  if (!unsubscribe) {
26
- unsubscribe = getStorageModule().addOnChange(config.scope, key => {
27
- if (key === config.key) {
28
- listeners.forEach(listener => listener());
29
- }
30
- });
41
+ if (isMemory) {
42
+ const listener = key => {
43
+ if (key === config.key) {
44
+ listeners.forEach(l => l());
45
+ }
46
+ };
47
+ memoryListeners.add(listener);
48
+ unsubscribe = () => memoryListeners.delete(listener);
49
+ } else {
50
+ unsubscribe = getStorageModule().addOnChange(config.scope, key => {
51
+ if (key === config.key) {
52
+ listeners.forEach(listener => listener());
53
+ }
54
+ });
55
+ }
31
56
  }
32
57
  };
33
58
  let lastRaw;
34
59
  let lastValue;
35
60
  const get = () => {
36
- const raw = getStorageModule().get(config.key, config.scope);
61
+ let raw;
62
+ if (isMemory) {
63
+ raw = memoryStore.get(config.key);
64
+ } else {
65
+ raw = getStorageModule().get(config.key, config.scope);
66
+ }
37
67
  if (raw === lastRaw && lastValue !== undefined) {
38
68
  return lastValue;
39
69
  }
@@ -41,16 +71,32 @@ export function createStorageItem(config) {
41
71
  if (raw === undefined) {
42
72
  lastValue = config.defaultValue;
43
73
  } else {
44
- lastValue = deserialize(raw);
74
+ if (isMemory) {
75
+ lastValue = raw;
76
+ } else {
77
+ lastValue = deserialize(raw);
78
+ }
45
79
  }
46
80
  return lastValue;
47
81
  };
48
- const set = value => {
49
- const serialized = serialize(value);
50
- getStorageModule().set(config.key, serialized, config.scope);
82
+ const set = valueOrFn => {
83
+ const currentValue = get();
84
+ const newValue = valueOrFn instanceof Function ? valueOrFn(currentValue) : valueOrFn;
85
+ if (isMemory) {
86
+ memoryStore.set(config.key, newValue);
87
+ notifyMemoryListeners(config.key, newValue);
88
+ } else {
89
+ const serialized = serialize(newValue);
90
+ getStorageModule().set(config.key, serialized, config.scope);
91
+ }
51
92
  };
52
93
  const deleteItem = () => {
53
- getStorageModule().remove(config.key, config.scope);
94
+ if (isMemory) {
95
+ memoryStore.delete(config.key);
96
+ notifyMemoryListeners(config.key, undefined);
97
+ } else {
98
+ getStorageModule().remove(config.key, config.scope);
99
+ }
54
100
  };
55
101
  const subscribe = callback => {
56
102
  ensureSubscription();
@@ -67,11 +113,16 @@ export function createStorageItem(config) {
67
113
  get,
68
114
  set,
69
115
  delete: deleteItem,
70
- subscribe
116
+ subscribe,
117
+ scope: config.scope,
118
+ key: config.key
71
119
  };
72
120
  }
73
121
  export function useStorage(item) {
74
122
  const value = useSyncExternalStore(item.subscribe, item.get, item.get);
75
123
  return [value, item.set];
76
124
  }
125
+ export function useSetStorage(item) {
126
+ return item.set;
127
+ }
77
128
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["useSyncExternalStore","NitroModules","StorageScope","_storageModule","getStorageModule","createHybridObject","defaultSerialize","value","JSON","stringify","defaultDeserialize","parse","createStorageItem","config","serialize","deserialize","listeners","Set","unsubscribe","ensureSubscription","addOnChange","scope","key","forEach","listener","lastRaw","lastValue","get","raw","undefined","defaultValue","set","serialized","deleteItem","remove","subscribe","callback","add","delete","size","useStorage","item"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["useSyncExternalStore","NitroModules","StorageScope","StorageScopeEnum","_storageModule","getStorageModule","createHybridObject","memoryStore","Map","memoryListeners","Set","notifyMemoryListeners","key","value","forEach","listener","storage","clear","scope","clearAll","Memory","defaultSerialize","JSON","stringify","defaultDeserialize","parse","createStorageItem","config","serialize","deserialize","isMemory","listeners","unsubscribe","ensureSubscription","l","add","delete","addOnChange","lastRaw","lastValue","get","raw","undefined","defaultValue","set","valueOrFn","currentValue","newValue","Function","serialized","deleteItem","remove","subscribe","callback","size","useStorage","item","useSetStorage"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+
3
+ export function migrateFromMMKV(mmkv, item, deleteFromMMKV = false) {
4
+ const key = item.key;
5
+ if (!mmkv.contains(key)) {
6
+ return false;
7
+ }
8
+ const value = mmkv.getString(key);
9
+ if (value !== undefined) {
10
+ try {
11
+ const parsed = JSON.parse(value);
12
+ item.set(parsed);
13
+ } catch {
14
+ item.set(value);
15
+ }
16
+ if (deleteFromMMKV) {
17
+ mmkv.delete(key);
18
+ }
19
+ return true;
20
+ }
21
+ const num = mmkv.getNumber(key);
22
+ if (num !== undefined) {
23
+ item.set(num);
24
+ if (deleteFromMMKV) mmkv.delete(key);
25
+ return true;
26
+ }
27
+ const bool = mmkv.getBoolean(key);
28
+ if (bool !== undefined) {
29
+ item.set(bool);
30
+ if (deleteFromMMKV) mmkv.delete(key);
31
+ return true;
32
+ }
33
+ return false;
34
+ }
35
+ //# sourceMappingURL=migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["migrateFromMMKV","mmkv","item","deleteFromMMKV","key","contains","value","getString","undefined","parsed","JSON","parse","set","delete","num","getNumber","bool","getBoolean"],"sourceRoot":"../../src","sources":["migration.ts"],"mappings":";;AAWA,OAAO,SAASA,eAAeA,CAC7BC,IAAc,EACdC,IAAoB,EACpBC,cAAc,GAAG,KAAK,EACb;EACT,MAAMC,GAAG,GAAGF,IAAI,CAACE,GAAG;EACpB,IAAI,CAACH,IAAI,CAACI,QAAQ,CAACD,GAAG,CAAC,EAAE;IACvB,OAAO,KAAK;EACd;EAEA,MAAME,KAAK,GAAGL,IAAI,CAACM,SAAS,CAACH,GAAG,CAAC;EAEjC,IAAIE,KAAK,KAAKE,SAAS,EAAE;IACvB,IAAI;MACF,MAAMC,MAAM,GAAGC,IAAI,CAACC,KAAK,CAACL,KAAK,CAAC;MAChCJ,IAAI,CAACU,GAAG,CAACH,MAAM,CAAC;IAClB,CAAC,CAAC,MAAM;MACNP,IAAI,CAACU,GAAG,CAACN,KAAU,CAAC;IACtB;IAEA,IAAIH,cAAc,EAAE;MAClBF,IAAI,CAACY,MAAM,CAACT,GAAG,CAAC;IAClB;IACA,OAAO,IAAI;EACb;EAEA,MAAMU,GAAG,GAAGb,IAAI,CAACc,SAAS,CAACX,GAAG,CAAC;EAC/B,IAAIU,GAAG,KAAKN,SAAS,EAAE;IACrBN,IAAI,CAACU,GAAG,CAACE,GAAQ,CAAC;IAClB,IAAIX,cAAc,EAAEF,IAAI,CAACY,MAAM,CAACT,GAAG,CAAC;IACpC,OAAO,IAAI;EACb;EAEA,MAAMY,IAAI,GAAGf,IAAI,CAACgB,UAAU,CAACb,GAAG,CAAC;EACjC,IAAIY,IAAI,KAAKR,SAAS,EAAE;IACtBN,IAAI,CAACU,GAAG,CAACI,IAAS,CAAC;IACnB,IAAIb,cAAc,EAAEF,IAAI,CAACY,MAAM,CAACT,GAAG,CAAC;IACpC,OAAO,IAAI;EACb;EAEA,OAAO,KAAK;AACd","ignoreList":[]}
@@ -1,6 +1,10 @@
1
1
  import type { StorageScope } from "./Storage.nitro";
2
2
  export { StorageScope } from "./Storage.nitro";
3
3
  export type { Storage } from "./Storage.nitro";
4
+ export declare const storage: {
5
+ clear: (scope: StorageScope.Memory) => void;
6
+ clearAll: () => void;
7
+ };
4
8
  export interface StorageItemConfig<T> {
5
9
  key: string;
6
10
  scope: StorageScope;
@@ -10,10 +14,13 @@ export interface StorageItemConfig<T> {
10
14
  }
11
15
  export interface StorageItem<T> {
12
16
  get: () => T;
13
- set: (value: T) => void;
17
+ set: (value: T | ((prev: T) => T)) => void;
14
18
  delete: () => void;
15
19
  subscribe: (callback: () => void) => () => void;
20
+ scope: StorageScope;
21
+ key: string;
16
22
  }
17
23
  export declare function createStorageItem<T = undefined>(config: StorageItemConfig<T>): StorageItem<T>;
18
- export declare function useStorage<T>(item: StorageItem<T>): [T, (value: T) => void];
24
+ export declare function useStorage<T>(item: StorageItem<T>): [T, (value: T | ((prev: T) => T)) => void];
25
+ export declare function useSetStorage<T>(item: StorageItem<T>): (value: T | ((prev: T) => T)) => void;
19
26
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAW/C,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,YAAY,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;IACjC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC,CAAC;IACb,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;CACjD;AAUD,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,SAAS,EAC7C,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC3B,WAAW,CAAC,CAAC,CAAC,CAkEhB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,CAAC,CAG3E"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG7D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,YAAY,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAkB/C,eAAO,MAAM,OAAO;mBACH,YAAY,CAAC,MAAM;;CAMnC,CAAC;AAEF,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,YAAY,CAAC;IACpB,YAAY,CAAC,EAAE,CAAC,CAAC;IACjB,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,CAAC;IACjC,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,CAAC,CAAC;CACpC;AAED,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC,CAAC;IACb,GAAG,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC;IAC3C,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IAChD,KAAK,EAAE,YAAY,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb;AAUD,wBAAgB,iBAAiB,CAAC,CAAC,GAAG,SAAS,EAC7C,MAAM,EAAE,iBAAiB,CAAC,CAAC,CAAC,GAC3B,WAAW,CAAC,CAAC,CAAC,CAwGhB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAC1B,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GACnB,CAAC,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAG5C;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,oCAlIb,IAAI,CAoI3C"}
@@ -0,0 +1,12 @@
1
+ import type { StorageItem } from "./index";
2
+ interface MMKVLike {
3
+ getString: (key: string) => string | undefined;
4
+ getNumber: (key: string) => number | undefined;
5
+ getBoolean: (key: string) => boolean | undefined;
6
+ contains: (key: string) => boolean;
7
+ delete: (key: string) => void;
8
+ getAllKeys: () => string[];
9
+ }
10
+ export declare function migrateFromMMKV<T>(mmkv: MMKVLike, item: StorageItem<T>, deleteFromMMKV?: boolean): boolean;
11
+ export {};
12
+ //# sourceMappingURL=migration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migration.d.ts","sourceRoot":"","sources":["../../src/migration.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,UAAU,QAAQ;IAChB,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/C,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAC/C,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GAAG,SAAS,CAAC;IACjD,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACnC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC9B,UAAU,EAAE,MAAM,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAgB,eAAe,CAAC,CAAC,EAC/B,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,cAAc,UAAQ,GACrB,OAAO,CAqCT"}
package/package.json CHANGED
@@ -1,12 +1,13 @@
1
1
  {
2
2
  "name": "react-native-nitro-storage",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "The fastest, most complete storage solution for React Native. Synchronous Memory, Disk, and Secure storage in one unified API. Built with Nitro Modules.",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
7
7
  "types": "lib/typescript/index.d.ts",
8
8
  "react-native": "src/index.ts",
9
9
  "source": "src/index.ts",
10
+ "app": "app.plugin.js",
10
11
  "files": [
11
12
  "src",
12
13
  "lib",
package/src/index.ts CHANGED
@@ -1,6 +1,7 @@
1
- import { useSyncExternalStore } from "react";
1
+ import { useSyncExternalStore, useMemo } from "react";
2
2
  import { NitroModules } from "react-native-nitro-modules";
3
3
  import type { Storage, StorageScope } from "./Storage.nitro";
4
+ import { StorageScope as StorageScopeEnum } from "./Storage.nitro";
4
5
 
5
6
  export { StorageScope } from "./Storage.nitro";
6
7
  export type { Storage } from "./Storage.nitro";
@@ -14,6 +15,22 @@ function getStorageModule(): Storage {
14
15
  return _storageModule!;
15
16
  }
16
17
 
18
+ const memoryStore = new Map<string, any>();
19
+ const memoryListeners = new Set<(key: string, value: any) => void>();
20
+
21
+ function notifyMemoryListeners(key: string, value: any) {
22
+ memoryListeners.forEach((listener) => listener(key, value));
23
+ }
24
+
25
+ export const storage = {
26
+ clear: (scope: StorageScope.Memory) => {
27
+ memoryStore.clear();
28
+ },
29
+ clearAll: () => {
30
+ storage.clear(StorageScopeEnum.Memory);
31
+ },
32
+ };
33
+
17
34
  export interface StorageItemConfig<T> {
18
35
  key: string;
19
36
  scope: StorageScope;
@@ -24,9 +41,11 @@ export interface StorageItemConfig<T> {
24
41
 
25
42
  export interface StorageItem<T> {
26
43
  get: () => T;
27
- set: (value: T) => void;
44
+ set: (value: T | ((prev: T) => T)) => void;
28
45
  delete: () => void;
29
46
  subscribe: (callback: () => void) => () => void;
47
+ scope: StorageScope;
48
+ key: string;
30
49
  }
31
50
 
32
51
  function defaultSerialize<T>(value: T): string {
@@ -42,26 +61,42 @@ export function createStorageItem<T = undefined>(
42
61
  ): StorageItem<T> {
43
62
  const serialize = config.serialize ?? defaultSerialize;
44
63
  const deserialize = config.deserialize ?? defaultDeserialize;
64
+ const isMemory = config.scope === StorageScopeEnum.Memory;
45
65
 
46
66
  const listeners = new Set<() => void>();
47
-
48
67
  let unsubscribe: (() => void) | null = null;
49
68
 
50
69
  const ensureSubscription = () => {
51
70
  if (!unsubscribe) {
52
- unsubscribe = getStorageModule().addOnChange(config.scope, (key) => {
53
- if (key === config.key) {
54
- listeners.forEach((listener) => listener());
55
- }
56
- });
71
+ if (isMemory) {
72
+ const listener = (key: string) => {
73
+ if (key === config.key) {
74
+ listeners.forEach((l) => l());
75
+ }
76
+ };
77
+ memoryListeners.add(listener);
78
+ unsubscribe = () => memoryListeners.delete(listener);
79
+ } else {
80
+ unsubscribe = getStorageModule().addOnChange(config.scope, (key) => {
81
+ if (key === config.key) {
82
+ listeners.forEach((listener) => listener());
83
+ }
84
+ });
85
+ }
57
86
  }
58
87
  };
59
88
 
60
- let lastRaw: string | undefined;
89
+ let lastRaw: string | any | undefined;
61
90
  let lastValue: T | undefined;
62
91
 
63
92
  const get = (): T => {
64
- const raw = getStorageModule().get(config.key, config.scope);
93
+ let raw: string | any;
94
+
95
+ if (isMemory) {
96
+ raw = memoryStore.get(config.key);
97
+ } else {
98
+ raw = getStorageModule().get(config.key, config.scope);
99
+ }
65
100
 
66
101
  if (raw === lastRaw && lastValue !== undefined) {
67
102
  return lastValue;
@@ -72,19 +107,39 @@ export function createStorageItem<T = undefined>(
72
107
  if (raw === undefined) {
73
108
  lastValue = config.defaultValue as T;
74
109
  } else {
75
- lastValue = deserialize(raw);
110
+ if (isMemory) {
111
+ lastValue = raw as T;
112
+ } else {
113
+ lastValue = deserialize(raw);
114
+ }
76
115
  }
77
116
 
78
117
  return lastValue;
79
118
  };
80
119
 
81
- const set = (value: T): void => {
82
- const serialized = serialize(value);
83
- getStorageModule().set(config.key, serialized, config.scope);
120
+ const set = (valueOrFn: T | ((prev: T) => T)): void => {
121
+ const currentValue = get();
122
+ const newValue =
123
+ valueOrFn instanceof Function
124
+ ? (valueOrFn as Function)(currentValue)
125
+ : valueOrFn;
126
+
127
+ if (isMemory) {
128
+ memoryStore.set(config.key, newValue);
129
+ notifyMemoryListeners(config.key, newValue);
130
+ } else {
131
+ const serialized = serialize(newValue);
132
+ getStorageModule().set(config.key, serialized, config.scope);
133
+ }
84
134
  };
85
135
 
86
136
  const deleteItem = (): void => {
87
- getStorageModule().remove(config.key, config.scope);
137
+ if (isMemory) {
138
+ memoryStore.delete(config.key);
139
+ notifyMemoryListeners(config.key, undefined);
140
+ } else {
141
+ getStorageModule().remove(config.key, config.scope);
142
+ }
88
143
  };
89
144
 
90
145
  const subscribe = (callback: () => void): (() => void) => {
@@ -104,10 +159,18 @@ export function createStorageItem<T = undefined>(
104
159
  set,
105
160
  delete: deleteItem,
106
161
  subscribe,
162
+ scope: config.scope,
163
+ key: config.key,
107
164
  };
108
165
  }
109
166
 
110
- export function useStorage<T>(item: StorageItem<T>): [T, (value: T) => void] {
167
+ export function useStorage<T>(
168
+ item: StorageItem<T>
169
+ ): [T, (value: T | ((prev: T) => T)) => void] {
111
170
  const value = useSyncExternalStore(item.subscribe, item.get, item.get);
112
171
  return [value, item.set];
113
172
  }
173
+
174
+ export function useSetStorage<T>(item: StorageItem<T>) {
175
+ return item.set;
176
+ }
@@ -0,0 +1,53 @@
1
+ import type { StorageItem } from "./index";
2
+
3
+ interface MMKVLike {
4
+ getString: (key: string) => string | undefined;
5
+ getNumber: (key: string) => number | undefined;
6
+ getBoolean: (key: string) => boolean | undefined;
7
+ contains: (key: string) => boolean;
8
+ delete: (key: string) => void;
9
+ getAllKeys: () => string[];
10
+ }
11
+
12
+ export function migrateFromMMKV<T>(
13
+ mmkv: MMKVLike,
14
+ item: StorageItem<T>,
15
+ deleteFromMMKV = false
16
+ ): boolean {
17
+ const key = item.key;
18
+ if (!mmkv.contains(key)) {
19
+ return false;
20
+ }
21
+
22
+ const value = mmkv.getString(key);
23
+
24
+ if (value !== undefined) {
25
+ try {
26
+ const parsed = JSON.parse(value);
27
+ item.set(parsed);
28
+ } catch {
29
+ item.set(value as T);
30
+ }
31
+
32
+ if (deleteFromMMKV) {
33
+ mmkv.delete(key);
34
+ }
35
+ return true;
36
+ }
37
+
38
+ const num = mmkv.getNumber(key);
39
+ if (num !== undefined) {
40
+ item.set(num as T);
41
+ if (deleteFromMMKV) mmkv.delete(key);
42
+ return true;
43
+ }
44
+
45
+ const bool = mmkv.getBoolean(key);
46
+ if (bool !== undefined) {
47
+ item.set(bool as T);
48
+ if (deleteFromMMKV) mmkv.delete(key);
49
+ return true;
50
+ }
51
+
52
+ return false;
53
+ }