rt-storage
Version:
A real time storage library based on localforage and rxjs.
457 lines (426 loc) • 17.7 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("localforage"), require("rxjs"));
else if(typeof define === 'function' && define.amd)
define(["localforage", "rxjs"], factory);
else if(typeof exports === 'object')
exports["RTStorage"] = factory(require("localforage"), require("rxjs"));
else
root["RTStorage"] = factory(root["localforage"], root["rxjs"]);
})(window, function(__WEBPACK_EXTERNAL_MODULE__4__, __WEBPACK_EXTERNAL_MODULE__5__) {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ (function(module, exports, __webpack_require__) {
"use strict";
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0)
t[p[i]] = s[p[i]];
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
var uuidv4 = __webpack_require__(1);
var localForage = __webpack_require__(4);
var rxjs_1 = __webpack_require__(5);
var RTStorage = /** @class */ (function () {
function RTStorage(_a) {
var _this = this;
var name = _a.name, option = __rest(_a, ["name"]);
this._name = name;
this._id = uuidv4();
localForage.config(__assign({ name: this._name }, option));
this._storage = localForage.createInstance({
name: this._name,
});
this._localStorage = localStorage;
this._storageChangedEventKey = this._name + "_storage_changed";
this._observable = new rxjs_1.Subject();
this._tabSyncHandler = function (event) { return __awaiter(_this, void 0, void 0, function () {
var _a, setter, key, value, e_1;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
if (!(event.key !== null &&
typeof event.key !== 'undefined' &&
event.key === this._storageChangedEventKey)) return [3 /*break*/, 4];
_b.label = 1;
case 1:
_b.trys.push([1, 3, , 4]);
_a = JSON.parse(event.newValue), setter = _a.setter, key = _a.key;
if (!setter || setter === this.id) {
return [2 /*return*/];
}
return [4 /*yield*/, this.getItem(key)];
case 2:
value = _b.sent();
this._observable.next({ key: key, value: value });
return [3 /*break*/, 4];
case 3:
e_1 = _b.sent();
return [3 /*break*/, 4];
case 4: return [2 /*return*/];
}
});
}); };
window.addEventListener('storage', this._tabSyncHandler);
}
RTStorage.prototype.setItem = function (key, value) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.waitForReady()];
case 1:
_a.sent();
return [4 /*yield*/, this._storage.setItem(key, { value: value, setter: this.id })];
case 2:
_a.sent();
this._observable.next({ key: key, value: value });
this._updateStorageChangeKey(key);
return [2 /*return*/];
}
});
});
};
RTStorage.prototype.getItem = function (key) {
return __awaiter(this, void 0, void 0, function () {
var originalData, value;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.waitForReady()];
case 1:
_a.sent();
return [4 /*yield*/, this._storage.getItem(key)];
case 2:
originalData = _a.sent();
try {
value = originalData.value;
return [2 /*return*/, value];
}
catch (error) {
return [2 /*return*/, undefined];
}
return [2 /*return*/];
}
});
});
};
RTStorage.prototype.removeItem = function (key) {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.waitForReady()];
case 1:
_a.sent();
return [4 /*yield*/, this._storage.removeItem(key)];
case 2:
_a.sent();
this._observable.next({ key: key, value: undefined });
this._updateStorageChangeKey(key);
return [2 /*return*/];
}
});
});
};
RTStorage.prototype.keys = function () {
return __awaiter(this, void 0, void 0, function () {
var keys;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.waitForReady()];
case 1:
_a.sent();
return [4 /*yield*/, this._storage.keys()];
case 2:
keys = _a.sent();
return [2 /*return*/, keys];
}
});
});
};
RTStorage.prototype._updateStorageChangeKey = function (key) {
this._localStorage.setItem(this._storageChangedEventKey, JSON.stringify({
timestamp: Date.now(),
key: key,
setter: this.id,
}));
};
Object.defineProperty(RTStorage.prototype, "id", {
get: function () {
return this._id;
},
enumerable: true,
configurable: true
});
RTStorage.prototype.waitForReady = function () {
return __awaiter(this, void 0, void 0, function () {
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (this._ready) {
return [2 /*return*/];
}
if (!(typeof this._storage.ready === 'function')) return [3 /*break*/, 2];
return [4 /*yield*/, this._storage.ready()];
case 1:
_a.sent();
_a.label = 2;
case 2:
this._ready = true;
return [2 /*return*/];
}
});
});
};
Object.defineProperty(RTStorage.prototype, "$", {
get: function () {
return this._observable;
},
enumerable: true,
configurable: true
});
RTStorage.prototype.subscribe = function (keyOrFunc, func) {
if (typeof keyOrFunc === 'function') {
return this._observable.subscribe(keyOrFunc);
}
return this._observable.subscribe(function (e) {
if (e.key === keyOrFunc) {
func(e.value);
}
});
};
RTStorage.prototype.destory = function () {
if (this._tabSyncHandler) {
window.removeEventListener('storage', this._tabSyncHandler);
}
};
return RTStorage;
}());
exports.default = RTStorage;
/***/ }),
/* 1 */
/***/ (function(module, exports, __webpack_require__) {
var rng = __webpack_require__(2);
var bytesToUuid = __webpack_require__(3);
function v4(options, buf, offset) {
var i = buf && offset || 0;
if (typeof(options) == 'string') {
buf = options === 'binary' ? new Array(16) : null;
options = null;
}
options = options || {};
var rnds = options.random || (options.rng || rng)();
// Per 4.4, set bits for version and `clock_seq_hi_and_reserved`
rnds[6] = (rnds[6] & 0x0f) | 0x40;
rnds[8] = (rnds[8] & 0x3f) | 0x80;
// Copy bytes to buffer, if provided
if (buf) {
for (var ii = 0; ii < 16; ++ii) {
buf[i + ii] = rnds[ii];
}
}
return buf || bytesToUuid(rnds);
}
module.exports = v4;
/***/ }),
/* 2 */
/***/ (function(module, exports) {
// Unique ID creation requires a high quality random # generator. In the
// browser this is a little complicated due to unknown quality of Math.random()
// and inconsistent support for the `crypto` API. We do the best we can via
// feature-detection
// getRandomValues needs to be invoked in a context where "this" is a Crypto
// implementation. Also, find the complete implementation of crypto on IE11.
var getRandomValues = (typeof(crypto) != 'undefined' && crypto.getRandomValues && crypto.getRandomValues.bind(crypto)) ||
(typeof(msCrypto) != 'undefined' && typeof window.msCrypto.getRandomValues == 'function' && msCrypto.getRandomValues.bind(msCrypto));
if (getRandomValues) {
// WHATWG crypto RNG - http://wiki.whatwg.org/wiki/Crypto
var rnds8 = new Uint8Array(16); // eslint-disable-line no-undef
module.exports = function whatwgRNG() {
getRandomValues(rnds8);
return rnds8;
};
} else {
// Math.random()-based (RNG)
//
// If all else fails, use Math.random(). It's fast, but is of unspecified
// quality.
var rnds = new Array(16);
module.exports = function mathRNG() {
for (var i = 0, r; i < 16; i++) {
if ((i & 0x03) === 0) r = Math.random() * 0x100000000;
rnds[i] = r >>> ((i & 0x03) << 3) & 0xff;
}
return rnds;
};
}
/***/ }),
/* 3 */
/***/ (function(module, exports) {
/**
* Convert array of 16 byte values to UUID string format of the form:
* XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
*/
var byteToHex = [];
for (var i = 0; i < 256; ++i) {
byteToHex[i] = (i + 0x100).toString(16).substr(1);
}
function bytesToUuid(buf, offset) {
var i = offset || 0;
var bth = byteToHex;
// join used to fix memory issue caused by concatenation: https://bugs.chromium.org/p/v8/issues/detail?id=3175#c4
return ([bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]], '-',
bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]],
bth[buf[i++]], bth[buf[i++]]]).join('');
}
module.exports = bytesToUuid;
/***/ }),
/* 4 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__4__;
/***/ }),
/* 5 */
/***/ (function(module, exports) {
module.exports = __WEBPACK_EXTERNAL_MODULE__5__;
/***/ })
/******/ ])["default"];
});