diff --git a/android/.classpath b/android/.classpath
new file mode 100644
index 0000000..32d6691
--- /dev/null
+++ b/android/.classpath
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/android/.project b/android/.project
index 0e0a1ba..675ef59 100644
--- a/android/.project
+++ b/android/.project
@@ -1,10 +1,15 @@
- android_
+ android
Project android_ created by Buildship.
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
org.eclipse.buildship.core.gradleprojectbuilder
@@ -12,6 +17,7 @@
+ org.eclipse.jdt.core.javanature
org.eclipse.buildship.core.gradleprojectnature
diff --git a/android/build.gradle b/android/build.gradle
index d7cb44b..299685d 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -22,12 +22,9 @@ def safeExtGet(prop, fallback) {
}
apply plugin: 'com.android.library'
-apply plugin: 'kotlin-android-extensions'
-apply plugin: 'kotlin-android'
apply plugin: 'maven'
buildscript {
- ext.kotlin_version = '1.3.61'
// The Android Gradle plugin is only required when opening the android folder stand-alone.
// This avoids unnecessary downloads and potential conflicts when the library is included as a
// module dependency in an application project.
@@ -44,9 +41,6 @@ buildscript {
repositories {
mavenCentral()
}
- dependencies {
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- }
}
apply plugin: 'com.android.library'
@@ -85,7 +79,6 @@ repositories {
dependencies {
//noinspection GradleDynamicVersion
implementation 'com.facebook.react:react-native:+'
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" // From node_modules
implementation "androidx.security:security-crypto:1.0.0-alpha02"
}
diff --git a/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStorageModule.java b/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStorageModule.java
new file mode 100644
index 0000000..1251620
--- /dev/null
+++ b/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStorageModule.java
@@ -0,0 +1,97 @@
+package com.emeraldsanto.encryptedstorage;
+
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.util.Log;
+
+import androidx.security.crypto.EncryptedSharedPreferences;
+import androidx.security.crypto.MasterKeys;
+
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+
+public class RNEncryptedStorageModule extends ReactContextBaseJavaModule {
+
+ private static String NATIVE_MODULE_NAME = "RNEncryptedStorage";
+ private static String SHARED_PREFERENCES_FILENAME = "RN_ENCRYPTED_STORAGE_SHARED_PREF";
+
+ private SharedPreferences sharedPreferences;
+
+ public RNEncryptedStorageModule(ReactApplicationContext context) {
+ super(context);
+
+ try {
+ this.sharedPreferences = EncryptedSharedPreferences.create(
+ RNEncryptedStorageModule.SHARED_PREFERENCES_FILENAME,
+ MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
+ context,
+ EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
+ EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
+ );
+ }
+
+ catch (Exception ex) {
+ Log.w(RNEncryptedStorageModule.NATIVE_MODULE_NAME, String.format("Could not initialize SharedPreferences - %s", ex.getLocalizedMessage()));
+ }
+ }
+
+ @Override
+ public String getName() {
+ return RNEncryptedStorageModule.NATIVE_MODULE_NAME;
+ }
+
+ @ReactMethod
+ public void setItem(String key, String value, Promise promise) {
+ if (this.sharedPreferences == null) {
+ promise.reject(new NullPointerException("Could not initialize SharedPreferences"));
+ return;
+ }
+
+ SharedPreferences.Editor editor = this.sharedPreferences.edit();
+ editor.putString(key, value);
+ boolean saved = editor.commit();
+
+ if (saved) {
+ promise.resolve(value);
+ }
+
+ else {
+ promise.reject(new Exception(String.format("An error occured while saving %s", key)));
+ }
+ }
+
+ @ReactMethod
+ public void getItem(String key, Promise promise) {
+ if (this.sharedPreferences == null) {
+ promise.reject(new NullPointerException("Could not initialize SharedPreferences"));
+ return;
+ }
+
+ String value = this.sharedPreferences.getString(key, null);
+
+ promise.resolve(value);
+ }
+
+ @ReactMethod
+ public void removeItem(String key, Promise promise) {
+ if (this.sharedPreferences == null) {
+ promise.reject(new NullPointerException("Could not initialize SharedPreferences"));
+ return;
+ }
+
+ SharedPreferences.Editor editor = this.sharedPreferences.edit();
+ editor.remove(key);
+ boolean saved = editor.commit();
+
+ if (saved) {
+ promise.resolve(key);
+ }
+
+ else {
+ promise.reject(new Exception(String.format("An error occured while removing %s", key)));
+ }
+ }
+}
diff --git a/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStorageModule.kt b/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStorageModule.kt
deleted file mode 100644
index 1ecbdb6..0000000
--- a/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStorageModule.kt
+++ /dev/null
@@ -1,77 +0,0 @@
-package com.emeraldsanto.encryptedstorage
-
-import android.content.SharedPreferences
-import android.content.res.Resources
-import androidx.security.crypto.EncryptedSharedPreferences
-import androidx.security.crypto.MasterKeys
-import com.facebook.react.bridge.Promise
-import com.facebook.react.bridge.ReactApplicationContext
-import com.facebook.react.bridge.ReactContextBaseJavaModule
-import com.facebook.react.bridge.ReactMethod
-
-class RNEncryptedStorageModule(context : ReactApplicationContext) : ReactContextBaseJavaModule(context) {
-
- companion object {
- const val NATIVE_MODULE_NAME = "RNEncryptedStorage";
- const val SHARED_PREFERENCES_FILENAME = "RN_ENCRYPTED_STORAGE_SHARED_PREF";
- }
-
- private val sharedPreferences : SharedPreferences;
-
- init {
- this.sharedPreferences = EncryptedSharedPreferences.create(
- RNEncryptedStorageModule.SHARED_PREFERENCES_FILENAME,
- MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC),
- context,
- EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
- EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
- );
- }
-
- override fun getName(): String {
- return RNEncryptedStorageModule.NATIVE_MODULE_NAME
- }
-
- @ReactMethod
- fun setItem(key : String, value : String, promise : Promise) {
- val editor = this.sharedPreferences.edit();
- editor.putString(key, value);
- val saved = editor.commit();
-
- if (saved) {
- promise.resolve(value);
- }
-
- else {
- promise.reject(Exception("An error occured while saving $key"));
- }
- }
-
- @ReactMethod
- fun getItem(key : String, promise : Promise) {
- val value = this.sharedPreferences.getString(key, "");
-
- if (value.isNullOrEmpty()) {
- promise.reject(Resources.NotFoundException("An error occured while retrieving $key"));
- }
-
- else {
- promise.resolve(value);
- }
- }
-
- @ReactMethod
- fun removeItem(key : String, promise : Promise) {
- val editor = this.sharedPreferences.edit();
- editor.remove(key);
- val saved = editor.commit();
-
- if (saved) {
- promise.resolve(key);
- }
-
- else {
- promise.reject(Exception("An error occured while removing $key"));
- }
- }
-}
\ No newline at end of file
diff --git a/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStoragePackage.java b/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStoragePackage.java
new file mode 100644
index 0000000..bf78574
--- /dev/null
+++ b/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStoragePackage.java
@@ -0,0 +1,22 @@
+package com.emeraldsanto.encryptedstorage;
+
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.util.Collections;
+import java.util.List;
+
+public class RNEncryptedStoragePackage implements ReactPackage {
+
+ @Override
+ public List createNativeModules(ReactApplicationContext reactContext) {
+ return Collections.singletonList(new RNEncryptedStorageModule(reactContext));
+ }
+
+ @Override
+ public List createViewManagers(ReactApplicationContext reactContext) {
+ return Collections.emptyList();
+ }
+}
\ No newline at end of file
diff --git a/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStoragePackage.kt b/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStoragePackage.kt
deleted file mode 100644
index d6580b5..0000000
--- a/android/src/main/java/com/emeraldsanto/encryptedstorage/RNEncryptedStoragePackage.kt
+++ /dev/null
@@ -1,21 +0,0 @@
-package com.emeraldsanto.encryptedstorage
-
-import android.view.View
-import com.facebook.react.ReactPackage
-import com.facebook.react.bridge.NativeModule
-import com.facebook.react.bridge.ReactApplicationContext
-import com.facebook.react.uimanager.ReactShadowNode
-import com.facebook.react.uimanager.ViewManager
-
-class RNEncryptedStoragePackage : ReactPackage {
-
- override fun createNativeModules(reactContext: ReactApplicationContext): MutableList {
- return mutableListOf(
- RNEncryptedStorageModule(reactContext)
- );
- }
-
- override fun createViewManagers(reactContext: ReactApplicationContext): MutableList>> {
- return mutableListOf();
- }
-}
\ No newline at end of file
diff --git a/ios/EncryptedStorage-Bridging-Header.h b/ios/EncryptedStorage-Bridging-Header.h
deleted file mode 100644
index 5ef3d27..0000000
--- a/ios/EncryptedStorage-Bridging-Header.h
+++ /dev/null
@@ -1,8 +0,0 @@
-//
-// Use this file to import your target's public headers that you would like to expose to Swift.
-//
-
-#import "React/RCTBridgeModule.h"
-#import "React/RCTViewManager.h"
-#import "React/RCTUIManager.h"
-#import "React/RCTEventEmitter.h"
diff --git a/ios/EncryptedStorage.xcodeproj/project.pbxproj b/ios/EncryptedStorage.xcodeproj/project.pbxproj
index adeb52b..c367c98 100644
--- a/ios/EncryptedStorage.xcodeproj/project.pbxproj
+++ b/ios/EncryptedStorage.xcodeproj/project.pbxproj
@@ -7,7 +7,6 @@
objects = {
/* Begin PBXBuildFile section */
- 1CAF8F2F23F383AD00FBCBB2 /* RNEncryptedStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1CAF8F2E23F383AD00FBCBB2 /* RNEncryptedStorage.swift */; };
B3E7B58A1CC2AC0600A0062D /* RNEncryptedStorage.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNEncryptedStorage.m */; };
/* End PBXBuildFile section */
@@ -25,8 +24,7 @@
/* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libEncryptedStorage.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libEncryptedStorage.a; sourceTree = BUILT_PRODUCTS_DIR; };
- 1CAF8F2D23F383AC00FBCBB2 /* EncryptedStorage-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "EncryptedStorage-Bridging-Header.h"; sourceTree = ""; };
- 1CAF8F2E23F383AD00FBCBB2 /* RNEncryptedStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RNEncryptedStorage.swift; sourceTree = ""; };
+ 1C15BF842407BE0E004846F8 /* RNEncryptedStorage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RNEncryptedStorage.h; sourceTree = ""; };
B3E7B5891CC2AC0600A0062D /* RNEncryptedStorage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNEncryptedStorage.m; sourceTree = ""; };
/* End PBXFileReference section */
@@ -52,10 +50,9 @@
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
- 1CAF8F2E23F383AD00FBCBB2 /* RNEncryptedStorage.swift */,
+ 1C15BF842407BE0E004846F8 /* RNEncryptedStorage.h */,
B3E7B5891CC2AC0600A0062D /* RNEncryptedStorage.m */,
134814211AA4EA7D00B7C361 /* Products */,
- 1CAF8F2D23F383AC00FBCBB2 /* EncryptedStorage-Bridging-Header.h */,
);
sourceTree = "";
};
@@ -117,7 +114,6 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- 1CAF8F2F23F383AD00FBCBB2 /* RNEncryptedStorage.swift in Sources */,
B3E7B58A1CC2AC0600A0062D /* RNEncryptedStorage.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -225,8 +221,9 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
- "$(SRCROOT)/../../../React/**",
+ "$(SRCROOT)/../../React/**",
"$(SRCROOT)/../../react-native/React/**",
+ "$(SRCROOT)/../../react-native/Libraries\n$(SRCROOT)/../../react-native/Libraries\n$(SRCROOT)/../../react-native/Libraries/**",
);
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
@@ -246,8 +243,9 @@
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
- "$(SRCROOT)/../../../React/**",
+ "$(SRCROOT)/../../React/**",
"$(SRCROOT)/../../react-native/React/**",
+ "$(SRCROOT)/../../react-native/Libraries\n$(SRCROOT)/../../react-native/Libraries\n$(SRCROOT)/../../react-native/Libraries/**",
);
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
LIBRARY_SEARCH_PATHS = "$(inherited)";
diff --git a/ios/RNEncryptedStorage.h b/ios/RNEncryptedStorage.h
new file mode 100644
index 0000000..3c691c3
--- /dev/null
+++ b/ios/RNEncryptedStorage.h
@@ -0,0 +1,14 @@
+//
+// RNEncryptedStorage.h
+// EncryptedStorage
+//
+// Created by Yanick Bélanger on 2020-02-27.
+// Copyright © 2020 Facebook. All rights reserved.
+//
+
+#import
+#import
+
+@interface RNEncryptedStorage : NSObject
+
+@end
diff --git a/ios/RNEncryptedStorage.m b/ios/RNEncryptedStorage.m
index f594ca6..ddf7ade 100644
--- a/ios/RNEncryptedStorage.m
+++ b/ios/RNEncryptedStorage.m
@@ -6,29 +6,94 @@
// Copyright © 2020 Facebook. All rights reserved.
//
-#import
-#import "React/RCTBridgeModule.h"
-
-@interface RCT_EXTERN_MODULE(RNEncryptedStorage, NSObject)
-
-RCT_EXTERN_METHOD(
- setItem: (NSString *)key
- value: (NSString *)value
- resolver: (RCTPromiseResolveBlock)resolve
- rejecter: (RCTPromiseRejectBlock)reject
-);
-
-RCT_EXTERN_METHOD(
- getItem: (NSString *)key
- resolver: (RCTPromiseResolveBlock)resolve
- rejecter: (RCTPromiseRejectBlock)reject
-);
-
-RCT_EXTERN_METHOD(
- removeItem: (NSString *)key
- resolver: (RCTPromiseResolveBlock)resolve
- rejecter: (RCTPromiseRejectBlock)reject
-);
+#import "RNEncryptedStorage.h"
+#import
+#import
-@end
+@implementation RNEncryptedStorage
+
++ (BOOL)requiresMainQueueSetup
+{
+ return NO;
+}
+
+RCT_EXPORT_MODULE();
+
+RCT_EXPORT_METHOD(setItem:(NSString *)key withValue:(NSString *)value resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+ NSData* dataFromValue = [value dataUsingEncoding:NSUTF8StringEncoding];
+
+ if (dataFromValue == nil) {
+ NSError* error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:0 userInfo: nil];
+ return reject(@"parse_error", @"An error occured while parsing value", error);
+ }
+
+ // Prepares the insert query structure
+ NSDictionary* storeQuery = @{
+ (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrAccount : key,
+ (__bridge id)kSecValueData : dataFromValue
+ };
+
+ // Deletes the existing item prior to inserting the new one
+ SecItemDelete((__bridge CFDictionaryRef)storeQuery);
+
+ OSStatus insertStatus = SecItemAdd((__bridge CFDictionaryRef)storeQuery, nil);
+
+ if (insertStatus == noErr) {
+ resolve(value);
+ }
+
+ else {
+ NSError* error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:1 userInfo: nil];
+ reject(@"insert_error", @"An error occured while saving value", error);
+ }
+}
+RCT_EXPORT_METHOD(getItem:(NSString *)key resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+ NSDictionary* getQuery = @{
+ (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrAccount : key,
+ (__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue,
+ (__bridge id)kSecMatchLimit : (__bridge id)kSecMatchLimitOne
+ };
+
+ CFTypeRef dataRef = NULL;
+ OSStatus getStatus = SecItemCopyMatching((__bridge CFDictionaryRef)getQuery, &dataRef);
+
+ if (getStatus == errSecSuccess) {
+ NSString* storedValue = [[NSString alloc] initWithData: (__bridge NSData*)dataRef encoding: NSUTF8StringEncoding];
+ resolve(storedValue);
+ }
+
+ else if (getStatus == errSecItemNotFound) {
+ resolve(nil);
+ }
+
+ else {
+ NSError* error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:2 userInfo: nil];
+ reject(@"retrieve_error", @"An error occured while retrieving value", error);
+ }
+}
+
+RCT_EXPORT_METHOD(removeItem:(NSString *)key resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+ NSDictionary* removeQuery = @{
+ (__bridge id)kSecClass : (__bridge id)kSecClassGenericPassword,
+ (__bridge id)kSecAttrAccount : key,
+ (__bridge id)kSecReturnData : (__bridge id)kCFBooleanTrue
+ };
+
+ OSStatus removeStatus = SecItemDelete((__bridge CFDictionaryRef)removeQuery);
+
+ if (removeStatus == noErr) {
+ resolve(key);
+ }
+
+ else {
+ NSError* error = [NSError errorWithDomain:[[NSBundle mainBundle] bundleIdentifier] code:3 userInfo: nil];
+ reject(@"remove_error", @"An error occured while removing", error);
+ }
+}
+@end
diff --git a/ios/RNEncryptedStorage.swift b/ios/RNEncryptedStorage.swift
deleted file mode 100644
index 0eb558c..0000000
--- a/ios/RNEncryptedStorage.swift
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-// RNEncryptedStorage.swift
-// EncryptedStorage
-//
-// Created by Yanick Bélanger on 2020-02-11.
-// Copyright © 2020 Facebook. All rights reserved.
-//
-
-import Foundation
-import Security
-
-@objc(RNEncryptedStorage)
-class RNEncryptedStorage: NSObject {
-
- @objc
- static func requiresMainQueueSetup() -> Bool {
- return false;
- }
-
- @objc func setItem(_ key : String, value : String, resolver resolve : RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
- guard let dataFromValue = value.data(using: .utf8, allowLossyConversion: false) else {
- return reject("Error parsing value for key \(key)", nil, nil);
- }
-
- // Prepares the insert query structure
- let storeQuery : [String : Any] = [
- kSecClass as String : kSecClassGenericPassword,
- kSecAttrAccount as String : key,
- kSecValueData as String : dataFromValue
- ];
-
- // Deletes the existing item prior to inserting the new one
- SecItemDelete(storeQuery as CFDictionary);
-
- let status = SecItemAdd(storeQuery as CFDictionary, nil);
-
- if (status == noErr) {
- resolve(value);
- }
-
- else {
- reject("An error occured while saving \(key)", nil, nil);
- }
- }
-
- @objc
- func getItem(_ key : String, resolver resolve : RCTPromiseResolveBlock, rejecter reject : RCTPromiseRejectBlock) {
- let retrieveQuery : [String : Any] = [
- kSecClass as String : kSecClassGenericPassword,
- kSecAttrAccount as String : key,
- kSecReturnData as String : kCFBooleanTrue!,
- kSecMatchLimit as String : kSecMatchLimitOne
- ];
-
- var dataRef : AnyObject? = nil;
-
- let status = SecItemCopyMatching(retrieveQuery as CFDictionary, &dataRef);
-
- if (status == noErr) {
- let stringValue = String(data : (dataRef as! Data?)!, encoding: .utf8)!;
- resolve(stringValue);
- }
-
- else {
- reject("An error occured while retrieving \(key)", nil, nil);
- }
- }
-
- @objc
- func removeItem(_ key : String, resolver resolve : RCTPromiseResolveBlock, rejecter reject : RCTPromiseRejectBlock) {
- let removeQuery : [String : Any] = [
- kSecClass as String : kSecClassGenericPassword,
- kSecAttrAccount as String : key,
- kSecReturnData as String : kCFBooleanTrue!
- ];
-
- let status = SecItemDelete(removeQuery as CFDictionary);
-
- if (status == noErr) {
- resolve(key);
- }
-
- else {
- reject("An error occured while removing \(key)", nil, nil);
- }
- }
-}
-
diff --git a/lib/EncryptedStorage.js b/lib/EncryptedStorage.js
index c2f637b..10807fd 100644
--- a/lib/EncryptedStorage.js
+++ b/lib/EncryptedStorage.js
@@ -15,8 +15,8 @@ const EncryptedStorage = {
return new Promise(async (resolve, reject) => {
try {
await RNEncryptedStorage.setItem(key, value);
- cb && cb(null);
- resolve(null);
+ cb && cb(undefined);
+ resolve(undefined);
} catch (error) {
cb && cb(error);
reject(error);
@@ -32,11 +32,11 @@ const EncryptedStorage = {
return new Promise(async (resolve, reject) => {
try {
const value = await RNEncryptedStorage.getItem(key);
- cb && cb(null, value);
- resolve(value);
+ cb && cb(undefined, value || undefined);
+ resolve(value || undefined);
} catch (error) {
- cb && cb(error, null);
- reject(error);
+ cb && cb(error, undefined);
+ reject(error);
}
});
},
@@ -49,9 +49,10 @@ const EncryptedStorage = {
return new Promise(async (resolve, reject) => {
try {
await RNEncryptedStorage.removeItem(key);
- cb && cb(null);
- resolve(null);
+ cb && cb(undefined);
+ resolve(undefined);
} catch (error) {
+ cb && cb(error);
reject(error);
}
});
diff --git a/lib/EncryptedStorage.test.js b/lib/EncryptedStorage.test.js
index f918616..4986b4e 100644
--- a/lib/EncryptedStorage.test.js
+++ b/lib/EncryptedStorage.test.js
@@ -1,128 +1,126 @@
-const EncryptedStorage = require('./EncryptedStorage');
-const { NativeModules } = require('react-native');
+const EncryptedStorage = require("./EncryptedStorage");
+const { NativeModules } = require("react-native");
const { RNEncryptedStorage } = NativeModules;
-describe('lib/EncryptedStorage', () => {
+describe("lib/EncryptedStorage", () => {
afterEach(() => {
jest.clearAllMocks();
});
- describe('using Promises', () => {
- describe('setItem(key, value)', () => {
- it('should return no errors if it could store the value', async () => {
- const storeError = await EncryptedStorage.setItem('key', 'value');
- expect(storeError).toBe(null);
+ describe("using Promises", () => {
+ describe("setItem(key, value)", () => {
+ it("should return no errors if it could store the value", () => {
+ return expect(EncryptedStorage.setItem("key", "value"))
+ .resolves
+ .toBeUndefined();
});
- it('should reject with an error if it could not store the value', async () => {
- RNEncryptedStorage.setItem.mockImplementationOnce(() => Promise.reject(new Error('Set error')));
-
- try {
- await EncryptedStorage.setItem('key', 'value');
- } catch (error) {
- expect(error.message).toBe('Set error');
- }
+ it("should reject with an error if it could not store the value", () => {
+ RNEncryptedStorage.setItem.mockImplementationOnce(() => Promise.reject(new Error("Set error")));
+
+ return expect(EncryptedStorage.setItem("key", "value"))
+ .rejects
+ .toThrow("Set error");
});
});
- describe('getItem(key)', () => {
- it('should return the value if it could be retrieved succesfully', async () => {
- const item = await EncryptedStorage.getItem('key');
- expect(item).toEqual('{ "foo": 1 }');
+ describe("getItem(key)", () => {
+ it("should return the value if it could be retrieved succesfully", () => {
+ return expect(EncryptedStorage.getItem("key"))
+ .resolves
+ .toEqual("{ \"foo\": 1 }");
});
- it('should return null if no value was found for that key', async () => {
+ it("should return null if no value was found for that key", () => {
RNEncryptedStorage.getItem.mockImplementationOnce(() => Promise.resolve(undefined));
- const item = await EncryptedStorage.getItem('key');
- expect(item).toEqual(undefined);
+ return expect(EncryptedStorage.getItem("key"))
+ .resolves
+ .toBeUndefined();
});
- it('should reject with an error if it could not retrieve the value', async () => {
+ it("should reject with an error if it could not retrieve the value", () => {
RNEncryptedStorage.getItem.mockImplementationOnce(() => Promise.reject(new Error("Get error")));
- try {
- await EncryptedStorage.getItem('key');
- } catch (error) {
- expect(error.message).toBe('Get error');
- }
+ return expect(EncryptedStorage.getItem("key"))
+ .rejects
+ .toThrow("Get error");
});
});
- describe('removeItem(key)', () => {
- it('should return no error if it could removed the stored value', async () => {
- const removeResult = await EncryptedStorage.removeItem('key');
- expect(removeResult).toBe(null);
+ describe("removeItem(key)", () => {
+ it("should return no error if it could removed the stored value", () => {
+ return expect(EncryptedStorage.removeItem("key"))
+ .resolves
+ .toBeUndefined();
});
- it('should throw an error if it could not retrieve the stored value', async () => {
+ it("should throw an error if it could not retrieve the stored value", async () => {
RNEncryptedStorage.removeItem.mockImplementationOnce(() => Promise.reject(new Error("Remove error")));
- try {
- await EncryptedStorage.removeItem('key');
- } catch (error) {
- expect(error.message).toBe('Remove error');
- }
+ return expect(EncryptedStorage.removeItem("key"))
+ .rejects
+ .toThrow("Remove error");
});
});
});
- describe('using callbacks', () => {
- describe('setItem(key, value)', () => {
- it('should return no errors if it could store the value', () => {
- EncryptedStorage.setItem('key', 'value', err => {
- expect(err).toBe(null);
+ describe("using callbacks", () => {
+ describe("setItem(key, value)", () => {
+ it("should return no errors if it could store the value", () => {
+ EncryptedStorage.setItem("key", "value", error => {
+ expect(error).toBeUndefined();
});
});
- it('should reject with an error if it could not store the value', () => {
- RNEncryptedStorage.setItem.mockImplementationOnce(() => Promise.reject(new Error('Set error')));
+ it("should reject with an error if it could not store the value", () => {
+ RNEncryptedStorage.setItem.mockImplementationOnce(() => Promise.reject(new Error("Set error")));
- EncryptedStorage.setItem('key', 'value', err => {
- expect(err.message).toBe('Set error');
+ EncryptedStorage.setItem("key", "value", error => {
+ expect(error.message).toEqual("Set error");
});
});
});
- describe('getItem(key)', () => {
- it('should return the value if it could be retrieved succesfully', () => {
- EncryptedStorage.getItem('key', (err, value) => {
- expect(err).toBe(null);
- expect(value).toEqual('{ "foo": 1 }');
+ describe("getItem(key)", () => {
+ it("should return the value if it could be retrieved succesfully", () => {
+ EncryptedStorage.getItem("key", (error, value) => {
+ expect(error).toBeUndefined();
+ expect(value).toEqual("{ \"foo\": 1 }");
});
});
- it('should return null if no value was found for that key', () => {
+ it("should return null if no value was found for that key", () => {
RNEncryptedStorage.getItem.mockImplementationOnce(() => Promise.resolve(undefined));
- EncryptedStorage.getItem('key', (err, value) => {
- expect(err).toBe(null);
- expect(value).toBe(undefined);
+ EncryptedStorage.getItem("key", (error, value) => {
+ expect(error).toBeUndefined();
+ expect(value).toBeUndefined();
});
});
- it('should reject with an error if it could not retrieve the value', () => {
+ it("should reject with an error if it could not retrieve the value", () => {
RNEncryptedStorage.getItem.mockImplementationOnce(() => Promise.reject(new Error("Get error")));
- EncryptedStorage.getItem('key', (err, value) => {
- expect(err.message).toEqual('Get error');
- expect(value).toBe(undefined);
+ EncryptedStorage.getItem("key", (error, value) => {
+ expect(error.message).toEqual("Get error");
+ expect(value).toBeUndefined();
});
});
});
- describe('removeItem(key)', () => {
- it('should return no error if it could removed the stored value', () => {
- EncryptedStorage.removeItem('key', err => {
- expect(err).toBe(null);
+ describe("removeItem(key)", () => {
+ it("should return no error if it could remove the stored value", () => {
+ EncryptedStorage.removeItem("key", error => {
+ expect(error).toBeUndefined();
});
});
- it('should throw an error if it could not retrieve the stored value', () => {
+ it("should throw an error if it could not retrieve the stored value", () => {
RNEncryptedStorage.removeItem.mockImplementationOnce(() => Promise.reject(new Error("Remove error")));
- EncryptedStorage.removeItem('key', err => {
- expect(err.message).toBe('Remove error');
+ EncryptedStorage.removeItem("key", error => {
+ expect(error.message).toEqual("Remove error");
});
});
});
diff --git a/package.json b/package.json
index 5d17d04..a27fc8f 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "react-native-encrypted-storage",
"title": "React Native Encrypted Storage",
- "version": "2.0.1",
+ "version": "2.1.0",
"description": "A React Native wrapper over SharedPreferences and Keychain to provide a secure alternative to Async Storage",
"main": "./lib/index.js",
"types": "./types/index.d.ts",
diff --git a/react-native-encrypted-storage.podspec b/react-native-encrypted-storage.podspec
index 67878d2..d6d8f13 100644
--- a/react-native-encrypted-storage.podspec
+++ b/react-native-encrypted-storage.podspec
@@ -9,7 +9,6 @@ Pod::Spec.new do |s|
s.description = <<-DESC
React Native wrapper around SharedPreferences and Keychain to provide a secure alternative to Async Storage
DESC
- s.swift_version = "5.0"
s.homepage = "https://github.com/emeraldsanto/react-native-encrypted-storage"
s.license = "MIT"
s.authors = { "Yanick" => "yanick.belanger@yahoo.com" }
diff --git a/types/index.d.ts b/types/index.d.ts
index 53fca78..6386f2c 100644
--- a/types/index.d.ts
+++ b/types/index.d.ts
@@ -8,13 +8,13 @@ declare module "react-native-encrypted-storage" {
* @param {string} key - A string that will be associated to the value for later retrieval.
* @param {Object} value - The data to store.
*/
- setItem(key : string, value : Object, callback? : (error? : Error) => void) : Promise;
+ setItem(key : string, value : string, callback? : (error? : Error) => void) : Promise;
/**
* Retrieves data from the disk, using SharedPreferences or KeyChain, depending on the platform and returns it.
* @param {string} key - A string that is associated to a value.
*/
- getItem(key : string, callback? : (error? : Error, value? : string) => void) : Promise;
+ getItem(key : string, callback? : (error? : Error, value? : string) => void) : Promise;
/**
* Deletes data from the disk, using SharedPreferences or KeyChain, depending on the platform.