Skip to content

Commit

Permalink
feat: New MMKV Core and readOnly mode (#753)
Browse files Browse the repository at this point in the history
* feat: Update MMKV core to V2

* feat: Add `isReadOnly` prop and config

* chore: Lockfiles

* feat: Upgrade deps

* feat: Upgrade deps in package

* fix: Fix missing template argument for `MMKVConfig`

* fix: Add `isReadOnly` to props

* feat: Throw JS Error about readonly

* fix: Format

* docs: Add `readOnly` to config docs
  • Loading branch information
mrousavy authored Oct 22, 2024
1 parent c164e60 commit 4f96988
Show file tree
Hide file tree
Showing 15 changed files with 1,774 additions and 1,722 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ export const storage = new MMKV({
id: `user-${userId}-storage`,
path: `${USER_DIRECTORY}/storage`,
encryptionKey: 'hunter2',
mode: Mode.MULTI_PROCESS
mode: Mode.MULTI_PROCESS,
readOnly: false
})
```

Expand All @@ -123,6 +124,7 @@ The following values can be configured:
* `path`: The MMKV instance's root path. By default, MMKV stores file inside `$(Documents)/mmkv/`. You can customize MMKV's root directory on MMKV initialization (documentation: [iOS](https://github.com/Tencent/MMKV/wiki/iOS_advance#customize-location) / [Android](https://github.com/Tencent/MMKV/wiki/android_advance#customize-location))
* `encryptionKey`: The MMKV instance's encryption/decryption key. By default, MMKV stores all key-values in plain text on file, relying on iOS's/Android's sandbox to make sure the file is encrypted. Should you worry about information leaking, you can choose to encrypt MMKV. (documentation: [iOS](https://github.com/Tencent/MMKV/wiki/iOS_advance#encryption) / [Android](https://github.com/Tencent/MMKV/wiki/android_advance#encryption))
* `mode`: The MMKV's process behaviour - when set to `MULTI_PROCESS`, the MMKV instance will assume data can be changed from the outside (e.g. App Clips, Extensions or App Groups).
* `readOnly`: Whether this MMKV instance should be in read-only mode. This is typically more efficient and avoids unwanted writes to the data if not needed. Any call to `set(..)` will throw.

### Set

Expand Down
2 changes: 1 addition & 1 deletion package/MMKV
Submodule MMKV updated 98 files
+1 −1 Android/MMKV/build.gradle
+1 −1 Android/MMKV/gradle.properties
+9 −4 Android/MMKV/mmkv/build.gradle
+83 −4 Android/MMKV/mmkv/src/main/cpp/flutter-bridge.cpp
+18 −0 Android/MMKV/mmkv/src/main/cpp/native-bridge.cpp
+15 −0 Android/MMKV/mmkv/src/main/java/com/tencent/mmkv/MMKV.java
+3 −3 Android/MMKV/mmkvdemo/build.gradle
+31 −3 Android/MMKV/mmkvdemo/src/main/java/com/tencent/mmkvdemo/MainActivity.java
+24 −0 CHANGELOG.md
+51 −15 Core/MMKV.cpp
+19 −5 Core/MMKV.h
+2 −2 Core/MMKVPredef.h
+13 −13 Core/MMKV_Android.cpp
+37 −6 Core/MMKV_IO.cpp
+15 −4 Core/MMKV_OSX.cpp
+24 −10 Core/MemoryFile.cpp
+8 −2 Core/MemoryFile.h
+4 −3 Core/MemoryFile_Android.cpp
+22 −11 Core/MemoryFile_Win32.cpp
+19 −24 Core/aes/AESCrypt.cpp
+4 −1 Core/aes/AESCrypt.h
+1 −1 OpenHarmony/MMKV/BuildProfile.ets
+5 −0 OpenHarmony/MMKV/CHANGELOG.md
+2 −1 OpenHarmony/MMKV/Index.ets
+3 −3 OpenHarmony/MMKV/README.md
+6 −3 OpenHarmony/MMKV/build-profile.json5
+32 −0 OpenHarmony/MMKV/consumer-rules.txt
+15 −1 OpenHarmony/MMKV/obfuscation-rules.txt
+1 −1 OpenHarmony/MMKV/oh-package.json5
+84 −5 OpenHarmony/MMKV/src/main/cpp/flutter-bridge.cpp
+210 −14 OpenHarmony/MMKV/src/main/cpp/native_bridge.cpp
+4 −1 OpenHarmony/MMKV/src/main/cpp/types/libmmkv/index.d.ts
+20 −4 OpenHarmony/MMKV/src/main/ets/utils/MMKV.ets
+111 −0 OpenHarmony/MMKV/src/main/ets/utils/MMKVHandler.ets
+5 −1 OpenHarmony/entry/obfuscation-rules.txt
+1 −1 OpenHarmony/entry/oh-package-lock.json5
+1 −1 OpenHarmony/entry/oh-package.json5
+76 −0 OpenHarmony/entry/src/main/ets/Util/MyMMKVHandler.ets
+2 −1 OpenHarmony/entry/src/main/ets/entryability/EntryAbility.ets
+34 −1 OpenHarmony/entry/src/main/ets/pages/Index.ets
+43 −0 POSIX/demo/demo.cpp
+16 −0 POSIX/golang/golang-bridge.cpp
+3 −0 POSIX/golang/golang-bridge.h
+18 −1 POSIX/golang/mmkv.go
+31 −2 POSIX/golang/test/main.go
+32 −3 Python/demo.py
+10 −2 Python/libmmkv_python.cpp
+3 −3 README.md
+2 −2 README_CN.md
+15 −0 SECURITY.md
+51 −0 Win32/Win32Demo/Win32Demo.cpp
+3 −0 flutter/.gitignore
+6 −0 flutter/mmkv/CHANGELOG.md
+36 −6 flutter/mmkv/example/ios/Runner.xcodeproj/project.pbxproj
+4 −4 flutter/mmkv/example/ios/Runner/Info.plist
+1 −1 flutter/mmkv/example/ios/Runner/Runner.entitlements
+72 −3 flutter/mmkv/example/lib/main.dart
+2 −0 flutter/mmkv/example/pubspec.yaml
+79 −34 flutter/mmkv/lib/mmkv.dart
+5 −5 flutter/mmkv/pubspec.yaml
+3 −0 flutter/mmkv_android/CHANGELOG.md
+2 −2 flutter/mmkv_android/android/build.gradle
+16 −5 flutter/mmkv_android/lib/mmkv_android.dart
+2 −2 flutter/mmkv_android/pubspec.yaml
+6 −0 flutter/mmkv_ios/CHANGELOG.md
+2 −14 flutter/mmkv_ios/ios/Classes/MMKVPlugin.mm
+32 −0 flutter/mmkv_ios/ios/Classes/flutter-bridge.h
+50 −52 flutter/mmkv_ios/ios/Classes/flutter-bridge.mm
+3 −3 flutter/mmkv_ios/ios/mmkv_ios.podspec
+31 −10 flutter/mmkv_ios/lib/mmkv_ios.dart
+2 −2 flutter/mmkv_ios/pubspec.yaml
+4 −1 flutter/mmkv_ohos/CHANGELOG.md
+4 −1 flutter/mmkv_ohos/lib/mmkv_ohos.dart
+2 −2 flutter/mmkv_ohos/ohos/oh-package.json5
+2 −2 flutter/mmkv_ohos/pubspec.yaml
+0 −6 flutter/mmkv_platform_interface/.flutter-plugins
+0 −1 flutter/mmkv_platform_interface/.flutter-plugins-dependencies
+4 −0 flutter/mmkv_platform_interface/CHANGELOG.md
+25 −0 flutter/mmkv_platform_interface/lib/mmkv_platform_ffi.dart
+94 −1 flutter/mmkv_platform_interface/lib/mmkv_platform_interface.dart
+1 −1 flutter/mmkv_platform_interface/pubspec.yaml
+3 −2 iOS/MMKV.podspec
+6 −6 iOS/MMKV/MMKV.xcodeproj/project.pbxproj
+16 −4 iOS/MMKV/MMKV/MMKV.h
+12 −4 iOS/MMKV/MMKV/libMMKV.mm
+2 −2 iOS/MMKVAppExtension.podspec
+2 −1 iOS/MMKVCore.podspec
+25 −9 iOS/MMKVDemo/MMKVDemo.xcodeproj/project.pbxproj
+1 −1 iOS/MMKVDemo/MMKVDemo.xcodeproj/xcshareddata/xcschemes/MMKVDemo.xcscheme
+0 −0 iOS/MMKVDemo/MMKVDemo/Resources/Assets.xcassets/AppIcon.appiconset/Contents.json
+0 −0 iOS/MMKVDemo/MMKVDemo/Resources/Base.lproj/LaunchScreen.storyboard
+0 −0 iOS/MMKVDemo/MMKVDemo/Resources/Base.lproj/Main.storyboard
+0 −0 iOS/MMKVDemo/MMKVDemo/Resources/Info.plist
+0 −0 iOS/MMKVDemo/MMKVDemo/Resources/MMKVDemo.entitlements
+ iOS/MMKVDemo/MMKVDemo/Resources/testReadOnly
+ iOS/MMKVDemo/MMKVDemo/Resources/testReadOnly.crc
+23 −1 iOS/MMKVDemo/MMKVDemo/ViewController.mm
+2 −2 iOS/MMKVWatchExtension.podspec
21 changes: 18 additions & 3 deletions package/cpp/MmkvHostObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ MmkvHostObject::MmkvHostObject(const facebook::react::MMKVConfig& config) {
std::string* pathPtr = path.size() > 0 ? &path : nullptr;
std::string* encryptionKeyPtr = encryptionKey.size() > 0 ? &encryptionKey : nullptr;
MMKVMode mode = getMMKVMode(config);
if (config.readOnly.has_value() && config.readOnly.value()) {
MmkvLogger::log("RNMMKV", "Instance is read-only!");
mode = mode | MMKVMode::MMKV_READ_ONLY;
}

#ifdef __APPLE__
instance = MMKV::mmkvWithID(config.id, mode, encryptionKeyPtr, pathPtr);
Expand Down Expand Up @@ -62,7 +66,7 @@ MmkvHostObject::~MmkvHostObject() {
std::vector<jsi::PropNameID> MmkvHostObject::getPropertyNames(jsi::Runtime& rt) {
return jsi::PropNameID::names(rt, "set", "getBoolean", "getBuffer", "getString", "getNumber",
"contains", "delete", "getAllKeys", "deleteAll", "recrypt", "trim",
"size");
"size", "isReadOnly");
}

MMKVMode MmkvHostObject::getMMKVMode(const facebook::react::MMKVConfig& config) {
Expand Down Expand Up @@ -130,7 +134,12 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
}

if (!successful) [[unlikely]] {
throw std::runtime_error("Failed to set " + keyName + "!");
if (instance->isReadOnly()) {
throw jsi::JSError(runtime,
"Failed to set " + keyName + "! This instance is read-only!");
} else {
throw jsi::JSError(runtime, "Failed to set " + keyName + "!");
}
}

return jsi::Value::undefined();
Expand Down Expand Up @@ -310,7 +319,7 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
}

if (!successful) [[unlikely]] {
throw std::runtime_error("Failed to recrypt MMKV instance!");
throw jsi::JSError(runtime, "Failed to recrypt MMKV instance!");
}

return jsi::Value::undefined();
Expand All @@ -336,5 +345,11 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
return jsi::Value(static_cast<int>(size));
}

if (propName == "isReadOnly") {
// MMKV.isReadOnly
bool isReadOnly = instance->isReadOnly();
return jsi::Value(isReadOnly);
}

return jsi::Value::undefined();
}
2 changes: 1 addition & 1 deletion package/cpp/NativeMmkvModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ namespace facebook::react {
// The MMKVConfiguration type from JS
using MMKVConfig =
NativeMmkvConfiguration<std::string, std::optional<std::string>, std::optional<std::string>,
std::optional<NativeMmkvMode>>;
std::optional<NativeMmkvMode>, std::optional<bool>>;
template <> struct Bridging<MMKVConfig> : NativeMmkvConfigurationBridging<MMKVConfig> {};

// The TurboModule itself
Expand Down
4 changes: 2 additions & 2 deletions package/example/Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ PLATFORMS
ruby

DEPENDENCIES
activesupport (>= 6.1.7.5, < 7.1.0)
cocoapods (>= 1.13, < 1.15)
activesupport (>= 6.1.7.5, != 7.1.0)
cocoapods (>= 1.13, != 1.15.1, != 1.15.0)

RUBY VERSION
ruby 2.6.10p210
Expand Down
Loading

0 comments on commit 4f96988

Please sign in to comment.