UNPKG

3box

Version:
596 lines (494 loc) 19.1 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } var _require = require('./utils/index'), throwIfUndefined = _require.throwIfUndefined, throwIfNotEqualLenArrays = _require.throwIfNotEqualLenArrays; var KeyValueStore = /*#__PURE__*/function () { /** * Please use **box.public** or **box.private** to get the instance of this class */ function KeyValueStore(name, replicator, threeId) { (0, _classCallCheck2["default"])(this, KeyValueStore); this._name = name; this._replicator = replicator; if (this._name.startsWith('3box.space.')) { this._space = this._name.split('.')[2]; } this._3id = threeId; } /** * Get the value and optionally metadata of the given key * * @param {String} key the key * @param {Object} opts optional parameters * @param {Boolean} opts.metadata return both value and metadata * @return {String|{value: String, timestamp: Number}} the value associated with the key, undefined if there's no such key */ (0, _createClass2["default"])(KeyValueStore, [{ key: "get", value: function () { var _get2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(key) { var opts, x, metadata, _args = arguments; return _regenerator["default"].wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: opts = _args.length > 1 && _args[1] !== undefined ? _args[1] : {}; _context.next = 3; return this._get(key); case 3: x = _context.sent; if (x) { _context.next = 6; break; } return _context.abrupt("return", x); case 6: if (!opts.metadata) { _context.next = 9; break; } metadata = this._extractMetadata(x); return _context.abrupt("return", _objectSpread(_objectSpread({}, metadata), {}, { value: x.value })); case 9: return _context.abrupt("return", x.value); case 10: case "end": return _context.stop(); } } }, _callee, this); })); function get(_x) { return _get2.apply(this, arguments); } return get; }() /** * Get metadata for for a given key * * @param {String} key the key * @return {Metadata} Metadata for the key, undefined if there's no such key */ }, { key: "getMetadata", value: function () { var _getMetadata = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(key) { var x; return _regenerator["default"].wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.next = 2; return this._get(key); case 2: x = _context2.sent; if (x) { _context2.next = 5; break; } return _context2.abrupt("return", x); case 5: return _context2.abrupt("return", this._extractMetadata(x)); case 6: case "end": return _context2.stop(); } } }, _callee2, this); })); function getMetadata(_x2) { return _getMetadata.apply(this, arguments); } return getMetadata; }() /** * Set a value for the given key * * @param {String} key the key * @param {String} value the value * @return {Boolean} true if successful */ }, { key: "set", value: function () { var _set = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee3(key, value) { var timeStamp; return _regenerator["default"].wrap(function _callee3$(_context3) { while (1) { switch (_context3.prev = _context3.next) { case 0: throwIfUndefined(key, 'key'); this._requireLoad(); this._replicator.ensureConnected(this._db.address.toString()); timeStamp = new Date().getTime(); _context3.next = 6; return this._db.put(key, { value: value, timeStamp: timeStamp }); case 6: return _context3.abrupt("return", true); case 7: case "end": return _context3.stop(); } } }, _callee3, this); })); function set(_x3, _x4) { return _set.apply(this, arguments); } return set; }() /** * Set multiple values for multiple keys * * @param {Array<String>} keys the keys * @param {Array<String>} values the values * @return {Boolean} true if successful, throw error if not */ }, { key: "setMultiple", value: function () { var _setMultiple = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee5(keys, values) { var _this = this; return _regenerator["default"].wrap(function _callee5$(_context5) { while (1) { switch (_context5.prev = _context5.next) { case 0: throwIfNotEqualLenArrays(keys, values); this._requireLoad(); this._replicator.ensureConnected(this._db.address.toString()); _context5.prev = 3; _context5.next = 6; return keys.reduce( /*#__PURE__*/function () { var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee4(previousPromise, nextKey, index) { var timeStamp; return _regenerator["default"].wrap(function _callee4$(_context4) { while (1) { switch (_context4.prev = _context4.next) { case 0: _context4.next = 2; return previousPromise; case 2: throwIfUndefined(nextKey, 'key'); timeStamp = new Date().getTime(); return _context4.abrupt("return", _this._db.put(nextKey, { value: values[index], timeStamp: timeStamp })); case 5: case "end": return _context4.stop(); } } }, _callee4); })); return function (_x7, _x8, _x9) { return _ref.apply(this, arguments); }; }(), Promise.resolve()); case 6: return _context5.abrupt("return", true); case 9: _context5.prev = 9; _context5.t0 = _context5["catch"](3); throw new Error(_context5.t0); case 12: case "end": return _context5.stop(); } } }, _callee5, this, [[3, 9]]); })); function setMultiple(_x5, _x6) { return _setMultiple.apply(this, arguments); } return setMultiple; }() /** * Remove the value for the given key * * @param {String} key the key * @return {Boolean} true if successful */ }, { key: "remove", value: function () { var _remove = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee6(key) { return _regenerator["default"].wrap(function _callee6$(_context6) { while (1) { switch (_context6.prev = _context6.next) { case 0: throwIfUndefined(key, 'key'); this._requireLoad(); this._replicator.ensureConnected(this._db.address.toString()); _context6.next = 5; return this._db.del(key); case 5: return _context6.abrupt("return", true); case 6: case "end": return _context6.stop(); } } }, _callee6, this); })); function remove(_x10) { return _remove.apply(this, arguments); } return remove; }() /** * Extract metadata from store object * @private * @param x {Object} data from store * @return {Metadata} store metadata */ }, { key: "_extractMetadata", value: function _extractMetadata(x) { // ms -> seconds, see issue #396 for details var timestamp = Math.floor(x.timeStamp / 1000); return { timestamp: timestamp }; } /** * Get the raw value of the given key * @private * * @param {String} key the key * @return {String} the value associated with the key */ }, { key: "_get", value: function () { var _get3 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee7(key) { return _regenerator["default"].wrap(function _callee7$(_context7) { while (1) { switch (_context7.prev = _context7.next) { case 0: this._requireLoad(); return _context7.abrupt("return", this._db.get(key)); case 2: case "end": return _context7.stop(); } } }, _callee7, this); })); function _get(_x11) { return _get3.apply(this, arguments); } return _get; }() }, { key: "_sync", value: function () { var _sync2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee8() { return _regenerator["default"].wrap(function _callee8$(_context8) { while (1) { switch (_context8.prev = _context8.next) { case 0: this._requireLoad(); _context8.next = 3; return this._replicator.syncDB(this._db); case 3: return _context8.abrupt("return", this._db.address.toString()); case 4: case "end": return _context8.stop(); } } }, _callee8, this); })); function _sync() { return _sync2.apply(this, arguments); } return _sync; }() }, { key: "_load", value: function () { var _load2 = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee9(threeId) { var _this2 = this; var odbAddress, key, odbIdentity; return _regenerator["default"].wrap(function _callee9$(_context9) { while (1) { switch (_context9.prev = _context9.next) { case 0: this._3id = threeId || this._3id; odbAddress = this._replicator.listStoreAddresses().find(function (odbAddress) { return odbAddress.includes(_this2._name); }); if (!odbAddress) { _context9.next = 8; break; } _context9.next = 5; return this._replicator.getStore(odbAddress); case 5: this._db = _context9.sent; _context9.next = 14; break; case 8: _context9.next = 10; return this._3id.getPublicKeys(this._space, true); case 10: key = _context9.sent.signingKey; _context9.next = 13; return this._replicator.addKVStore(this._name, key, Boolean(this._space), this._3id.getSubDID(this._space)); case 13: this._db = _context9.sent; case 14: _context9.next = 16; return this._3id.getOdbId(this._space); case 16: odbIdentity = _context9.sent; this._db.setIdentity(odbIdentity); return _context9.abrupt("return", this._db.address.toString()); case 19: case "end": return _context9.stop(); } } }, _callee9, this); })); function _load(_x12) { return _load2.apply(this, arguments); } return _load; }() }, { key: "_requireLoad", value: function _requireLoad() { if (!this._db) throw new Error('_load must be called before interacting with the store'); } }, { key: "close", value: function () { var _close = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee10() { return _regenerator["default"].wrap(function _callee10$(_context10) { while (1) { switch (_context10.prev = _context10.next) { case 0: this._requireLoad(); _context10.next = 3; return this._db.close(); case 3: case "end": return _context10.stop(); } } }, _callee10, this); })); function close() { return _close.apply(this, arguments); } return close; }() /** * Get all values and optionally metadata * * @param {Object} opts optional parameters * @param {Boolean} opts.metadata return both values and metadata * @return {Array<String|{value: String, timestamp: Number}>} the values */ }, { key: "all", value: function () { var _all = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee11() { var _this3 = this; var opts, entries, allSimple, _args11 = arguments; return _regenerator["default"].wrap(function _callee11$(_context11) { while (1) { switch (_context11.prev = _context11.next) { case 0: opts = _args11.length > 0 && _args11[0] !== undefined ? _args11[0] : {}; this._requireLoad(); entries = this._db.all; allSimple = {}; Object.keys(entries).map(function (key) { var entry = entries[key]; if (opts.metadata) { allSimple[key] = _objectSpread(_objectSpread({}, _this3._extractMetadata(entry)), {}, { value: entry.value }); } else { allSimple[key] = entry.value; } }); return _context11.abrupt("return", allSimple); case 6: case "end": return _context11.stop(); } } }, _callee11, this); })); function all() { return _all.apply(this, arguments); } return all; }() /** * Returns array of underlying log entries. In linearized order according to their Lamport clocks. * Useful for generating a complete history of all operations on store. * * @example * const log = store.log * const entry = log[0] * console.log(entry) * // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' } * * @return {Array<Object>} Array of ordered log entry objects */ }, { key: "log", value: function () { var _log = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee12() { return _regenerator["default"].wrap(function _callee12$(_context12) { while (1) { switch (_context12.prev = _context12.next) { case 0: return _context12.abrupt("return", this._db._oplog.values.map(function (obj) { return { op: obj.payload.op, key: obj.payload.key, value: obj.payload.value ? obj.payload.value.value : null, timeStamp: obj.payload.value ? obj.payload.value.timeStamp : null }; })); case 1: case "end": return _context12.stop(); } } }, _callee12, this); })); function log() { return _log.apply(this, arguments); } return log; }() }]); return KeyValueStore; }(); module.exports = KeyValueStore;