Skip to content

Commit

Permalink
Remove dep on localforage
Browse files Browse the repository at this point in the history
refs #39
  • Loading branch information
rickmak committed Nov 16, 2016
2 parents b7440b0 + 7f9ecda commit 8cd2271
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 78 deletions.
220 changes: 156 additions & 64 deletions lib/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,25 @@ var store;
import {CookieStorage} from 'cookie-storage';
import {isLocalStorageValid} from './util';

class Store {
constructor(storage, keyWhiteList) {
this.storage = storage;
this.keyWhiteList = keyWhiteList;
class SyncStorageDriver {

constructor(syncImpl) {
this._syncImpl = syncImpl;
}

clear(callback) {
return new Promise(function (resolve) {
this.storage.clear();
this._syncImpl.clear();
if (callback) {
callback();
callback(null);
}
resolve();
}.bind(this));
}

getItem(key, callback) {
return new Promise(function (resolve) {
let value = this.storage.getItem(key);
const value = this._syncImpl.getItem(key);
if (callback) {
callback(null, value);
}
Expand All @@ -50,83 +50,175 @@ class Store {

setItem(key, value, callback) {
return new Promise(function (resolve, reject) {
if (this.keyWhiteList && this.keyWhiteList.indexOf(key) === -1) {
reject('Saving key is not permitted');
return;
try {
this._syncImpl.setItem(key, value);
if (callback) {
callback(null);
}
resolve();
} catch (e) {
if (callback) {
callback(e);
}
reject(e);
}
this.storage.setItem(key, value);
if (callback) {
callback(value);
}
resolve(value);
}.bind(this));
}

removeItem(key, callback) {
return new Promise(function (resolve) {
this.storage.removeItem(key);
this._syncImpl.removeItem(key);
if (callback) {
callback();
callback(null);
}
resolve();
}.bind(this));
}

key(n, callback) {
return new Promise(function (resolve) {
const result = this._syncImpl.key(n);
if (callback) {
callback(null, result);
}
resolve(result);
}.bind(this));
}

keys(callback) {
return new Promise(function (resolve) {
const length = this._syncImpl.length;
const output = [];
for (let i = 0; i < length; ++i) {
output.push(this._syncImpl.key(i));
}
if (callback) {
callback(null, output);
}
resolve(output);
}.bind(this));
}

length(callback) {
return new Promise(function (resolve) {
const length = this._syncImpl.length;
if (callback) {
callback(null, length);
}
resolve(length);
}.bind(this));
}

}

if (typeof window !== 'undefined') {
var localforage = require('localforage');
class ReactNativeAsyncStorageDriver {

var rn = require('react-native');
constructor(rnImpl) {
this._rnImpl = rnImpl;
}

if (rn && rn.AsyncStorage) {
var AsyncStorage = rn.AsyncStorage;
var ReactNativeDriver = {
_driver: 'ReactNativeAsyncStorage',
_support: true,
_initStorage: function (options) { //eslint-disable-line
console.log('Init ReactNativeAsyncStorage');
return;
},
clear: function (callback) {
return AsyncStorage.clear(callback);
},
getItem: function (key, callback) {
return AsyncStorage.getItem(key, callback);
},
setItem: function (key, value, callback) {
return AsyncStorage.setItem(key, value, callback);
},
removeItem: function (key, callback) {
return AsyncStorage.removeItem(key, callback);
},
key: function (n, callback) { //eslint-disable-line
throw Error('Not support key in ReactNativeAsyncStorage');
},
keys: function (callback) {
AsyncStorage.getAllKeys(callback);
},
length: function (callback) { //eslint-disable-line
throw Error('Not support length in ReactNativeAsyncStorage');
},
iterate: function(iterator, callback) { //eslint-disable-line
// localForage doc is incorrect,
// https://mozilla.github.io/localForage/#config
throw Error('Not support iterate in ReactNativeAsyncStorage');
clear(callback) {
return this._rnImpl.clear(callback);
}

getItem(key, callback) {
return this._rnImpl.getItem(key, callback);
}

setItem(key, value, callback) {
return this._rnImpl.setItem(key, value, callback);
}

removeItem(key, callback) {
return this._rnImpl.removeItem(key, callback);
}

key(n, callback) {
return this._rnImpl.getAllKeys().then(function (allKeys) {
let result = null;
if (n >= 0 && n < allKeys.length) {
result = allKeys[n];
}
if (callback) {
callback(null, result);
}
};
return result;
});
}

store = ReactNativeDriver;
} else {
if (isLocalStorageValid()) {
store = localforage;
} else {
var storage = new CookieStorage();
store = new Store(storage, cookieKeyWhiteList);
keys(callback) {
return this._rnImpl.getAllKeys(callback);
}

length(callback) {
return this._rnImpl.getAllKeys().then(function (allKeys) {
if (callback) {
callback(null, allKeys.length);
}
return allKeys.length;
});
}

}

class Store {
constructor(driver, keyWhiteList) {
this._driver = driver;
this.keyWhiteList = keyWhiteList;
}

clear(callback) {
return this._driver.clear(callback);
}

getItem(key, callback) {
return this._driver.getItem(key, callback);
}

setItem(key, value, callback) {
if (this.keyWhiteList && this.keyWhiteList.indexOf(key) < 0) {
return Promise.reject(new Error('Saving key is not permitted'));
}
return this._driver.setItem(key, value, callback);
}

removeItem(key, callback) {
return this._driver.removeItem(key, callback);
}

key(n, callback) {
return this._driver.key(n, callback);
}

keys(callback) {
return this._driver.keys(callback);
}

length(callback) {
return this._driver.length(callback);
}

}

/* global window: false */
if (typeof window !== 'undefined') {
// env: browser-like
var rn = require('react-native');
if (rn && rn.AsyncStorage) {
// env: ReactNative
store = new Store(new ReactNativeAsyncStorageDriver(rn.AsyncStorage));
} else if (isLocalStorageValid()) {
// env: Modern browsers
store = new Store(new SyncStorageDriver(window.localStorage));
} else {
// env: Legacy browsers
var cookieImpl = new CookieStorage();
store = new Store(new SyncStorageDriver(cookieImpl, cookieKeyWhiteList));
}
} else {
var localStorage = require('localstorage-memory');
store = new Store(localStorage);
// env: node
var memoryImpl = require('localstorage-memory');
store = new Store(new SyncStorageDriver(memoryImpl));
}

export default store;
18 changes: 5 additions & 13 deletions lib/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,20 +62,12 @@ export function fromJSON(attrs) {
}

export function isLocalStorageValid() {
/*global localStorage: false*/
/* global window: false */
try {
var valid = typeof localStorage !== 'undefined' &&
'setItem' in localStorage &&
localStorage.setItem;
// localForage detect the localStorage support incorrectly
// under safari private mode, localStorage.setItem is not null
// but will throw exception when you call it
// https://github.com/mozilla/localForage/issues/145
if (valid) {
localStorage.setItem('_skygear_test', 'test');
localStorage.removeItem('_skygear_test');
}
return valid;
var testKey = '_skygear_test';
window.localStorage.setItem(testKey, 'test');
window.localStorage.removeItem(testKey);
return true;
} catch (e) {
return false;
}
Expand Down
1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@
"cookie-storage": "^1.0.4",
"event-emitter": "^0.3.4",
"formidable": "^1.0.17",
"localforage": "^1.4.2",
"localstorage-memory": "^1.0.2",
"lodash": "^3.10.1",
"md5": "^2.0.0",
Expand Down

0 comments on commit 8cd2271

Please sign in to comment.