react-native-mmkv 3.0.2 → 3.1.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.
Files changed (68) hide show
  1. package/MMKV/Core/MMKV.cpp +51 -15
  2. package/MMKV/Core/MMKV.h +19 -5
  3. package/MMKV/Core/MMKVPredef.h +2 -2
  4. package/MMKV/Core/MMKV_Android.cpp +13 -13
  5. package/MMKV/Core/MMKV_IO.cpp +37 -6
  6. package/MMKV/Core/MMKV_OSX.cpp +15 -4
  7. package/MMKV/Core/MemoryFile.cpp +24 -10
  8. package/MMKV/Core/MemoryFile.h +8 -2
  9. package/MMKV/Core/MemoryFile_Android.cpp +4 -3
  10. package/MMKV/Core/MemoryFile_Win32.cpp +22 -11
  11. package/MMKV/Core/aes/AESCrypt.cpp +19 -24
  12. package/MMKV/Core/aes/AESCrypt.h +4 -1
  13. package/MMKV/README.md +354 -0
  14. package/README.md +5 -0
  15. package/cpp/MmkvHostObject.cpp +18 -3
  16. package/cpp/NativeMmkvModule.h +1 -1
  17. package/lib/commonjs/MMKV.js +5 -5
  18. package/lib/commonjs/MMKV.js.map +1 -1
  19. package/lib/commonjs/MemoryWarningListener.js +31 -0
  20. package/lib/commonjs/MemoryWarningListener.js.map +1 -0
  21. package/lib/commonjs/NativeMmkv.js +5 -5
  22. package/lib/commonjs/NativeMmkv.js.map +1 -1
  23. package/lib/commonjs/NativeMmkvPlatformContext.js +4 -4
  24. package/lib/commonjs/NativeMmkvPlatformContext.js.map +1 -1
  25. package/lib/commonjs/createMMKV.js +6 -0
  26. package/lib/commonjs/createMMKV.js.map +1 -1
  27. package/lib/commonjs/createMMKV.mock.js +1 -0
  28. package/lib/commonjs/createMMKV.mock.js.map +1 -1
  29. package/lib/commonjs/createMMKV.web.js +1 -0
  30. package/lib/commonjs/createMMKV.web.js.map +1 -1
  31. package/lib/module/MMKV.js +5 -5
  32. package/lib/module/MMKV.js.map +1 -1
  33. package/lib/module/MemoryWarningListener.js +27 -0
  34. package/lib/module/MemoryWarningListener.js.map +1 -0
  35. package/lib/module/NativeMmkv.js +5 -5
  36. package/lib/module/NativeMmkv.js.map +1 -1
  37. package/lib/module/NativeMmkvPlatformContext.js +4 -4
  38. package/lib/module/NativeMmkvPlatformContext.js.map +1 -1
  39. package/lib/module/createMMKV.js +7 -1
  40. package/lib/module/createMMKV.js.map +1 -1
  41. package/lib/module/createMMKV.mock.js +1 -0
  42. package/lib/module/createMMKV.mock.js.map +1 -1
  43. package/lib/module/createMMKV.web.js +1 -0
  44. package/lib/module/createMMKV.web.js.map +1 -1
  45. package/lib/typescript/src/MMKV.d.ts +1 -0
  46. package/lib/typescript/src/MMKV.d.ts.map +1 -1
  47. package/lib/typescript/src/MemoryWarningListener.d.ts +3 -0
  48. package/lib/typescript/src/MemoryWarningListener.d.ts.map +1 -0
  49. package/lib/typescript/src/NativeMmkv.d.ts +4 -0
  50. package/lib/typescript/src/NativeMmkv.d.ts.map +1 -1
  51. package/lib/typescript/src/NativeMmkvPlatformContext.d.ts.map +1 -1
  52. package/lib/typescript/src/Types.d.ts +5 -0
  53. package/lib/typescript/src/Types.d.ts.map +1 -1
  54. package/lib/typescript/src/createMMKV.d.ts.map +1 -1
  55. package/lib/typescript/src/createMMKV.mock.d.ts.map +1 -1
  56. package/lib/typescript/src/createMMKV.web.d.ts.map +1 -1
  57. package/package.json +12 -14
  58. package/react-native-mmkv.podspec +1 -1
  59. package/src/MMKV.ts +5 -5
  60. package/src/MemoryWarningListener.ts +29 -0
  61. package/src/NativeMmkv.ts +9 -5
  62. package/src/NativeMmkvPlatformContext.ts +6 -4
  63. package/src/Types.ts +5 -0
  64. package/src/createMMKV.mock.ts +1 -0
  65. package/src/createMMKV.ts +8 -1
  66. package/src/createMMKV.web.ts +1 -0
  67. package/img/banner-dark.png +0 -0
  68. package/img/banner-light.png +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-mmkv",
