Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: return outcome of set and recrypt. #584

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions android/src/main/cpp/MmkvHostObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,19 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
"MMKV::set: First argument ('key') has to be of type string!");
}

bool result = false;
auto keyName = arguments[0].getString(runtime).utf8(runtime);

if (arguments[1].isBool()) {
// bool
instance->set(arguments[1].getBool(), keyName);
result = instance->set(arguments[1].getBool(), keyName);
} else if (arguments[1].isNumber()) {
// number
instance->set(arguments[1].getNumber(), keyName);
result = instance->set(arguments[1].getNumber(), keyName);
} else if (arguments[1].isString()) {
// string
auto stringValue = arguments[1].getString(runtime).utf8(runtime);
instance->set(stringValue, keyName);
result = instance->set(stringValue, keyName);
} else if (arguments[1].isObject()) {
// object
auto object = arguments[1].asObject(runtime);
Expand All @@ -91,7 +92,7 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
auto bufferValue = typedArray.getBuffer(runtime);
mmkv::MMBuffer buffer(bufferValue.data(runtime), bufferValue.size(runtime),
mmkv::MMBufferCopyFlag::MMBufferNoCopy);
instance->set(buffer, keyName);
result = instance->set(buffer, keyName);
} else {
// unknown object
throw jsi::JSError(
Expand All @@ -104,7 +105,7 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
"MMKV::set: 'value' argument is not of type bool, number, string or buffer!");
}

return jsi::Value::undefined();
return jsi::Value(result);
});
}

Expand Down Expand Up @@ -269,19 +270,20 @@ jsi::Value MmkvHostObject::get(jsi::Runtime& runtime, const jsi::PropNameID& pro
1, // encryptionKey
[this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
size_t count) -> jsi::Value {
bool result;
if (arguments[0].isUndefined()) {
// reset encryption key to "no encryption"
instance->reKey(std::string());
result = instance->reKey(std::string());
} else if (arguments[0].isString()) {
// reKey(..) with new encryption-key
auto encryptionKey = arguments[0].getString(runtime).utf8(runtime);
instance->reKey(encryptionKey);
result = instance->reKey(encryptionKey);
} else {
throw jsi::JSError(
runtime,
"First argument ('encryptionKey') has to be of type string (or undefined)!");
}
return jsi::Value::undefined();
return jsi::Value(result);
});
}

Expand Down
7 changes: 6 additions & 1 deletion example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export default function App() {
const [text, setText] = React.useState<string>('');
const [key, setKey] = React.useState<string>('');
const [keys, setKeys] = React.useState<string[]>([]);
const [success, setSuccess] = React.useState<boolean | undefined>();

const [example, setExample] = useMMKVString('yeeeet');

Expand All @@ -19,7 +20,8 @@ export default function App() {
}
try {
console.log('setting...');
storage.set(key, text);
const result = storage.set(key, text);
setSuccess(result);
console.log('set.');
} catch (e) {
console.error('Error:', e);
Expand Down Expand Up @@ -86,6 +88,9 @@ export default function App() {
onChangeText={setText}
/>
</View>
<View style={styles.row}>
{success && <Text>Saved: {success ? 'successfully' : 'failed'}</Text>}
</View>
<Button onPress={save} title="Save to MMKV" />
<Button onPress={read} title="Read from MMKV" />
</View>
Expand Down
19 changes: 10 additions & 9 deletions ios/MmkvHostObject.mm
Original file line number Diff line number Diff line change
Expand Up @@ -82,18 +82,18 @@
throw jsi::JSError(runtime,
"MMKV::set: First argument ('key') has to be of type string!");
}

bool result = false;
auto keyName = convertJSIStringToNSString(runtime, arguments[0].getString(runtime));
if (arguments[1].isBool()) {
// Set as boolean
[instance setBool:arguments[1].getBool() forKey:keyName];
result = [instance setBool:arguments[1].getBool() forKey:keyName];
} else if (arguments[1].isNumber()) {
// Set as number (double in JS)
[instance setDouble:arguments[1].getNumber() forKey:keyName];
result = [instance setDouble:arguments[1].getNumber() forKey:keyName];
} else if (arguments[1].isString()) {
// Set as UTF-8 string
auto stringValue = convertJSIStringToNSString(runtime, arguments[1].getString(runtime));
[instance setString:stringValue forKey:keyName];
result = [instance setString:stringValue forKey:keyName];
} else if (arguments[1].isObject()) {
// object
auto object = arguments[1].asObject(runtime);
Expand All @@ -103,7 +103,7 @@
auto bufferValue = typedArray.getBuffer(runtime);
auto data = [[NSData alloc] initWithBytes:bufferValue.data(runtime)
length:bufferValue.length(runtime)];
[instance setData:data forKey:keyName];
result = [instance setData:data forKey:keyName];
} else {
// unknown object
throw jsi::JSError(
Expand All @@ -115,7 +115,7 @@
runtime, "Second argument ('value') has to be of type bool, number or string!");
}

return jsi::Value::undefined();
return jsi::Value(result);
});
}

