react-native-mmkv 4.1.2 → 4.3.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/NitroMmkv.podspec +9 -2
- package/android/CMakeLists.txt +5 -0
- package/android/build.gradle +8 -3
- package/android/src/main/cpp/cpp-adapter.cpp +2 -1
- package/cpp/HybridMMKV.cpp +94 -58
- package/cpp/HybridMMKV.hpp +5 -0
- package/cpp/HybridMMKVFactory.cpp +1 -5
- package/cpp/MMKVTypes.hpp +12 -0
- package/cpp/ManagedMMBuffer.hpp +1 -1
- package/lib/__tests__/hooks.test.js +30 -1
- package/lib/createMMKV/createMMKV.web.js +17 -1
- package/lib/createMMKV/createMockMMKV.js +15 -1
- package/lib/hooks/createMMKVHook.js +9 -18
- package/lib/specs/MMKV.nitro.d.ts +46 -1
- package/lib/specs/MMKVFactory.nitro.d.ts +30 -1
- package/nitrogen/generated/android/NitroMmkvOnLoad.cpp +35 -25
- package/nitrogen/generated/android/NitroMmkvOnLoad.hpp +13 -4
- package/nitrogen/generated/android/c++/JHybridMMKVPlatformContextSpec.cpp +20 -26
- package/nitrogen/generated/android/c++/JHybridMMKVPlatformContextSpec.hpp +19 -22
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/mmkv/HybridMMKVPlatformContextSpec.kt +15 -18
- package/nitrogen/generated/ios/NitroMmkv-Swift-Cxx-Bridge.hpp +1 -1
- package/nitrogen/generated/ios/swift/HybridMMKVPlatformContextSpec.swift +0 -1
- package/nitrogen/generated/ios/swift/HybridMMKVPlatformContextSpec_cxx.swift +0 -1
- package/nitrogen/generated/shared/c++/Configuration.hpp +13 -2
- package/nitrogen/generated/shared/c++/EncryptionType.hpp +76 -0
- package/nitrogen/generated/shared/c++/HybridMMKVSpec.cpp +5 -0
- package/nitrogen/generated/shared/c++/HybridMMKVSpec.hpp +8 -0
- package/package.json +3 -3
- package/src/__tests__/hooks.test.tsx +37 -0
- package/src/createMMKV/createMMKV.web.ts +17 -1
- package/src/createMMKV/createMockMMKV.ts +15 -1
- package/src/hooks/createMMKVHook.ts +16 -19
- package/src/specs/MMKV.nitro.ts +46 -1
- package/src/specs/MMKVFactory.nitro.ts +31 -1
|
@@ -39,8 +39,18 @@ export function createMMKV(
|
|
|
39
39
|
|
|
40
40
|
return {
|
|
41
41
|
id: config.id,
|
|
42
|
-
|
|
42
|
+
get length(): number {
|
|
43
|
+
return getLocalStorage().length
|
|
44
|
+
},
|
|
45
|
+
get size(): number {
|
|
46
|
+
return this.byteSize
|
|
47
|
+
},
|
|
48
|
+
get byteSize(): number {
|
|
49
|
+
// estimate - assumes UTF8
|
|
50
|
+
return JSON.stringify(getLocalStorage()).length
|
|
51
|
+
},
|
|
43
52
|
isReadOnly: false,
|
|
53
|
+
isEncrypted: false,
|
|
44
54
|
clearAll: () => {
|
|
45
55
|
const storage = getLocalStorage()
|
|
46
56
|
const keys = Object.keys(storage)
|
|
@@ -100,6 +110,12 @@ export function createMMKV(
|
|
|
100
110
|
recrypt: () => {
|
|
101
111
|
throw new Error('`recrypt(..)` is not supported on Web!')
|
|
102
112
|
},
|
|
113
|
+
encrypt: () => {
|
|
114
|
+
throw new Error('`encrypt(..)` is not supported on Web!')
|
|
115
|
+
},
|
|
116
|
+
decrypt: () => {
|
|
117
|
+
throw new Error('`decrypt(..)` is not supported on Web!')
|
|
118
|
+
},
|
|
103
119
|
trim: () => {
|
|
104
120
|
// no-op
|
|
105
121
|
},
|
|
@@ -18,10 +18,18 @@ export function createMockMMKV(
|
|
|
18
18
|
|
|
19
19
|
return {
|
|
20
20
|
id: config.id,
|
|
21
|
-
get
|
|
21
|
+
get length(): number {
|
|
22
22
|
return storage.size
|
|
23
23
|
},
|
|
24
|
+
get size(): number {
|
|
25
|
+
return this.byteSize
|
|
26
|
+
},
|
|
27
|
+
get byteSize(): number {
|
|
28
|
+
// estimate - assumes UTF8
|
|
29
|
+
return JSON.stringify(storage).length
|
|
30
|
+
},
|
|
24
31
|
isReadOnly: false,
|
|
32
|
+
isEncrypted: false,
|
|
25
33
|
clearAll: () => {
|
|
26
34
|
const keysBefore = storage.keys()
|
|
27
35
|
storage.clear()
|
|
@@ -63,6 +71,12 @@ export function createMockMMKV(
|
|
|
63
71
|
recrypt: () => {
|
|
64
72
|
console.warn('Encryption is not supported in mocked MMKV instances!')
|
|
65
73
|
},
|
|
74
|
+
encrypt: () => {
|
|
75
|
+
console.warn('Encryption is not supported in mocked MMKV instances!')
|
|
76
|
+
},
|
|
77
|
+
decrypt: () => {
|
|
78
|
+
console.warn('Encryption is not supported in mocked MMKV instances!')
|
|
79
|
+
},
|
|
66
80
|
trim: () => {
|
|
67
81
|
// no-op
|
|
68
82
|
},
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useCallback,
|
|
1
|
+
import { useCallback, useSyncExternalStore } from 'react'
|
|
2
2
|
import { getDefaultMMKVInstance } from '../createMMKV/getDefaultMMKVInstance'
|
|
3
3
|
import type { MMKV } from '../specs/MMKV.nitro'
|
|
4
4
|
|
|
@@ -13,14 +13,21 @@ export function createMMKVHook<
|
|
|
13
13
|
): [value: T, setValue: (value: TSetAction) => void] => {
|
|
14
14
|
const mmkv = instance ?? getDefaultMMKVInstance()
|
|
15
15
|
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
const value = useSyncExternalStore(
|
|
17
|
+
useCallback(
|
|
18
|
+
(onStoreChange: () => void) => {
|
|
19
|
+
const listener = mmkv.addOnValueChangedListener((changedKey) => {
|
|
20
|
+
if (changedKey === key) {
|
|
21
|
+
onStoreChange()
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
return () => listener.remove()
|
|
25
|
+
},
|
|
26
|
+
[key, mmkv]
|
|
27
|
+
),
|
|
28
|
+
useCallback(() => getter(mmkv, key), [key, mmkv]),
|
|
29
|
+
useCallback(() => getter(mmkv, key), [key, mmkv])
|
|
30
|
+
)
|
|
24
31
|
|
|
25
32
|
// update value by user set
|
|
26
33
|
const set = useCallback(
|
|
@@ -51,16 +58,6 @@ export function createMMKVHook<
|
|
|
51
58
|
[key, mmkv]
|
|
52
59
|
)
|
|
53
60
|
|
|
54
|
-
// update value if it changes somewhere else (second hook, same key)
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
const listener = mmkv.addOnValueChangedListener((changedKey) => {
|
|
57
|
-
if (changedKey === key) {
|
|
58
|
-
setBump((b) => b + 1)
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
return () => listener.remove()
|
|
62
|
-
}, [key, mmkv])
|
|
63
|
-
|
|
64
61
|
return [value, set]
|
|
65
62
|
}
|
|
66
63
|
}
|
package/src/specs/MMKV.nitro.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { HybridObject } from 'react-native-nitro-modules'
|
|
2
|
+
import type { EncryptionType } from './MMKVFactory.nitro'
|
|
2
3
|
|
|
3
4
|
export interface Listener {
|
|
4
5
|
remove: () => void
|
|
@@ -9,15 +10,31 @@ export interface MMKV extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
|
|
|
9
10
|
* Get the ID of this {@linkcode MMKV} instance.
|
|
10
11
|
*/
|
|
11
12
|
readonly id: string
|
|
13
|
+
/**
|
|
14
|
+
* Get the current amount of key/value pairs stored in
|
|
15
|
+
* this storage.
|
|
16
|
+
*/
|
|
17
|
+
readonly length: number
|
|
12
18
|
/**
|
|
13
19
|
* Get the current total size of the storage, in bytes.
|
|
20
|
+
* @deprecated Use {@linkcode byteSize} instead.
|
|
14
21
|
*/
|
|
15
22
|
readonly size: number
|
|
16
23
|
/**
|
|
17
|
-
*
|
|
24
|
+
* Get the current total size of the storage, in bytes.
|
|
25
|
+
*/
|
|
26
|
+
readonly byteSize: number
|
|
27
|
+
/**
|
|
28
|
+
* Get whether this instance is in read-only mode or not.
|
|
18
29
|
* If this is `true`, you can only use "get"-functions.
|
|
19
30
|
*/
|
|
20
31
|
readonly isReadOnly: boolean
|
|
32
|
+
/**
|
|
33
|
+
* Get whether this instance is encrypted, or not.
|
|
34
|
+
* @see {@linkcode encrypt | encrypt(...)}
|
|
35
|
+
* @see {@linkcode decrypt | decrypt()}
|
|
36
|
+
*/
|
|
37
|
+
readonly isEncrypted: boolean
|
|
21
38
|
/**
|
|
22
39
|
* Set a {@linkcode value} for the given {@linkcode key}.
|
|
23
40
|
*
|
|
@@ -76,8 +93,36 @@ export interface MMKV extends HybridObject<{ ios: 'c++'; android: 'c++' }> {
|
|
|
76
93
|
* Encryption keys can have a maximum length of 16 bytes.
|
|
77
94
|
*
|
|
78
95
|
* @throws an Error if the instance cannot be recrypted.
|
|
96
|
+
* @deprecated Use {@linkcode encrypt | encrypt(...)} or {@linkcode decrypt | decrypt()} instead.
|
|
79
97
|
*/
|
|
80
98
|
recrypt(key: string | undefined): void
|
|
99
|
+
/**
|
|
100
|
+
* Encrypts the data in this MMKV instance with the
|
|
101
|
+
* given {@linkcode key} and {@linkcode encryptionType}.
|
|
102
|
+
*
|
|
103
|
+
* If this MMKV instance is already encrypted ({@linkcode isEncrypted}),
|
|
104
|
+
* it will re-encrypt the data.
|
|
105
|
+
*
|
|
106
|
+
* Future attempts to open this MMKV instance will require the same
|
|
107
|
+
* {@linkcode key} and {@linkcode encryptionType}, otherwise reads
|
|
108
|
+
* will fail.
|
|
109
|
+
*
|
|
110
|
+
* The {@linkcode key} must be 16-bytes in {@linkcode EncryptionType | 'AES-128'}
|
|
111
|
+
* encryption (the default), or 32-bytes in {@linkcode EncryptionType | 'AES-256'}
|
|
112
|
+
* encryption.
|
|
113
|
+
*
|
|
114
|
+
* @param key The encryption key to use. In AES-128 this must be 16-bytes, in AES-256 it must be 32-bytes long.
|
|
115
|
+
* @param encryptionType The encryption type to use. Default: AES-128
|
|
116
|
+
*/
|
|
117
|
+
encrypt(key: string, encryptionType?: EncryptionType): void
|
|
118
|
+
/**
|
|
119
|
+
* Decrypts the data in this MMKV instance and removes
|
|
120
|
+
* the encryption key.
|
|
121
|
+
*
|
|
122
|
+
* Future attempts to open this MMKV instance must be done
|
|
123
|
+
* without an encryption key, as it is now plain-text.
|
|
124
|
+
*/
|
|
125
|
+
decrypt(): void
|
|
81
126
|
/**
|
|
82
127
|
* Trims the storage space and clears memory cache.
|
|
83
128
|
*
|
|
@@ -8,6 +8,13 @@ import type { MMKV } from './MMKV.nitro'
|
|
|
8
8
|
*/
|
|
9
9
|
export type Mode = 'single-process' | 'multi-process'
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Configures the encryption algorithm for the MMKV instance.
|
|
13
|
+
* - `AES-128`: Uses AES-128 encryption (default).
|
|
14
|
+
* - `AES-256`: Uses AES-256 encryption for enhanced security.
|
|
15
|
+
*/
|
|
16
|
+
export type EncryptionType = 'AES-128' | 'AES-256'
|
|
17
|
+
|
|
11
18
|
/**
|
|
12
19
|
* Used for configuration of a single MMKV instance.
|
|
13
20
|
*/
|
|
@@ -42,7 +49,7 @@ export interface Configuration {
|
|
|
42
49
|
/**
|
|
43
50
|
* The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV.
|
|
44
51
|
*
|
|
45
|
-
* Encryption keys can have a maximum length of 16 bytes.
|
|
52
|
+
* Encryption keys can have a maximum length of 16 bytes with AES-128 encryption and 32 bytes with AES-256 encryption.
|
|
46
53
|
*
|
|
47
54
|
* @example
|
|
48
55
|
* ```ts
|
|
@@ -52,6 +59,21 @@ export interface Configuration {
|
|
|
52
59
|
* @default undefined
|
|
53
60
|
*/
|
|
54
61
|
encryptionKey?: string
|
|
62
|
+
/**
|
|
63
|
+
* The encryption algorithm to use when an encryption key is provided.
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* ```ts
|
|
67
|
+
* const secureStorage = createMMKV({
|
|
68
|
+
* id: 'secure-storage',
|
|
69
|
+
* encryptionKey: 'my-encryption-key!',
|
|
70
|
+
* encryptionType: 'AES-256'
|
|
71
|
+
* })
|
|
72
|
+
* ```
|
|
73
|
+
*
|
|
74
|
+
* @default 'AES-128'
|
|
75
|
+
*/
|
|
76
|
+
encryptionType?: EncryptionType
|
|
55
77
|
/**
|
|
56
78
|
* Configure the processing mode for MMKV.
|
|
57
79
|
*
|
|
@@ -64,6 +86,14 @@ export interface Configuration {
|
|
|
64
86
|
* @default false
|
|
65
87
|
*/
|
|
66
88
|
readOnly?: boolean
|
|
89
|
+
/**
|
|
90
|
+
* If `true`, MMKV will internally compare a value for equality before writing to
|
|
91
|
+
* disk, and if the new value is equal to what is already stored, it will skip
|
|
92
|
+
* the file write.
|
|
93
|
+
* Treat this as an optional performance optimization.
|
|
94
|
+
* @default false
|
|
95
|
+
*/
|
|
96
|
+
compareBeforeSet?: boolean
|
|
67
97
|
}
|
|
68
98
|
|
|
69
99
|
export interface MMKVFactory
|