3
- "version": "3.0.2",
3
+ "version": "3.1.0",
4
4
  "description": "The fastest key/value storage for React Native. ~30x faster than AsyncStorage! Works on Android, iOS and Web.",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -26,9 +26,7 @@
26
26
  "src",
27
27
  "react-native-mmkv.podspec",
28
28
  "react-native.config.js",
29
- "../README.md",
30
- "img/banner-light.png",
31
- "img/banner-dark.png"
29
+ "README.md"
32
30
  ],
33
31
  "scripts": {
34
32
  "typescript": "tsc --noEmit",
@@ -74,23 +72,23 @@
74
72
  "devDependencies": {
75
73
  "@firmnav/eslint-github-actions-formatter": "^1.0.1",
76
74
  "@jamesacarr/eslint-formatter-github-actions": "^0.2.0",
77
- "@react-native-community/cli-types": "^14.0.1",
78
- "@react-native/eslint-config": "^0.75.2",
79
- "@release-it/conventional-changelog": "^8.0.1",
80
- "@testing-library/react-native": "^12.6.1",
81
- "@types/jest": "^29.5.5",
82
- "@types/react": "^18.3.4",
83
- "del-cli": "^5.1.0",
75
+ "@react-native-community/cli-types": "^14.1.1",
76
+ "@react-native/eslint-config": "^0.75.4",
77
+ "@release-it/conventional-changelog": "^9.0.1",
78
+ "@testing-library/react-native": "^12.7.2",
79
+ "@types/jest": "^29.5.13",
80
+ "@types/react": "^18.3.11",
81
+ "del-cli": "^6.0.0",
84
82
  "eslint": "^8.51.0",
85
83
  "eslint-config-prettier": "^9.0.0",
86
84
  "eslint-plugin-prettier": "^5.2.1",
87
85
  "jest": "^29.7.0",
88
86
  "prettier": "^3.3.3",
89
87
  "react": "^18.3.1",
90
- "react-native": "^0.75.2",
91
- "react-native-builder-bob": "^0.30.0",
88
+ "react-native": "^0.75.4",
89
+ "react-native-builder-bob": "^0.30.2",
92
90
  "react-test-renderer": "18.3.1",
93
- "release-it": "^17.6.0",
91
+ "release-it": "^17.10.0",
94
92
  "typescript": "^5.5.4"
95
93
  },
96
94
  "resolutions": {
@@ -14,7 +14,7 @@ Pod::Spec.new do |s|
14
14
  s.license = package["license"]
15
15
  s.authors = package["author"]
16
16
 
17
- s.platforms = { :ios => min_ios_version_supported }
17
+ s.platforms = { :ios => min_ios_version_supported, :tvos => "12.0", :osx => "10.14" }
18
18
  s.source = { :git => "https://github.com/mrousavy/react-native-mmkv.git", :tag => "#{s.version}" }
19
19
 
20
20
  s.pod_target_xcconfig = {
package/src/MMKV.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { AppState } from 'react-native';
2
1
  import { createMMKV } from './createMMKV';
3
2
  import { createMockMMKV } from './createMMKV.mock';
4
3
  import { isTest } from './PlatformChecker';
5
4
  import type { Configuration } from './NativeMmkv';
6
5
  import type { Listener, MMKVInterface, NativeMMKV } from './Types';
6
+ import { addMemoryWarningListener } from './MemoryWarningListener';
7
7
 
8
8
  const onValueChangedListeners = new Map<string, ((key: string) => void)[]>();
9
9
 
@@ -26,10 +26,7 @@ export class MMKV implements MMKVInterface {
26
26
  : createMMKV(configuration);
27
27
  this.functionCache = {};
28
28
 
29
- AppState.addEventListener('memoryWarning', () => {
30
- // when we have a memory warning, delete unused keys by trimming MMKV
31
- this.trim();
32
- });
29
+ addMemoryWarningListener(this);
33
30
  }
34
31
 
35
32
  private get onValueChangedListeners() {
@@ -61,6 +58,9 @@ export class MMKV implements MMKVInterface {
61
58
  get size(): number {
62
59
  return this.nativeInstance.size;
63
60
  }
61
+ get isReadOnly(): boolean {
62
+ return this.nativeInstance.isReadOnly;
63
+ }
64
64
  set(key: string, value: boolean | string | number | ArrayBuffer): void {
65
65
  const func = this.getFunctionFromCache('set');
66
66
  func(key, value);
@@ -0,0 +1,29 @@
1
+ import { AppState } from 'react-native';
2
+ import type { NativeEventSubscription } from 'react-native';
3
+ import { MMKVInterface } from './Types';
4
+
5
+ export function addMemoryWarningListener(mmkv: MMKVInterface): void {
6
+ if (global.WeakRef != null && global.FinalizationRegistry != null) {
7
+ // 1. Weakify MMKV so we can safely use it inside the memoryWarning event listener
8
+ const weakMmkv = new WeakRef(mmkv);
9
+ const listener = AppState.addEventListener('memoryWarning', () => {
10
+ // 0. Everytime we receive a memoryWarning, we try to trim the MMKV instance (if it is still valid)
11
+ weakMmkv.deref()?.trim();
12
+ });
13
+ // 2. Add a listener to when the MMKV instance is deleted
14
+ const finalization = new FinalizationRegistry(
15
+ (l: NativeEventSubscription) => {
16
+ // 3. When MMKV is deleted, this listener will be called with the memoryWarning listener.
17
+ l.remove();
18
+ }
19
+ );
20
+ // 2.1. Bind the listener to the actual MMKV instance.
21
+ finalization.register(mmkv, listener);
22
+ } else {
23
+ // WeakRef/FinalizationRegistry is not implemented in this engine.
24
+ // Just add the listener, even if it retains MMKV strong forever.
25
+ AppState.addEventListener('memoryWarning', () => {
26
+ mmkv.trim();
27
+ });
28
+ }
29
+ }
package/src/NativeMmkv.ts CHANGED
@@ -70,6 +70,10 @@ export interface Configuration {
70
70
  * @default SINGLE_PROCESS
71
71
  */
72
72
  mode?: Mode;
73
+ /**
74
+ * If `true`, the MMKV instance can only read from the storage, but not write to it.
75
+ */
76
+ readOnly?: boolean;
73
77
  }
74
78
 
75
79
  export interface Spec extends TurboModule {
@@ -85,23 +89,23 @@ export interface Spec extends TurboModule {
85
89
  createMMKV(configuration: Configuration): UnsafeObject;
86
90
  }
87
91
 
88
- let module: Spec | null;
92
+ let mmkvModule: Spec | null;
89
93
 
90
94
  export function getMMKVTurboModule(): Spec {
91
95
  try {
92
- if (module == null) {
96
+ if (mmkvModule == null) {
93
97
  // 1. Load MMKV TurboModule
94
- module = TurboModuleRegistry.getEnforcing<Spec>('MmkvCxx');
98
+ mmkvModule = TurboModuleRegistry.getEnforcing<Spec>('MmkvCxx');
95
99
 
96
100
  // 2. Get the PlatformContext TurboModule as well
97
101
  const platformContext = getMMKVPlatformContextTurboModule();
98
102
 
99
103
  // 3. Initialize it with the documents directory from platform-specific context
100
104
  const basePath = platformContext.getBaseDirectory();
101
- module.initialize(basePath);
105
+ mmkvModule.initialize(basePath);
102
106
  }
103
107
 
104
- return module;
108
+ return mmkvModule;
105
109
  } catch (cause) {
106
110
  // TurboModule could not be found!
107
111
  throw new ModuleNotFoundError(cause);
@@ -20,15 +20,17 @@ export interface Spec extends TurboModule {
20
20
  getAppGroupDirectory(): string | undefined;
21
21
  }
22
22
 
23
- let module: Spec | null;
23
+ let mmkvPlatformModule: Spec | null;
24
24
 
25
25
  export function getMMKVPlatformContextTurboModule(): Spec {
26
26
  try {
27
- if (module == null) {
27
+ if (mmkvPlatformModule == null) {
28
28
  // 1. Get the TurboModule
29
- module = TurboModuleRegistry.getEnforcing<Spec>('MmkvPlatformContext');
29
+ mmkvPlatformModule = TurboModuleRegistry.getEnforcing<Spec>(
30
+ 'MmkvPlatformContext'
31
+ );
30
32
  }
31
- return module;
33
+ return mmkvPlatformModule;
32
34
  } catch (e) {
33
35
  // TurboModule could not be found!
34
36
  throw new ModuleNotFoundError(e);
package/src/Types.ts CHANGED
@@ -74,6 +74,11 @@ export interface NativeMMKV {
74
74
  * Get the current total size of the storage, in bytes.
75
75
  */
76
76
  readonly size: number;
77
+ /**
78
+ * Returns whether this instance is in read-only mode or not.
79
+ * If this is `true`, you can only use "get"-functions.
80
+ */
81
+ readonly isReadOnly: boolean;
77
82
  }
78
83
 
79
84
  export interface Listener {
@@ -30,6 +30,7 @@ export const createMockMMKV = (): NativeMMKV => {
30
30
  console.warn('Encryption is not supported in mocked MMKV instances!');
31
31
  },
32
32
  size: 0,
33
+ isReadOnly: false,
33
34
  trim: () => {
34
35
  // no-op
35
36
  },
package/src/createMMKV.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Platform } from 'react-native';
2
- import { getMMKVTurboModule, type Configuration } from './NativeMmkv';
2
+ import { getMMKVTurboModule, Mode, type Configuration } from './NativeMmkv';
3
3
  import type { NativeMMKV } from './Types';
4
4
  import { getMMKVPlatformContextTurboModule } from './NativeMmkvPlatformContext';
5
5
 
@@ -23,6 +23,13 @@ export const createMMKV = (config: Configuration): NativeMMKV => {
23
23
  }
24
24
  }
25
25
 
26
+ if (typeof config.mode === 'number') {
27
+ // Code-gen expects enums to be strings. In TS, they might be numbers tho.
28
+ // This sucks, so we need a workaround.
29
+ // @ts-expect-error the native side actually expects a string.
30
+ config.mode = Mode[config.mode];
31
+ }
32
+
26
33
  const instance = module.createMMKV(config);
27
34
  if (__DEV__) {
28
35
  if (typeof instance !== 'object' || instance == null) {
@@ -120,6 +120,7 @@ export const createMMKV = (config: Configuration): NativeMMKV => {
120
120
  throw new Error('`recrypt(..)` is not supported on Web!');
121
121
  },
122
122
  size: 0,
123
+ isReadOnly: false,
123
124
  trim: () => {
124
125
  // no-op
125
126
  },
Binary file
Binary file