Expand Down Expand Up @@ -273,21 +273,22 @@
1, // encryptionKey
[this](jsi::Runtime& runtime, const jsi::Value& thisValue, const jsi::Value* arguments,
size_t count) -> jsi::Value {
bool result;
if (arguments[0].isUndefined()) {
// reset encryption key to "no encryption"
[instance reKey:nil];
result = [instance reKey:nil];
} else if (arguments[0].isString()) {
// reKey(..) with new encryption-key
NSString* encryptionKey =
convertJSIStringToNSString(runtime, arguments[0].getString(runtime));
NSData* encryptionKeyBytes = [encryptionKey dataUsingEncoding:NSUTF8StringEncoding];
[instance reKey:encryptionKeyBytes];
result = [instance reKey:encryptionKeyBytes];
} else {
throw jsi::JSError(
runtime,
"First argument ('encryptionKey') has to be of type string (or undefined)!");
}
return jsi::Value::undefined();
return jsi::Value(result);
});
}

Expand Down
15 changes: 8 additions & 7 deletions src/MMKV.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export interface MMKVConfiguration {
* ```ts
* const temporaryStorage = new MMKV({ path: '/tmp/' })
* ```
*
* _Notice_: On iOS you can set the AppGroup bundle property to share the same storage between your app and its extensions.
*
* _Notice_: On iOS you can set the AppGroup bundle property to share the same storage between your app and its extensions.
* In this case `path` property will be ignored.
* See more on MMKV configuration [here](https://github.com/Tencent/MMKV/wiki/iOS_tutorial#configuration).
*/
Expand All @@ -55,7 +55,7 @@ interface MMKVInterface {
/**
* Set a value for the given `key`.
*/
set: (key: string, value: boolean | string | number | Uint8Array) => void;
set: (key: string, value: boolean | string | number | Uint8Array) => boolean;
/**
* Get the boolean value for the given `key`, or `undefined` if it does not exist.
*
Expand Down Expand Up @@ -105,7 +105,7 @@ interface MMKVInterface {
*
* Encryption keys can have a maximum length of 16 bytes.
*/
recrypt: (key: string | undefined) => void;
recrypt: (key: string | undefined) => boolean;
/**
* Adds a value changed listener. The Listener will be called whenever any value
* in this storage instance changes (set or delete).
Expand Down Expand Up @@ -179,11 +179,12 @@ export class MMKV implements MMKVInterface {
}
}

set(key: string, value: boolean | string | number | Uint8Array): void {
set(key: string, value: boolean | string | number | Uint8Array): boolean {
const func = this.getFunctionFromCache('set');
func(key, value);
const result = func(key, value);

this.onValuesChanged([key]);
return result;
}
getBoolean(key: string): boolean | undefined {
const func = this.getFunctionFromCache('getBoolean');
Expand Down Expand Up @@ -223,7 +224,7 @@ export class MMKV implements MMKVInterface {

this.onValuesChanged(keys);
}
recrypt(key: string | undefined): void {
recrypt(key: string | undefined): boolean {
const func = this.getFunctionFromCache('recrypt');
return func(key);
}
Expand Down
6 changes: 5 additions & 1 deletion src/createMMKV.mock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ export const createMockMMKV = (): NativeMMKV => {
return {
clearAll: () => storage.clear(),
delete: (key) => storage.delete(key),
set: (key, value) => storage.set(key, value),
set: (key, value) => {
storage.set(key, value);
return true;
},
getString: (key) => {
const result = storage.get(key);
return typeof result === 'string' ? result : undefined;
Expand All @@ -28,6 +31,7 @@ export const createMockMMKV = (): NativeMMKV => {
contains: (key) => storage.has(key),
recrypt: () => {
console.warn('Encryption is not supported in mocked MMKV instances!');
return true;
},
};
};
3 changes: 2 additions & 1 deletion src/createMMKV.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export const createMMKV = (config: MMKVConfiguration): NativeMMKV => {
if (config.path != null) {
throw new Error("MMKV: 'path' is not supported on Web!");
}

// canUseDOM check prevents spam in Node server environments, such as Next.js server side props.
if (!hasAccessToLocalStorage() && canUseDOM) {
console.warn(
Expand Down Expand Up @@ -91,6 +91,7 @@ export const createMMKV = (config: MMKVConfiguration): NativeMMKV => {
delete: (key) => storage().removeItem(prefixedKey(key)),
set: (key, value) => {
storage().setItem(prefixedKey(key), value.toString());
return true;
},
getString: (key) => storage().getItem(prefixedKey(key)) ?? undefined,
getNumber: (key) => {
Expand Down
Loading