/* ========================================================================== * dexie-export-import.js * ========================================================================== * * Dexie addon for exporting and importing databases to / from Blobs. * * By David Fahlander, david.fahlander@gmail.com, * * ========================================================================== * * Version 4.0.7, Wed Mar 29 2023 * * https://dexie.org * * Apache License Version 2.0, January 2004, http://www.apache.org/licenses/ * */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('dexie')) : typeof define === 'function' && define.amd ? define(['exports', 'dexie'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.DexieExportImport = {}, global.Dexie)); })(this, (function (exports, Dexie) { 'use strict'; function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var Dexie__default = /*#__PURE__*/_interopDefaultLegacy(Dexie); /*! ***************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } 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) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(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 }; } } function getSchemaString(table) { var primKeyAndIndexes = [table.schema.primKey].concat(table.schema.indexes); return primKeyAndIndexes.map(function (index) { return index.src; }).join(','); } function extractDbSchema(exportedDb) { var schema = {}; for (var _i = 0, _a = exportedDb.tables; _i < _a.length; _i++) { var table = _a[_i]; schema[table.name] = table.schema; } return schema; } function readBlobAsync(blob, type) { return new Promise(function (resolve, reject) { var reader = new FileReader(); reader.onabort = function (ev) { return reject(new Error("file read aborted")); }; reader.onerror = function (ev) { return reject(ev.target.error); }; reader.onload = function (ev) { return resolve(ev.target.result); }; if (type === 'binary') reader.readAsArrayBuffer(blob); else reader.readAsText(blob); }); } function readBlobSync(blob, type) { if (typeof FileReaderSync === 'undefined') { throw new Error('FileReaderSync missing. Reading blobs synchronously requires code to run from within a web worker. Use TSON.encapsulateAsync() to do it from the main thread.'); } var reader = new FileReaderSync(); // Requires worker environment var data = type === 'binary' ? reader.readAsArrayBuffer(blob) : reader.readAsText(blob); return data; } var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {}; function createCommonjsModule(fn, module) { return module = { exports: {} }, fn(module, module.exports), module.exports; } var typeson = createCommonjsModule(function (module, exports) { (function (global, factory) { module.exports = factory() ; }(commonjsGlobal, (function () { function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function (obj) { return typeof obj; }; } else { _typeof = function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; } function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 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 _objectSpread2(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) { _defineProperty(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; } function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } /** * We keep this function minimized so if using two instances of this * library, where one is minimized and one is not, it will still work * with `hasConstructorOf`. * With ES6 classes, we may be able to simply use `class TypesonPromise * extends Promise` and add a string tag for detection. * @param {function} f */ // eslint-disable-next-line max-len // eslint-disable-next-line block-spacing, space-before-function-paren, space-before-blocks, space-infix-ops, semi, promise/avoid-new var TypesonPromise = function TypesonPromise(f) { _classCallCheck(this, TypesonPromise); this.p = new Promise(f); }; // eslint-disable-next-line max-len // class TypesonPromise extends Promise {get[Symbol.toStringTag](){return 'TypesonPromise'};} // eslint-disable-line keyword-spacing, space-before-function-paren, space-before-blocks, block-spacing, semi TypesonPromise.__typeson__type__ = 'TypesonPromise'; // Note: core-js-bundle provides a `Symbol` polyfill /* istanbul ignore else */ if (typeof Symbol !== 'undefined') { // Ensure `isUserObject` will return `false` for `TypesonPromise` TypesonPromise.prototype[Symbol.toStringTag] = 'TypesonPromise'; } /** * * @param {function} [onFulfilled] * @param {function} [onRejected] * @returns {TypesonPromise} */ TypesonPromise.prototype.then = function (onFulfilled, onRejected) { var _this = this; return new TypesonPromise(function (typesonResolve, typesonReject) { // eslint-disable-next-line promise/catch-or-return _this.p.then(function (res) { // eslint-disable-next-line promise/always-return typesonResolve(onFulfilled ? onFulfilled(res) : res); })["catch"](function (res) { return onRejected ? onRejected(res) : Promise.reject(res); }).then(typesonResolve, typesonReject); }); }; /** * * @param {function} onRejected * @returns {TypesonPromise} */ TypesonPromise.prototype["catch"] = function (onRejected) { return this.then(null, onRejected); }; /** * * @param {Any} v * @returns {TypesonPromise} */ TypesonPromise.resolve = function (v) { return new TypesonPromise(function (typesonResolve) { typesonResolve(v); }); }; /** * * @param {Any} v * @returns {TypesonPromise} */ TypesonPromise.reject = function (v) { return new TypesonPromise(function (typesonResolve, typesonReject) { typesonReject(v); }); }; ['all', 'race'].forEach(function (meth) { /** * * @param {Promise[]} promArr * @returns {TypesonPromise} */ TypesonPromise[meth] = function (promArr) { return new TypesonPromise(function (typesonResolve, typesonReject) { // eslint-disable-next-line promise/catch-or-return Promise[meth](promArr.map(function (prom) { return prom && prom.constructor && prom.constructor.__typeson__type__ === 'TypesonPromise' ? prom.p : prom; })).then(typesonResolve, typesonReject); }); }; }); var _ref = {}, toStr = _ref.toString, hasOwn = {}.hasOwnProperty, getProto = Object.getPrototypeOf, fnToString = hasOwn.toString; /** * Second argument not in use internally, but provided for utility. * @param {Any} v * @param {boolean} catchCheck * @returns {boolean} */ function isThenable(v, catchCheck) { return isObject(v) && typeof v.then === 'function' && (!catchCheck || typeof v["catch"] === 'function'); } /** * * @param {Any} val * @returns {string} */ function toStringTag(val) { return toStr.call(val).slice(8, -1); } /** * This function is dependent on both constructors * being identical so any minimization is expected of both. * @param {Any} a * @param {function} b * @returns {boolean} */ function hasConstructorOf(a, b) { if (!a || _typeof(a) !== 'object') { return false; } var proto = getProto(a); if (!proto) { return b === null; } var Ctor = hasOwn.call(proto, 'constructor') && proto.constructor; if (typeof Ctor !== 'function') { return b === null; } if (b === Ctor) { return true; } if (b !== null && fnToString.call(Ctor) === fnToString.call(b)) { return true; } if (typeof b === 'function' && typeof Ctor.__typeson__type__ === 'string' && Ctor.__typeson__type__ === b.__typeson__type__) { return true; } return false; } /** * * @param {Any} val * @returns {boolean} */ function isPlainObject(val) { // Mirrors jQuery's if (!val || toStringTag(val) !== 'Object') { return false; } var proto = getProto(val); if (!proto) { // `Object.create(null)` return true; } return hasConstructorOf(val, Object); } /** * * @param {Any} val * @returns {boolean} */ function isUserObject(val) { if (!val || toStringTag(val) !== 'Object') { return false; } var proto = getProto(val); if (!proto) { // `Object.create(null)` return true; } return hasConstructorOf(val, Object) || isUserObject(proto); } /** * * @param {Any} v * @returns {boolean} */ function isObject(v) { return v && _typeof(v) === 'object'; } /** * * @param {string} keyPathComponent * @returns {string} */ function escapeKeyPathComponent(keyPathComponent) { return keyPathComponent.replace(/~/g, '~0').replace(/\./g, '~1'); } /** * * @param {string} keyPathComponent * @returns {string} */ function unescapeKeyPathComponent(keyPathComponent) { return keyPathComponent.replace(/~1/g, '.').replace(/~0/g, '~'); } /** * @param {PlainObject|GenericArray} obj * @param {string} keyPath * @returns {Any} */ function getByKeyPath(obj, keyPath) { if (keyPath === '') { return obj; } var period = keyPath.indexOf('.'); if (period > -1) { var innerObj = obj[unescapeKeyPathComponent(keyPath.slice(0, period))]; return innerObj === undefined ? undefined : getByKeyPath(innerObj, keyPath.slice(period + 1)); } return obj[unescapeKeyPathComponent(keyPath)]; } /** * * @param {PlainObject} obj * @param {string} keyPath * @param {Any} value * @returns {Any} */ function setAtKeyPath(obj, keyPath, value) { if (keyPath === '') { return value; } var period = keyPath.indexOf('.'); if (period > -1) { var innerObj = obj[unescapeKeyPathComponent(keyPath.slice(0, period))]; return setAtKeyPath(innerObj, keyPath.slice(period + 1), value); } obj[unescapeKeyPathComponent(keyPath)] = value; return obj; } /** * * @param {external:JSON} value * @returns {"null"|"array"|"undefined"|"boolean"|"number"|"string"| * "object"|"symbol"} */ function getJSONType(value) { return value === null ? 'null' : Array.isArray(value) ? 'array' : _typeof(value); } var keys = Object.keys, isArray = Array.isArray, hasOwn$1 = {}.hasOwnProperty, internalStateObjPropsToIgnore = ['type', 'replaced', 'iterateIn', 'iterateUnsetNumeric']; /** * Handle plain object revivers first so reference setting can use * revived type (e.g., array instead of object); assumes revived * has same structure or will otherwise break subsequent references. * @param {PlainObjectType} a * @param {PlainObjectType} b * @returns {1|-1|boolean} */ function nestedPathsFirst(a, b) { if (a.keypath === '') { return -1; } var as = a.keypath.match(/\./g) || 0; var bs = b.keypath.match(/\./g) || 0; if (as) { as = as.length; } if (bs) { bs = bs.length; } return as > bs ? -1 : as < bs ? 1 : a.keypath < b.keypath ? -1 : a.keypath > b.keypath; } /** * An instance of this class can be used to call `stringify()` and `parse()`. * Typeson resolves cyclic references by default. Can also be extended to * support custom types using the register() method. * * @class * @param {{cyclic: boolean}} [options] - if cyclic (default true), * cyclic references will be handled gracefully. */ var Typeson = /*#__PURE__*/ function () { function Typeson(options) { _classCallCheck(this, Typeson); this.options = options; // Replacers signature: replace (value). Returns falsy if not // replacing. Otherwise ['Date', value.getTime()] this.plainObjectReplacers = []; this.nonplainObjectReplacers = []; // Revivers: [{type => reviver}, {plain: boolean}]. // Sample: [{'Date': value => new Date(value)}, {plain: false}] this.revivers = {}; /** Types registered via `register()`. */ this.types = {}; } /** * @typedef {null|boolean|number|string|GenericArray|PlainObject} JSON */ /** * @callback JSONReplacer * @param {""|string} key * @param {JSON} value * @returns {number|string|boolean|null|PlainObject|undefined} * @see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The%20replacer%20parameter */ /** * Serialize given object to Typeson. * Initial arguments work identical to those of `JSON.stringify`. * The `replacer` argument has nothing to do with our replacers. * @param {Any} obj * @param {JSONReplacer|string[]} replacer * @param {number|string} space * @param {object} opts * @returns {string|Promise} Promise resolves to a string */ _createClass(Typeson, [{ key: "stringify", value: function stringify(obj, replacer, space, opts) { opts = _objectSpread2({}, this.options, {}, opts, { stringification: true }); var encapsulated = this.encapsulate(obj, null, opts); if (isArray(encapsulated)) { return JSON.stringify(encapsulated[0], replacer, space); } return encapsulated.then(function (res) { return JSON.stringify(res, replacer, space); }); } /** * Also sync but throws on non-sync result. * @param {Any} obj * @param {JSONReplacer|string[]} replacer * @param {number|string} space * @param {object} opts * @returns {string} */ }, { key: "stringifySync", value: function stringifySync(obj, replacer, space, opts) { return this.stringify(obj, replacer, space, _objectSpread2({ throwOnBadSyncType: true }, opts, { sync: true })); } /** * * @param {Any} obj * @param {JSONReplacer|string[]} replacer * @param {number|string} space * @param {object} opts * @returns {Promise} */ }, { key: "stringifyAsync", value: function stringifyAsync(obj, replacer, space, opts) { return this.stringify(obj, replacer, space, _objectSpread2({ throwOnBadSyncType: true }, opts, { sync: false })); } /** * Parse Typeson back into an obejct. * Initial arguments works identical to those of `JSON.parse()`. * @param {string} text * @param {function} reviver This JSON reviver has nothing to do with * our revivers. * @param {object} opts * @returns {external:JSON} */ }, { key: "parse", value: function parse(text, reviver, opts) { opts = _objectSpread2({}, this.options, {}, opts, { parse: true }); return this.revive(JSON.parse(text, reviver), opts); } /** * Also sync but throws on non-sync result. * @param {string} text * @param {function} reviver This JSON reviver has nothing to do with * our revivers. * @param {object} opts * @returns {external:JSON} */ }, { key: "parseSync", value: function parseSync(text, reviver, opts) { return this.parse(text, reviver, _objectSpread2({ throwOnBadSyncType: true }, opts, { sync: true })); } /** * @param {string} text * @param {function} reviver This JSON reviver has nothing to do with * our revivers. * @param {object} opts * @returns {Promise} Resolves to `external:JSON` */ }, { key: "parseAsync", value: function parseAsync(text, reviver, opts) { return this.parse(text, reviver, _objectSpread2({ throwOnBadSyncType: true }, opts, { sync: false })); } /** * * @param {Any} obj * @param {object} stateObj * @param {object} [opts={}] * @returns {string[]|false} */ }, { key: "specialTypeNames", value: function specialTypeNames(obj, stateObj) { var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; opts.returnTypeNames = true; return this.encapsulate(obj, stateObj, opts); } /** * * @param {Any} obj * @param {PlainObject} stateObj * @param {PlainObject} [opts={}] * @returns {Promise|GenericArray|PlainObject|string|false} */ }, { key: "rootTypeName", value: function rootTypeName(obj, stateObj) { var opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; opts.iterateNone = true; return this.encapsulate(obj, stateObj, opts); } /** * Encapsulate a complex object into a plain Object by replacing * registered types with plain objects representing the types data. * * This method is used internally by `Typeson.stringify()`. * @param {Any} obj - Object to encapsulate. * @param {PlainObject} stateObj * @param {PlainObject} opts * @returns {Promise|GenericArray|PlainObject|string|false} */ }, { key: "encapsulate", value: function encapsulate(obj, stateObj, opts) { opts = _objectSpread2({ sync: true }, this.options, {}, opts); var _opts = opts, sync = _opts.sync; var that = this, types = {}, refObjs = [], // For checking cyclic references refKeys = [], // For checking cyclic references promisesDataRoot = []; // Clone the object deeply while at the same time replacing any // special types or cyclic reference: var cyclic = 'cyclic' in opts ? opts.cyclic : true; var _opts2 = opts, encapsulateObserver = _opts2.encapsulateObserver; var ret = _encapsulate('', obj, cyclic, stateObj || {}, promisesDataRoot); /** * * @param {Any} ret * @returns {GenericArray|PlainObject|string|false} */ function finish(ret) { // Add `$types` to result only if we ever bumped into a // special type (or special case where object has own `$types`) var typeNames = Object.values(types); if (opts.iterateNone) { if (typeNames.length) { return typeNames[0]; } return Typeson.getJSONType(ret); } if (typeNames.length) { if (opts.returnTypeNames) { return _toConsumableArray(new Set(typeNames)); } // Special if array (or a primitive) was serialized // because JSON would ignore custom `$types` prop on it if (!ret || !isPlainObject(ret) || // Also need to handle if this is an object with its // own `$types` property (to avoid ambiguity) hasOwn$1.call(ret, '$types')) { ret = { $: ret, $types: { $: types } }; } else { ret.$types = types; } // No special types } else if (isObject(ret) && hasOwn$1.call(ret, '$types')) { ret = { $: ret, $types: true }; } if (opts.returnTypeNames) { return false; } return ret; } /** * * @param {Any} ret * @param {GenericArray} promisesData * @returns {Promise} */ function checkPromises(_x, _x2) { return _checkPromises.apply(this, arguments); } /** * * @param {object} stateObj * @param {object} ownKeysObj * @param {function} cb * @returns {undefined} */ function _checkPromises() { _checkPromises = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee2(ret, promisesData) { var promResults; return regeneratorRuntime.wrap(function _callee2$(_context2) { while (1) { switch (_context2.prev = _context2.next) { case 0: _context2.next = 2; return Promise.all(promisesData.map(function (pd) { return pd[1].p; })); case 2: promResults = _context2.sent; _context2.next = 5; return Promise.all(promResults.map( /*#__PURE__*/ function () { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(promResult) { var newPromisesData, _promisesData$splice, _promisesData$splice2, prData, _prData, keyPath, cyclic, stateObj, parentObj, key, detectedType, encaps, isTypesonPromise, encaps2; return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch (_context.prev = _context.next) { case 0: newPromisesData = []; _promisesData$splice = promisesData.splice(0, 1), _promisesData$splice2 = _slicedToArray(_promisesData$splice, 1), prData = _promisesData$splice2[0]; _prData = _slicedToArray(prData, 7), keyPath = _prData[0], cyclic = _prData[2], stateObj = _prData[3], parentObj = _prData[4], key = _prData[5], detectedType = _prData[6]; encaps = _encapsulate(keyPath, promResult, cyclic, stateObj, newPromisesData, true, detectedType); isTypesonPromise = hasConstructorOf(encaps, TypesonPromise); // Handle case where an embedded custom type itself // returns a `Typeson.Promise` if (!(keyPath && isTypesonPromise)) { _context.next = 11; break; } _context.next = 8; return encaps.p; case 8: encaps2 = _context.sent; parentObj[key] = encaps2; return _context.abrupt("return", checkPromises(ret, newPromisesData)); case 11: if (keyPath) { parentObj[key] = encaps; } else if (isTypesonPromise) { ret = encaps.p; } else { // If this is itself a `Typeson.Promise` (because the // original value supplied was a `Promise` or // because the supplied custom type value resolved // to one), returning it below will be fine since // a `Promise` is expected anyways given current // config (and if not a `Promise`, it will be ready // as the resolve value) ret = encaps; } return _context.abrupt("return", checkPromises(ret, newPromisesData)); case 13: case "end": return _context.stop(); } } }, _callee); })); return function (_x3) { return _ref.apply(this, arguments); }; }())); case 5: return _context2.abrupt("return", ret); case 6: case "end": return _context2.stop(); } } }, _callee2); })); return _checkPromises.apply(this, arguments); } function _adaptBuiltinStateObjectProperties(stateObj, ownKeysObj, cb) { Object.assign(stateObj, ownKeysObj); var vals = internalStateObjPropsToIgnore.map(function (prop) { var tmp = stateObj[prop]; delete stateObj[prop]; return tmp; }); // eslint-disable-next-line callback-return cb(); internalStateObjPropsToIgnore.forEach(function (prop, i) { stateObj[prop] = vals[i]; }); } /** * * @param {string} keypath * @param {Any} value * @param {boolean} cyclic * @param {PlainObject} stateObj * @param {boolean} promisesData * @param {boolean} resolvingTypesonPromise * @param {string} detectedType * @returns {Any} */ function _encapsulate(keypath, value, cyclic, stateObj, promisesData, resolvingTypesonPromise, detectedType) { var ret; var observerData = {}; var $typeof = _typeof(value); var runObserver = encapsulateObserver ? function (obj) { var type = detectedType || stateObj.type || Typeson.getJSONType(value); encapsulateObserver(Object.assign(obj || observerData, { keypath: keypath, value: value, cyclic: cyclic, stateObj: stateObj, promisesData: promisesData, resolvingTypesonPromise: resolvingTypesonPromise, awaitingTypesonPromise: hasConstructorOf(value, TypesonPromise) }, { type: type })); } : null; if (['string', 'boolean', 'number', 'undefined'].includes($typeof)) { if (value === undefined || $typeof === 'number' && (isNaN(value) || value === -Infinity || value === Infinity)) { if (stateObj.replaced) { ret = value; } else { ret = replace(keypath, value, stateObj, promisesData, false, resolvingTypesonPromise, runObserver); } if (ret !== value) { observerData = { replaced: ret }; } } else { ret = value; } if (runObserver) { runObserver(); } return ret; } if (value === null) { if (runObserver) { runObserver(); } return value; } if (cyclic && !stateObj.iterateIn && !stateObj.iterateUnsetNumeric && value && _typeof(value) === 'object') { // Options set to detect cyclic references and be able // to rewrite them. var refIndex = refObjs.indexOf(value); if (refIndex < 0) { if (cyclic === true) { refObjs.push(value); refKeys.push(keypath); } } else { types[keypath] = '#'; if (runObserver) { runObserver({ cyclicKeypath: refKeys[refIndex] }); } return '#' + refKeys[refIndex]; } } var isPlainObj = isPlainObject(value); var isArr = isArray(value); var replaced = // Running replace will cause infinite loop as will test // positive again (isPlainObj || isArr) && (!that.plainObjectReplacers.length || stateObj.replaced) || stateObj.iterateIn ? // Optimization: if plain object and no plain-object // replacers, don't try finding a replacer value : replace(keypath, value, stateObj, promisesData, isPlainObj || isArr, null, runObserver); var clone; if (replaced !== value) { ret = replaced; observerData = { replaced: replaced }; } else { // eslint-disable-next-line no-lonely-if if (keypath === '' && hasConstructorOf(value, TypesonPromise)) { promisesData.push([keypath, value, cyclic, stateObj, undefined, undefined, stateObj.type]); ret = value; } else if (isArr && stateObj.iterateIn !== 'object' || stateObj.iterateIn === 'array') { clone = new Array(value.length); observerData = { clone: clone }; } else if (!['function', 'symbol'].includes(_typeof(value)) && !('toJSON' in value) && !hasConstructorOf(value, TypesonPromise) && !hasConstructorOf(value, Promise) && !hasConstructorOf(value, ArrayBuffer) || isPlainObj || stateObj.iterateIn === 'object') { clone = {}; if (stateObj.addLength) { clone.length = value.length; } observerData = { clone: clone }; } else { ret = value; // Only clone vanilla objects and arrays } } if (runObserver) { runObserver(); } if (opts.iterateNone) { return clone || ret; } if (!clone) { return ret; } // Iterate object or array if (stateObj.iterateIn) { var _loop = function _loop(key) { var ownKeysObj = { ownKeys: hasOwn$1.call(value, key) }; _adaptBuiltinStateObjectProperties(stateObj, ownKeysObj, function () { var kp = keypath + (keypath ? '.' : '') + escapeKeyPathComponent(key); var val = _encapsulate(kp, value[key], Boolean(cyclic), stateObj, promisesData, resolvingTypesonPromise); if (hasConstructorOf(val, TypesonPromise)) { promisesData.push([kp, val, Boolean(cyclic), stateObj, clone, key, stateObj.type]); } else if (val !== undefined) { clone[key] = val; } }); }; // eslint-disable-next-line guard-for-in for (var key in value) { _loop(key); } if (runObserver) { runObserver({ endIterateIn: true, end: true }); } } else { // Note: Non-indexes on arrays won't survive stringify so // somewhat wasteful for arrays, but so too is iterating // all numeric indexes on sparse arrays when not wanted // or filtering own keys for positive integers keys(value).forEach(function (key) { var kp = keypath + (keypath ? '.' : '') + escapeKeyPathComponent(key); var ownKeysObj = { ownKeys: true }; _adaptBuiltinStateObjectProperties(stateObj, ownKeysObj, function () { var val = _encapsulate(kp, value[key], Boolean(cyclic), stateObj, promisesData, resolvingTypesonPromise); if (hasConstructorOf(val, TypesonPromise)) { promisesData.push([kp, val, Boolean(cyclic), stateObj, clone, key, stateObj.type]); } else if (val !== undefined) { clone[key] = val; } }); }); if (runObserver) { runObserver({ endIterateOwn: true, end: true }); } } // Iterate array for non-own numeric properties (we can't // replace the prior loop though as it iterates non-integer // keys) if (stateObj.iterateUnsetNumeric) { var vl = value.length; var _loop2 = function _loop2(i) { if (!(i in value)) { // No need to escape numeric var kp = keypath + (keypath ? '.' : '') + i; var ownKeysObj = { ownKeys: false }; _adaptBuiltinStateObjectProperties(stateObj, ownKeysObj, function () { var val = _encapsulate(kp, undefined, Boolean(cyclic), stateObj, promisesData, resolvingTypesonPromise); if (hasConstructorOf(val, TypesonPromise)) { promisesData.push([kp, val, Boolean(cyclic), stateObj, clone, i, stateObj.type]); } else if (val !== undefined) { clone[i] = val; } }); } }; for (var i = 0; i < vl; i++) { _loop2(i); } if (runObserver) { runObserver({ endIterateUnsetNumeric: true, end: true }); } } return clone; } /** * * @param {string} keypath * @param {Any} value * @param {PlainObject} stateObj * @param {GenericArray} promisesData * @param {boolean} plainObject * @param {boolean} resolvingTypesonPromise * @param {function} [runObserver] * @returns {*} */ function replace(keypath, value, stateObj, promisesData, plainObject, resolvingTypesonPromise, runObserver) { // Encapsulate registered types var replacers = plainObject ? that.plainObjectReplacers : that.nonplainObjectReplacers; var i = replacers.length; while (i--) { var replacer = replacers[i]; if (replacer.test(value, stateObj)) { var type = replacer.type; if (that.revivers[type]) { // Record the type only if a corresponding reviver // exists. This is to support specs where only // replacement is done. // For example, ensuring deep cloning of the object, // or replacing a type to its equivalent without // the need to revive it. var existing = types[keypath]; // type can comprise an array of types (see test // "should support intermediate types") types[keypath] = existing ? [type].concat(existing) : type; } Object.assign(stateObj, { type: type, replaced: true }); if ((sync || !replacer.replaceAsync) && !replacer.replace) { if (runObserver) { runObserver({ typeDetected: true }); } return _encapsulate(keypath, value, cyclic && 'readonly', stateObj, promisesData, resolvingTypesonPromise, type); } if (runObserver) { runObserver({ replacing: true }); } // Now, also traverse the result in case it contains its // own types to replace var replaceMethod = sync || !replacer.replaceAsync ? 'replace' : 'replaceAsync'; return _encapsulate(keypath, replacer[replaceMethod](value, stateObj), cyclic && 'readonly', stateObj, promisesData, resolvingTypesonPromise, type); } } return value; } return promisesDataRoot.length ? sync && opts.throwOnBadSyncType ? function () { throw new TypeError('Sync method requested but async result obtained'); }() : Promise.resolve(checkPromises(ret, promisesDataRoot)).then(finish) : !sync && opts.throwOnBadSyncType ? function () { throw new TypeError('Async method requested but sync result obtained'); }() // If this is a synchronous request for stringification, yet // a promise is the result, we don't want to resolve leading // to an async result, so we return an array to avoid // ambiguity : opts.stringification && sync ? [finish(ret)] : sync ? finish(ret) : Promise.resolve(finish(ret)); } /** * Also sync but throws on non-sync result. * @param {*} obj * @param {object} stateObj * @param {object} opts * @returns {*} */ }, { key: "encapsulateSync", value: function encapsulateSync(obj, stateObj, opts) { return this.encapsulate(obj, stateObj, _objectSpread2({ throwOnBadSyncType: true }, opts, { sync: true })); } /** * @param {*} obj * @param {object} stateObj * @param {object} opts * @returns {*} */ }, { key: "encapsulateAsync", value: function encapsulateAsync(obj, stateObj, opts) { return this.encapsulate(obj, stateObj, _objectSpread2({ throwOnBadSyncType: true }, opts, { sync: false })); } /** * Revive an encapsulated object. * This method is used internally by `Typeson.parse()`. * @param {object} obj - Object to revive. If it has `$types` member, the * properties that are listed there will be replaced with its true type * instead of just plain objects. * @param {object} opts * @throws TypeError If mismatch between sync/async type and result * @returns {Promise|*} If async, returns a Promise that resolves to `*` */ }, { key: "revive", value: function revive(obj, opts) { var types = obj && obj.$types; // No type info added. Revival not needed. if (!types) { return obj; } // Object happened to have own `$types` property but with // no actual types, so we unescape and return that object if (types === true) { return obj.$; } opts = _objectSpread2({ sync: true }, this.options, {}, opts); var _opts3 = opts, sync = _opts3.sync; var keyPathResolutions = []; var stateObj = {}; var ignore$Types = true; // Special when root object is not a trivial Object, it will // be encapsulated in `$`. It will also be encapsulated in // `$` if it has its own `$` property to avoid ambiguity if (types.$ && isPlainObject(types.$)) { obj = obj.$; types = types.$; ignore$Types = false; } var that = this; /** * @callback RevivalReducer * @param {Any} value * @param {string} type * @returns {Any} */ /** * * @param {string} type * @param {Any} val * @returns {[type]} [description] */ function executeReviver(type, val) { var _ref2 = that.revivers[type] || [], _ref3 = _slicedToArray(_ref2, 1), reviver = _ref3[0]; if (!reviver) { throw new Error('Unregistered type: ' + type); } // Only `sync` expected here, as problematic async would // be missing both `reviver` and `reviverAsync`, and // encapsulation shouldn't have added types, so // should have made an early exit if (sync && !('revive' in reviver)) { // Just return value as is return val; } return reviver[sync && reviver.revive ? 'revive' : !sync && reviver.reviveAsync ? 'reviveAsync' : 'revive'](val, stateObj); } /** * * @returns {void|TypesonPromise} */ function revivePlainObjects() { // const references = []; // const reviveTypes = []; var plainObjectTypes = []; Object.entries(types).forEach(function (_ref4) { var _ref5 = _slicedToArray(_ref4, 2), keypath = _ref5[0], type = _ref5[1]; if (type === '#') { /* references.push({ keypath, reference: getByKeyPath(obj, keypath) }); */ return; } [].concat(type).forEach(function (type) { var _ref6 = that.revivers[type] || [null, {}], _ref7 = _slicedToArray(_ref6, 2), plain = _ref7[1].plain; if (!plain) { // reviveTypes.push({keypath, type}); return; } plainObjectTypes.push({ keypath: keypath, type: type }); delete types[keypath]; // Avoid repeating }); }); if (!plainObjectTypes.length) { return undefined; } // console.log(plainObjectTypes.sort(nestedPathsFirst)); /** * @typedef {PlainObject} PlainObjectType * @property {string} keypath * @property {string} type */ return plainObjectTypes.sort(nestedPathsFirst).reduce(function reducer(possibleTypesonPromise, _ref8) { var keypath = _ref8.keypath, type = _ref8.type; if (isThenable(possibleTypesonPromise)) { return possibleTypesonPromise.then(function (val) { return reducer(val, { keypath: keypath, type: type }); }); } // console.log('obj', JSON.stringify(keypath), obj); var val = getByKeyPath(obj, keypath); val = executeReviver(type, val); if (hasConstructorOf(val, TypesonPromise)) { return val.then(function (v) { var newVal = setAtKeyPath(obj, keypath, v); if (newVal === v) { obj = newVal; } return undefined; }); } var newVal = setAtKeyPath(obj, keypath, val); if (newVal === val) { obj = newVal; } return undefined; }, undefined // This argument must be explicit ); // references.forEach(({keypath, reference}) => {}); // reviveTypes.sort(nestedPathsFirst).forEach(() => {}); } var revivalPromises = []; /** * * @param {string} keypath * @param {Any} value * @param {?(Array|object)} target * @param {Array|object} [clone] * @param {string} [key] * @returns {Any} */ function _revive(keypath, value, target, clone, key) { if (ignore$Types && keypath === '$types') { return undefined; } var type = types[keypath]; var isArr = isArray(value); if (isArr || isPlainObject(value)) { var _clone = isArr ? new Array(value.length) : {}; // Iterate object or array keys(value).forEach(function (k) { var val = _revive(keypath + (keypath ? '.' : '') + escapeKeyPathComponent(k), value[k], target || _clone, _clone, k); var set = function set(v) { if (hasConstructorOf(v, Undefined)) { _clone[k] = undefined; } else if (v !== undefined) { _clone[k] = v; } return v; }; if (hasConstructorOf(val, TypesonPromise)) { revivalPromises.push(val.then(function (ret) { return set(ret); })); } else { set(val); } }); value = _clone; // Try to resolve cyclic reference as soon as available while (keyPathResolutions.length) { var _keyPathResolutions$ = _slicedToArray(keyPathResolutions[0], 4), _target = _keyPathResolutions$[0], keyPath = _keyPathResolutions$[1], _clone2 = _keyPathResolutions$[2], k = _keyPathResolutions$[3]; var val = getByKeyPath(_target, keyPath); // Typeson.Undefined not expected here as not cyclic or // `undefined` if (val !== undefined) { _clone2[k] = val; } else { break; } keyPathResolutions.splice(0, 1); } } if (!type) { return value; } if (type === '#') { var _ret = getByKeyPath(target, value.slice(1)); if (_ret === undefined) { // Cyclic reference not yet available keyPathResolutions.push([target, value.slice(1), clone, key]); } return _ret; } // `type` can be an array here return [].concat(type).reduce(function reducer(val, typ) { if (hasConstructorOf(val, TypesonPromise)) { return val.then(function (v) { // TypesonPromise here too return reducer(v, typ); }); } return executeReviver(typ, val); }, value); } /** * * @param {Any} retrn * @returns {undefined|Any} */ function checkUndefined(retrn) { return hasConstructorOf(retrn, Undefined) ? undefined : retrn; } var possibleTypesonPromise = revivePlainObjects(); var ret; if (hasConstructorOf(possibleTypesonPromise, TypesonPromise)) { ret = possibleTypesonPromise.then(function () { return obj; }); } else { ret = _revive('', obj, null); if (revivalPromises.length) { // Ensure children resolved ret = TypesonPromise.resolve(ret).then(function (r) { return TypesonPromise.all([// May be a TypesonPromise or not r].concat(revivalPromises)); }).then(function (_ref9) { var _ref10 = _slicedToArray(_ref9, 1), r = _ref10[0]; return r; }); } } return isThenable(ret) ? sync && opts.throwOnBadSyncType ? function () { throw new TypeError('Sync method requested but async result obtained'); }() : hasConstructorOf(ret, TypesonPromise) ? ret.p.then(checkUndefined) : ret : !sync && opts.throwOnBadSyncType ? function () { throw new TypeError('Async method requested but sync result obtained'); }() : sync ? checkUndefined(ret) : Promise.resolve(checkUndefined(ret)); } /** * Also sync but throws on non-sync result. * @param {Any} obj * @param {object} opts * @returns {Any} */ }, { key: "reviveSync", value: function reviveSync(obj, opts) { return this.revive(obj, _objectSpread2({ throwOnBadSyncType: true }, opts, { sync: true })); } /** * @param {Any} obj * @param {object} opts * @returns {Promise} Resolves to `*` */ }, { key: "reviveAsync", value: function reviveAsync(obj, opts) { return this.revive(obj, _objectSpread2({ throwOnBadSyncType: true }, opts, { sync: false })); } /** * Register types. * For examples on how to use this method, see * {@link https://github.com/dfahlander/typeson-registry/tree/master/types}. * @param {object.[]} typeSpecSets - Types and * their functions [test, encapsulate, revive]; * @param {object} opts * @returns {Typeson} */ }, { key: "register", value: function register(typeSpecSets, opts) { opts = opts || {}; [].concat(typeSpecSets).forEach(function R(typeSpec) { var _this = this; // Allow arrays of arrays of arrays... if (isArray(typeSpec)) { return typeSpec.map(function (typSpec) { return R.call(_this, typSpec); }); } typeSpec && keys(typeSpec).forEach(function (typeId) { if (typeId === '#') { throw new TypeError('# cannot be used as a type name as it is reserved ' + 'for cyclic objects'); } else if (Typeson.JSON_TYPES.includes(typeId)) { throw new TypeError('Plain JSON object types are reserved as type names'); } var spec = typeSpec[typeId]; var replacers = spec && spec.testPlainObjects ? this.plainObjectReplacers : this.nonplainObjectReplacers; var existingReplacer = replacers.filter(function (r) { return r.type === typeId; }); if (existingReplacer.length) { // Remove existing spec and replace with this one. replacers.splice(replacers.indexOf(existingReplacer[0]), 1); delete this.revivers[typeId]; delete this.types[typeId]; } if (typeof spec === 'function') { // Support registering just a class without replacer/reviver var Class = spec; spec = { test: function test(x) { return x && x.constructor === Class; }, replace: function replace(x) { return _objectSpread2({}, x); }, revive: function revive(x) { return Object.assign(Object.create(Class.prototype), x); } }; } else if (isArray(spec)) { var _spec = spec, _spec2 = _slicedToArray(_spec, 3), test = _spec2[0], replace = _spec2[1], revive = _spec2[2]; spec = { test: test, replace: replace, revive: revive }; } if (!spec || !spec.test) { return; } var replacerObj = { type: typeId, test: spec.test.bind(spec) }; if (spec.replace) { replacerObj.replace = spec.replace.bind(spec); } if (spec.replaceAsync) { replacerObj.replaceAsync = spec.replaceAsync.bind(spec); } var start = typeof opts.fallback === 'number' ? opts.fallback : opts.fallback ? 0 : Infinity; if (spec.testPlainObjects) { this.plainObjectReplacers.splice(start, 0, replacerObj); } else { this.nonplainObjectReplacers.splice(start, 0, replacerObj); } // Todo: We might consider a testAsync type if (spec.revive || spec.reviveAsync) { var reviverObj = {}; if (spec.revive) { reviverObj.revive = spec.revive.bind(spec); } if (spec.reviveAsync) { reviverObj.reviveAsync = spec.reviveAsync.bind(spec); } this.revivers[typeId] = [reviverObj, { plain: spec.testPlainObjects }]; } // Record to be retrieved via public types property. this.types[typeId] = spec; }, this); }, this); return this; } }]); return Typeson; }(); /** * We keep this function minimized so if using two instances of this * library, where one is minimized and one is not, it will still work * with `hasConstructorOf`. * @class */ var Undefined = function Undefined() { _classCallCheck(this, Undefined); }; // eslint-disable-line space-before-blocks Undefined.__typeson__type__ = 'TypesonUndefined'; // The following provide classes meant to avoid clashes with other values // To insist `undefined` should be added Typeson.Undefined = Undefined; // To support async encapsulation/stringification Typeson.Promise = TypesonPromise; // Some fundamental type-checking utilities Typeson.isThenable = isThenable; Typeson.toStringTag = toStringTag; Typeson.hasConstructorOf = hasConstructorOf; Typeson.isObject = isObject; Typeson.isPlainObject = isPlainObject; Typeson.isUserObject = isUserObject; Typeson.escapeKeyPathComponent = escapeKeyPathComponent; Typeson.unescapeKeyPathComponent = unescapeKeyPathComponent; Typeson.getByKeyPath = getByKeyPath; Typeson.getJSONType = getJSONType; Typeson.JSON_TYPES = ['null', 'boolean', 'number', 'string', 'array', 'object']; return Typeson; }))); }); var structuredCloning = createCommonjsModule(function (module, exports) { !function(e,t){module.exports=t();}(commonjsGlobal,(function(){function _typeof$1(e){return (_typeof$1="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(e)}function _classCallCheck$1(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _defineProperties$1(e,t){for(var r=0;re.length)&&(t=e.length);for(var r=0,n=new Array(t);re.length)&&(t=e.length);for(var r=0,n=new Array(t);r-1){var n=e[unescapeKeyPathComponent(t.slice(0,r))];return void 0===n?void 0:getByKeyPath(n,t.slice(r+1))}return e[unescapeKeyPathComponent(t)]}function setAtKeyPath(e,t,r){if(""===t)return r;var n=t.indexOf(".");return n>-1?setAtKeyPath(e[unescapeKeyPathComponent(t.slice(0,n))],t.slice(n+1),r):(e[unescapeKeyPathComponent(t)]=r,e)}function _await(e,t,r){return r?t?t(e):e:(e&&e.then||(e=Promise.resolve(e)),t?e.then(t):e)}var o=Object.keys,a=Array.isArray,c={}.hasOwnProperty,u=["type","replaced","iterateIn","iterateUnsetNumeric"];function _async(e){return function(){for(var t=[],r=0;rn?-1:rt.keypath}var s=function(){function Typeson(e){_classCallCheck(this,Typeson),this.options=e,this.plainObjectReplacers=[],this.nonplainObjectReplacers=[],this.revivers={},this.types={};}return function _createClass(e,t,r){return t&&_defineProperties(e.prototype,t),r&&_defineProperties(e,r),e}(Typeson,[{key:"stringify",value:function stringify(e,t,r,n){n=_objectSpread2(_objectSpread2(_objectSpread2({},this.options),n),{},{stringification:!0});var i=this.encapsulate(e,null,n);return a(i)?JSON.stringify(i[0],t,r):i.then((function(e){return JSON.stringify(e,t,r)}))}},{key:"stringifySync",value:function stringifySync(e,t,r,n){return this.stringify(e,t,r,_objectSpread2(_objectSpread2({throwOnBadSyncType:!0},n),{},{sync:!0}))}},{key:"stringifyAsync",value:function stringifyAsync(e,t,r,n){return this.stringify(e,t,r,_objectSpread2(_objectSpread2({throwOnBadSyncType:!0},n),{},{sync:!1}))}},{key:"parse",value:function parse(e,t,r){return r=_objectSpread2(_objectSpread2(_objectSpread2({},this.options),r),{},{parse:!0}),this.revive(JSON.parse(e,t),r)}},{key:"parseSync",value:function parseSync(e,t,r){return this.parse(e,t,_objectSpread2(_objectSpread2({throwOnBadSyncType:!0},r),{},{sync:!0}))}},{key:"parseAsync",value:function parseAsync(e,t,r){return this.parse(e,t,_objectSpread2(_objectSpread2({throwOnBadSyncType:!0},r),{},{sync:!1}))}},{key:"specialTypeNames",value:function specialTypeNames(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return r.returnTypeNames=!0,this.encapsulate(e,t,r)}},{key:"rootTypeName",value:function rootTypeName(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return r.iterateNone=!0,this.encapsulate(e,t,r)}},{key:"encapsulate",value:function encapsulate(t,r,n){var i=_async((function(t,r){return _await(Promise.all(r.map((function(e){return e[1].p}))),(function(n){return _await(Promise.all(n.map(_async((function(n){var o=!1,a=[],c=_slicedToArray(r.splice(0,1),1),u=_slicedToArray(c[0],7),s=u[0],f=u[2],l=u[3],p=u[4],y=u[5],v=u[6],b=_encapsulate(s,n,f,l,a,!0,v),d=hasConstructorOf(b,e);return function _invoke(e,t){var r=e();return r&&r.then?r.then(t):t(r)}((function(){if(s&&d)return _await(b.p,(function(e){return p[y]=e,o=!0,i(t,a)}))}),(function(e){return o?e:(s?p[y]=b:t=d?b.p:b,i(t,a))}))})))),(function(){return t}))}))})),s=(n=_objectSpread2(_objectSpread2({sync:!0},this.options),n)).sync,f=this,l={},p=[],y=[],v=[],b=!("cyclic"in n)||n.cyclic,d=n.encapsulateObserver,h=_encapsulate("",t,b,r||{},v);function finish(e){var t=Object.values(l);if(n.iterateNone)return t.length?t[0]:Typeson.getJSONType(e);if(t.length){if(n.returnTypeNames)return _toConsumableArray(new Set(t));e&&isPlainObject(e)&&!c.call(e,"$types")?e.$types=l:e={$:e,$types:{$:l}};}else isObject(e)&&c.call(e,"$types")&&(e={$:e,$types:!0});return !n.returnTypeNames&&e}function _adaptBuiltinStateObjectProperties(e,t,r){Object.assign(e,t);var n=u.map((function(t){var r=e[t];return delete e[t],r}));r(),u.forEach((function(t,r){e[t]=n[r];}));}function _encapsulate(t,r,i,u,s,v,b){var h,g={},m=_typeof(r),O=d?function(n){var o=b||u.type||Typeson.getJSONType(r);d(Object.assign(n||g,{keypath:t,value:r,cyclic:i,stateObj:u,promisesData:s,resolvingTypesonPromise:v,awaitingTypesonPromise:hasConstructorOf(r,e)},{type:o}));}:null;if(["string","boolean","number","undefined"].includes(m))return void 0===r||Number.isNaN(r)||r===Number.NEGATIVE_INFINITY||r===Number.POSITIVE_INFINITY?(h=u.replaced?r:replace(t,r,u,s,!1,v,O))!==r&&(g={replaced:h}):h=r,O&&O(),h;if(null===r)return O&&O(),r;if(i&&!u.iterateIn&&!u.iterateUnsetNumeric&&r&&"object"===_typeof(r)){var _=p.indexOf(r);if(!(_<0))return l[t]="#",O&&O({cyclicKeypath:y[_]}),"#"+y[_];!0===i&&(p.push(r),y.push(t));}var j,S=isPlainObject(r),T=a(r),w=(S||T)&&(!f.plainObjectReplacers.length||u.replaced)||u.iterateIn?r:replace(t,r,u,s,S||T,null,O);if(w!==r?(h=w,g={replaced:w}):""===t&&hasConstructorOf(r,e)?(s.push([t,r,i,u,void 0,void 0,u.type]),h=r):T&&"object"!==u.iterateIn||"array"===u.iterateIn?(j=new Array(r.length),g={clone:j}):(["function","symbol"].includes(_typeof(r))||"toJSON"in r||hasConstructorOf(r,e)||hasConstructorOf(r,Promise)||hasConstructorOf(r,ArrayBuffer))&&!S&&"object"!==u.iterateIn?h=r:(j={},u.addLength&&(j.length=r.length),g={clone:j}),O&&O(),n.iterateNone)return j||h;if(!j)return h;if(u.iterateIn){var A=function _loop(n){var o={ownKeys:c.call(r,n)};_adaptBuiltinStateObjectProperties(u,o,(function(){var o=t+(t?".":"")+escapeKeyPathComponent(n),a=_encapsulate(o,r[n],Boolean(i),u,s,v);hasConstructorOf(a,e)?s.push([o,a,Boolean(i),u,j,n,u.type]):void 0!==a&&(j[n]=a);}));};for(var P in r)A(P);O&&O({endIterateIn:!0,end:!0});}else o(r).forEach((function(n){var o=t+(t?".":"")+escapeKeyPathComponent(n);_adaptBuiltinStateObjectProperties(u,{ownKeys:!0},(function(){var t=_encapsulate(o,r[n],Boolean(i),u,s,v);hasConstructorOf(t,e)?s.push([o,t,Boolean(i),u,j,n,u.type]):void 0!==t&&(j[n]=t);}));})),O&&O({endIterateOwn:!0,end:!0});if(u.iterateUnsetNumeric){for(var I=r.length,C=function _loop2(n){if(!(n in r)){var o=t+(t?".":"")+n;_adaptBuiltinStateObjectProperties(u,{ownKeys:!1},(function(){var t=_encapsulate(o,void 0,Boolean(i),u,s,v);hasConstructorOf(t,e)?s.push([o,t,Boolean(i),u,j,n,u.type]):void 0!==t&&(j[n]=t);}));}},N=0;N>2],o+=O[(3&n[a])<<4|n[a+1]>>4],o+=O[(15&n[a+1])<<2|n[a+2]>>6],o+=O[63&n[a+2]];return i%3==2?o=o.slice(0,-1)+"=":i%3==1&&(o=o.slice(0,-2)+"=="),o},T=function decode(e){var t,r,n,i,o=e.length,a=.75*e.length,c=0;"="===e[e.length-1]&&(a--,"="===e[e.length-2]&&a--);for(var u=new ArrayBuffer(a),s=new Uint8Array(u),f=0;f>4,s[c++]=(15&r)<<4|n>>2,s[c++]=(3&n)<<6|63&i;return u},w={arraybuffer:{test:function test(e){return "ArrayBuffer"===s.toStringTag(e)},replace:function replace(e,t){t.buffers||(t.buffers=[]);var r=t.buffers.indexOf(e);return r>-1?{index:r}:(t.buffers.push(e),S(e))},revive:function revive(e,t){if(t.buffers||(t.buffers=[]),"object"===_typeof$1(e))return t.buffers[e.index];var r=T(e);return t.buffers.push(r),r}}},A="undefined"==typeof self?commonjsGlobal:self,P={};["Int8Array","Uint8Array","Uint8ClampedArray","Int16Array","Uint16Array","Int32Array","Uint32Array","Float32Array","Float64Array"].forEach((function(e){var t=e,r=A[t];r&&(P[e.toLowerCase()]={test:function test(e){return s.toStringTag(e)===t},replace:function replace(e,t){var r=e.buffer,n=e.byteOffset,i=e.length;t.buffers||(t.buffers=[]);var o=t.buffers.indexOf(r);return o>-1?{index:o,byteOffset:n,length:i}:(t.buffers.push(r),{encoded:S(r),byteOffset:n,length:i})},revive:function revive(e,t){t.buffers||(t.buffers=[]);var n,i=e.byteOffset,o=e.length,a=e.encoded,c=e.index;return "index"in e?n=t.buffers[c]:(n=T(a),t.buffers.push(n)),new r(n,i,o)}});}));var I={dataview:{test:function test(e){return "DataView"===s.toStringTag(e)},replace:function replace(e,t){var r=e.buffer,n=e.byteOffset,i=e.byteLength;t.buffers||(t.buffers=[]);var o=t.buffers.indexOf(r);return o>-1?{index:o,byteOffset:n,byteLength:i}:(t.buffers.push(r),{encoded:S(r),byteOffset:n,byteLength:i})},revive:function revive(e,t){t.buffers||(t.buffers=[]);var r,n=e.byteOffset,i=e.byteLength,o=e.encoded,a=e.index;return "index"in e?r=t.buffers[a]:(r=T(o),t.buffers.push(r)),new DataView(r,n,i)}}},C={IntlCollator:{test:function test(e){return s.hasConstructorOf(e,Intl.Collator)},replace:function replace(e){return e.resolvedOptions()},revive:function revive(e){return new Intl.Collator(e.locale,e)}},IntlDateTimeFormat:{test:function test(e){return s.hasConstructorOf(e,Intl.DateTimeFormat)},replace:function replace(e){return e.resolvedOptions()},revive:function revive(e){return new Intl.DateTimeFormat(e.locale,e)}},IntlNumberFormat:{test:function test(e){return s.hasConstructorOf(e,Intl.NumberFormat)},replace:function replace(e){return e.resolvedOptions()},revive:function revive(e){return new Intl.NumberFormat(e.locale,e)}}};function string2arraybuffer(e){for(var t=new Uint8Array(e.length),r=0;r> 2]; base64 += chars[(bytes[_i] & 3) << 4 | bytes[_i + 1] >> 4]; base64 += chars[(bytes[_i + 1] & 15) << 2 | bytes[_i + 2] >> 6]; base64 += chars[bytes[_i + 2] & 63]; } if (len % 3 === 2) { base64 = base64.slice(0, -1) + '='; } else if (len % 3 === 1) { base64 = base64.slice(0, -2) + '=='; } return base64; }; /** * @param {string} base64 * @returns {ArrayBuffer} */ var decode = function decode(base64) { var len = base64.length; var bufferLength = base64.length * 0.75; var p = 0; var encoded1, encoded2, encoded3, encoded4; if (base64[base64.length - 1] === '=') { bufferLength--; if (base64[base64.length - 2] === '=') { bufferLength--; } } var arraybuffer = new ArrayBuffer(bufferLength), bytes = new Uint8Array(arraybuffer); for (var _i2 = 0; _i2 < len; _i2 += 4) { encoded1 = lookup[base64.codePointAt(_i2)]; encoded2 = lookup[base64.codePointAt(_i2 + 1)]; encoded3 = lookup[base64.codePointAt(_i2 + 2)]; encoded4 = lookup[base64.codePointAt(_i2 + 3)]; bytes[p++] = encoded1 << 2 | encoded2 >> 4; bytes[p++] = (encoded2 & 15) << 4 | encoded3 >> 2; bytes[p++] = (encoded3 & 3) << 6 | encoded4 & 63; } return arraybuffer; }; /* eslint-env browser, node */ var _global = typeof self === 'undefined' ? global : self; var exportObj = {}; [ 'Int8Array', 'Uint8Array', 'Uint8ClampedArray', 'Int16Array', 'Uint16Array', 'Int32Array', 'Uint32Array', 'Float32Array', 'Float64Array' ].forEach(function (typeName) { var arrType = typeName; var TypedArray = _global[arrType]; if (TypedArray) { exportObj[typeName.toLowerCase() + "2"] = { test: function (x) { return typeson.toStringTag(x) === arrType; }, replace: function (_a) { var buffer = _a.buffer, byteOffset = _a.byteOffset, length = _a.length; return { buffer: buffer, byteOffset: byteOffset, length: length }; }, revive: function (b64Obj) { var buffer = b64Obj.buffer, byteOffset = b64Obj.byteOffset, length = b64Obj.length; return new TypedArray(buffer, byteOffset, length); } }; } }); var arrayBuffer = { arraybuffer: { test: function (x) { return typeson.toStringTag(x) === 'ArrayBuffer'; }, replace: function (b) { return encode(b, 0, b.byteLength); }, revive: function (b64) { var buffer = decode(b64); return buffer; } } }; // See also typed-arrays! var TSON = new typeson().register(structuredCloning); var readBlobsSynchronously = 'FileReaderSync' in self; // true in workers only. var blobsToAwait = []; var blobsToAwaitPos = 0; // Need to patch encapsulateAsync as it does not work as of typeson 5.8.2 // Also, current version of typespn-registry-1.0.0-alpha.21 does not // encapsulate/revive Blobs correctly (fails one of the unit tests in // this library (test 'export-format')) TSON.register([ arrayBuffer, exportObj, { blob2: { test: function (x) { return typeson.toStringTag(x) === 'Blob'; }, replace: function (b) { if (b.isClosed) { // On MDN, but not in https://w3c.github.io/FileAPI/#dfn-Blob throw new Error('The Blob is closed'); } if (readBlobsSynchronously) { var data = readBlobSync(b, 'binary'); var base64 = encode(data, 0, data.byteLength); return { type: b.type, data: base64 }; } else { blobsToAwait.push(b); // This will also make TSON.mustFinalize() return true. var result = { type: b.type, data: { start: blobsToAwaitPos, end: blobsToAwaitPos + b.size } }; blobsToAwaitPos += b.size; return result; } }, finalize: function (b, ba) { b.data = encode(ba, 0, ba.byteLength); }, revive: function (_a) { var type = _a.type, data = _a.data; return new Blob([decode(data)], { type: type }); } } } ]); TSON.mustFinalize = function () { return blobsToAwait.length > 0; }; TSON.finalize = function (items) { return __awaiter(void 0, void 0, void 0, function () { var allChunks, _i, items_1, item, types, arrayType, keyPath, typeName, typeSpec, b; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, readBlobAsync(new Blob(blobsToAwait), 'binary')]; case 1: allChunks = _a.sent(); if (items) { for (_i = 0, items_1 = items; _i < items_1.length; _i++) { item = items_1[_i]; // Manually go through all "blob" types in the result // and lookup the data slice they point at. if (item.$types) { types = item.$types; arrayType = types.$; if (arrayType) types = types.$; for (keyPath in types) { typeName = types[keyPath]; typeSpec = TSON.types[typeName]; if (typeSpec && typeSpec.finalize) { b = Dexie__default["default"].getByKeyPath(item, arrayType ? "$." + keyPath : keyPath); typeSpec.finalize(b, allChunks.slice(b.start, b.end)); } } } } } // Free up memory blobsToAwait = []; return [2 /*return*/]; } }); }); }; var DEFAULT_ROWS_PER_CHUNK = 2000; function exportDB(db, options) { return __awaiter(this, void 0, void 0, function () { function exportAll() { return __awaiter(this, void 0, void 0, function () { var tablesRowCounts, emptyExportJson, posEndDataArray, firstJsonSlice, filter, _loop_1, _i, tables_1, tableName; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, Promise.all(db.tables.map(function (table) { return table.count(); }))]; case 1: tablesRowCounts = _a.sent(); tablesRowCounts.forEach(function (rowCount, i) { return tables[i].rowCount = rowCount; }); progress.totalRows = tablesRowCounts.reduce(function (p, c) { return p + c; }); emptyExportJson = JSON.stringify(emptyExport, undefined, prettyJson ? 2 : undefined); posEndDataArray = emptyExportJson.lastIndexOf(']'); firstJsonSlice = emptyExportJson.substring(0, posEndDataArray); slices.push(firstJsonSlice); filter = options.filter; _loop_1 = function (tableName) { var table, primKey, inbound, LIMIT, emptyTableExport, emptyTableExportJson, posEndRowsArray, lastKey, lastNumRows, mayHaveMoreRows, _loop_2, state_1; return __generator(this, function (_b) { switch (_b.label) { case 0: table = db.table(tableName); primKey = table.schema.primKey; inbound = !!primKey.keyPath; LIMIT = options.numRowsPerChunk || DEFAULT_ROWS_PER_CHUNK; emptyTableExport = inbound ? { tableName: table.name, inbound: true, rows: [] } : { tableName: table.name, inbound: false, rows: [] }; emptyTableExportJson = JSON.stringify(emptyTableExport, undefined, prettyJson ? 2 : undefined); if (prettyJson) { // Increase indentation according to this: // { // ... // data: [ // ... // data: [ // 123456<---- here // ] // ] // } emptyTableExportJson = emptyTableExportJson.split('\n').join('\n '); } posEndRowsArray = emptyTableExportJson.lastIndexOf(']'); slices.push(emptyTableExportJson.substring(0, posEndRowsArray)); lastKey = null; lastNumRows = 0; mayHaveMoreRows = true; _loop_2 = function () { var chunkedCollection, values, filteredValues, tsonValues, json, keys, keyvals, tsonTuples, json; return __generator(this, function (_c) { switch (_c.label) { case 0: if (progressCallback) { // Keep ongoing transaction private Dexie__default["default"].ignoreTransaction(function () { return progressCallback(progress); }); } chunkedCollection = lastKey == null ? table.limit(LIMIT) : table.where(':id').above(lastKey).limit(LIMIT); return [4 /*yield*/, chunkedCollection.toArray()]; case 1: values = _c.sent(); if (values.length === 0) return [2 /*return*/, "break"]; if (lastKey != null && lastNumRows > 0) { // Not initial chunk. Must add a comma: slices.push(","); if (prettyJson) { slices.push("\n "); } } mayHaveMoreRows = values.length === LIMIT; if (!inbound) return [3 /*break*/, 4]; filteredValues = filter ? values.filter(function (value) { return filter(tableName, value); }) : values; tsonValues = filteredValues.map(function (value) { return TSON.encapsulate(value); }); if (!TSON.mustFinalize()) return [3 /*break*/, 3]; return [4 /*yield*/, Dexie__default["default"].waitFor(TSON.finalize(tsonValues))]; case 2: _c.sent(); _c.label = 3; case 3: json = JSON.stringify(tsonValues, undefined, prettyJson ? 2 : undefined); if (prettyJson) json = json.split('\n').join('\n '); // By generating a blob here, we give web platform the opportunity to store the contents // on disk and release RAM. slices.push(new Blob([json.substring(1, json.length - 1)])); lastNumRows = filteredValues.length; lastKey = values.length > 0 ? Dexie__default["default"].getByKeyPath(values[values.length - 1], primKey.keyPath) : null; return [3 /*break*/, 8]; case 4: return [4 /*yield*/, chunkedCollection.primaryKeys()]; case 5: keys = _c.sent(); keyvals = keys.map(function (key, i) { return [key, values[i]]; }); if (filter) keyvals = keyvals.filter(function (_a) { var key = _a[0], value = _a[1]; return filter(tableName, value, key); }); tsonTuples = keyvals.map(function (tuple) { return TSON.encapsulate(tuple); }); if (!TSON.mustFinalize()) return [3 /*break*/, 7]; return [4 /*yield*/, Dexie__default["default"].waitFor(TSON.finalize(tsonTuples))]; case 6: _c.sent(); _c.label = 7; case 7: json = JSON.stringify(tsonTuples, undefined, prettyJson ? 2 : undefined); if (prettyJson) json = json.split('\n').join('\n '); // By generating a blob here, we give web platform the opportunity to store the contents // on disk and release RAM. slices.push(new Blob([json.substring(1, json.length - 1)])); lastNumRows = keyvals.length; lastKey = keys.length > 0 ? keys[keys.length - 1] : null; _c.label = 8; case 8: progress.completedRows += values.length; return [2 /*return*/]; } }); }; _b.label = 1; case 1: if (!mayHaveMoreRows) return [3 /*break*/, 3]; return [5 /*yield**/, _loop_2()]; case 2: state_1 = _b.sent(); if (state_1 === "break") return [3 /*break*/, 3]; return [3 /*break*/, 1]; case 3: slices.push(emptyTableExportJson.substr(posEndRowsArray)); // "]}" progress.completedTables += 1; if (progress.completedTables < progress.totalTables) { slices.push(","); } return [2 /*return*/]; } }); }; _i = 0, tables_1 = tables; _a.label = 2; case 2: if (!(_i < tables_1.length)) return [3 /*break*/, 5]; tableName = tables_1[_i].name; return [5 /*yield**/, _loop_1(tableName)]; case 3: _a.sent(); _a.label = 4; case 4: _i++; return [3 /*break*/, 2]; case 5: slices.push(emptyExportJson.substr(posEndDataArray)); progress.done = true; if (progressCallback) { // Keep ongoing transaction private Dexie__default["default"].ignoreTransaction(function () { return progressCallback(progress); }); } return [2 /*return*/]; } }); }); } var slices, tables, prettyJson, emptyExport, progressCallback, progress; return __generator(this, function (_a) { switch (_a.label) { case 0: options = options || {}; slices = []; tables = db.tables.map(function (table) { return ({ name: table.name, schema: getSchemaString(table), rowCount: 0 }); }); prettyJson = options.prettyJson; emptyExport = { formatName: "dexie", formatVersion: 1, data: { databaseName: db.name, databaseVersion: db.verno, tables: tables, data: [] } }; progressCallback = options.progressCallback; progress = { done: false, completedRows: 0, completedTables: 0, totalRows: NaN, totalTables: db.tables.length }; _a.label = 1; case 1: _a.trys.push([1, , 6, 7]); if (!options.noTransaction) return [3 /*break*/, 3]; return [4 /*yield*/, exportAll()]; case 2: _a.sent(); return [3 /*break*/, 5]; case 3: return [4 /*yield*/, db.transaction('r', db.tables, exportAll)]; case 4: _a.sent(); _a.label = 5; case 5: return [3 /*break*/, 7]; case 6: TSON.finalize(); // Free up mem if error has occurred return [7 /*endfinally*/]; case 7: return [2 /*return*/, new Blob(slices, { type: "text/json" })]; } }); }); } var VERSION = 1; var fakeStream = {Stream: function(){}}; var clarinet_1 = createCommonjsModule(function (module, exports) { (function (clarinet) { // non node-js needs to set clarinet debug on root var env =(typeof process === 'object' && process.env) ? process.env : self; clarinet.parser = function (opt) { return new CParser(opt);}; clarinet.CParser = CParser; clarinet.CStream = CStream; clarinet.createStream = createStream; clarinet.MAX_BUFFER_LENGTH = 10 * 1024 * 1024; clarinet.DEBUG = (env.CDEBUG==='debug'); clarinet.INFO = (env.CDEBUG==='debug' || env.CDEBUG==='info'); clarinet.EVENTS = [ "value" , "string" , "key" , "openobject" , "closeobject" , "openarray" , "closearray" , "error" , "end" , "ready" ]; var buffers = { textNode: undefined, numberNode: "" } , streamWraps = clarinet.EVENTS.filter(function (ev) { return ev !== "error" && ev !== "end"; }) , S = 0 , Stream ; clarinet.STATE = { BEGIN : S++ , VALUE : S++ // general stuff , OPEN_OBJECT : S++ // { , CLOSE_OBJECT : S++ // } , OPEN_ARRAY : S++ // [ , CLOSE_ARRAY : S++ // ] , TEXT_ESCAPE : S++ // \ stuff , STRING : S++ // "" , BACKSLASH : S++ , END : S++ // No more stack , OPEN_KEY : S++ // , "a" , CLOSE_KEY : S++ // : , TRUE : S++ // r , TRUE2 : S++ // u , TRUE3 : S++ // e , FALSE : S++ // a , FALSE2 : S++ // l , FALSE3 : S++ // s , FALSE4 : S++ // e , NULL : S++ // u , NULL2 : S++ // l , NULL3 : S++ // l , NUMBER_DECIMAL_POINT : S++ // . , NUMBER_DIGIT : S++ // [0-9] }; for (var s_ in clarinet.STATE) clarinet.STATE[clarinet.STATE[s_]] = s_; // switcharoo S = clarinet.STATE; const Char = { tab : 0x09, // \t lineFeed : 0x0A, // \n carriageReturn : 0x0D, // \r space : 0x20, // " " doubleQuote : 0x22, // " plus : 0x2B, // + comma : 0x2C, // , minus : 0x2D, // - period : 0x2E, // . _0 : 0x30, // 0 _9 : 0x39, // 9 colon : 0x3A, // : E : 0x45, // E openBracket : 0x5B, // [ backslash : 0x5C, // \ closeBracket : 0x5D, // ] a : 0x61, // a b : 0x62, // b e : 0x65, // e f : 0x66, // f l : 0x6C, // l n : 0x6E, // n r : 0x72, // r s : 0x73, // s t : 0x74, // t u : 0x75, // u openBrace : 0x7B, // { closeBrace : 0x7D, // } }; if (!Object.create) { Object.create = function (o) { function f () { this["__proto__"] = o; } f.prototype = o; return new f; }; } if (!Object.getPrototypeOf) { Object.getPrototypeOf = function (o) { return o["__proto__"]; }; } if (!Object.keys) { Object.keys = function (o) { var a = []; for (var i in o) if (o.hasOwnProperty(i)) a.push(i); return a; }; } function checkBufferLength (parser) { var maxAllowed = Math.max(clarinet.MAX_BUFFER_LENGTH, 10) , maxActual = 0 ; for (var buffer in buffers) { var len = parser[buffer] === undefined ? 0 : parser[buffer].length; if (len > maxAllowed) { switch (buffer) { case "text": closeText(parser); break; default: error(parser, "Max buffer length exceeded: "+ buffer); } } maxActual = Math.max(maxActual, len); } parser.bufferCheckPosition = (clarinet.MAX_BUFFER_LENGTH - maxActual) + parser.position; } function clearBuffers (parser) { for (var buffer in buffers) { parser[buffer] = buffers[buffer]; } } var stringTokenPattern = /[\\"\n]/g; function CParser (opt) { if (!(this instanceof CParser)) return new CParser (opt); var parser = this; clearBuffers(parser); parser.bufferCheckPosition = clarinet.MAX_BUFFER_LENGTH; parser.q = parser.c = parser.p = ""; parser.opt = opt || {}; parser.closed = parser.closedRoot = parser.sawRoot = false; parser.tag = parser.error = null; parser.state = S.BEGIN; parser.stack = new Array(); // mostly just for error reporting parser.position = parser.column = 0; parser.line = 1; parser.slashed = false; parser.unicodeI = 0; parser.unicodeS = null; parser.depth = 0; emit(parser, "onready"); } CParser.prototype = { end : function () { end(this); } , write : write , resume : function () { this.error = null; return this; } , close : function () { return this.write(null); } }; try { Stream = fakeStream.Stream; } catch (ex) { Stream = function () {}; } function createStream (opt) { return new CStream(opt); } function CStream (opt) { if (!(this instanceof CStream)) return new CStream(opt); this._parser = new CParser(opt); this.writable = true; this.readable = true; //var Buffer = this.Buffer || function Buffer () {}; // if we don't have Buffers, fake it so we can do `var instanceof Buffer` and not throw an error this.bytes_remaining = 0; // number of bytes remaining in multi byte utf8 char to read after split boundary this.bytes_in_sequence = 0; // bytes in multi byte utf8 char to read this.temp_buffs = { "2": new Buffer(2), "3": new Buffer(3), "4": new Buffer(4) }; // for rebuilding chars split before boundary is reached this.string = ''; var me = this; Stream.apply(me); this._parser.onend = function () { me.emit("end"); }; this._parser.onerror = function (er) { me.emit("error", er); me._parser.error = null; }; streamWraps.forEach(function (ev) { Object.defineProperty(me, "on" + ev, { get : function () { return me._parser["on" + ev]; } , set : function (h) { if (!h) { me.removeAllListeners(ev); me._parser["on"+ev] = h; return h; } me.on(ev, h); } , enumerable : true , configurable : false }); }); } CStream.prototype = Object.create(Stream.prototype, { constructor: { value: CStream } }); CStream.prototype.write = function (data) { data = new Buffer(data); for (var i = 0; i < data.length; i++) { var n = data[i]; // check for carry over of a multi byte char split between data chunks // & fill temp buffer it with start of this data chunk up to the boundary limit set in the last iteration if (this.bytes_remaining > 0) { for (var j = 0; j < this.bytes_remaining; j++) { this.temp_buffs[this.bytes_in_sequence][this.bytes_in_sequence - this.bytes_remaining + j] = data[j]; } this.string = this.temp_buffs[this.bytes_in_sequence].toString(); this.bytes_in_sequence = this.bytes_remaining = 0; // move iterator forward by number of byte read during sequencing i = i + j - 1; // pass data to parser and move forward to parse rest of data this._parser.write(this.string); this.emit("data", this.string); continue; } // if no remainder bytes carried over, parse multi byte (>=128) chars one at a time if (this.bytes_remaining === 0 && n >= 128) { if ((n >= 194) && (n <= 223)) this.bytes_in_sequence = 2; if ((n >= 224) && (n <= 239)) this.bytes_in_sequence = 3; if ((n >= 240) && (n <= 244)) this.bytes_in_sequence = 4; if ((this.bytes_in_sequence + i) > data.length) { // if bytes needed to complete char fall outside data length, we have a boundary split for (var k = 0; k <= (data.length - 1 - i); k++) { this.temp_buffs[this.bytes_in_sequence][k] = data[i + k]; // fill temp data of correct size with bytes available in this chunk } this.bytes_remaining = (i + this.bytes_in_sequence) - data.length; // immediately return as we need another chunk to sequence the character return true; } else { this.string = data.slice(i, (i + this.bytes_in_sequence)).toString(); i = i + this.bytes_in_sequence - 1; this._parser.write(this.string); this.emit("data", this.string); continue; } } // is there a range of characters that are immediately parsable? for (var p = i; p < data.length; p++) { if (data[p] >= 128) break; } this.string = data.slice(i, p).toString(); this._parser.write(this.string); this.emit("data", this.string); i = p - 1; // handle any remaining characters using multibyte logic continue; } }; CStream.prototype.end = function (chunk) { if (chunk && chunk.length) this._parser.write(chunk.toString()); this._parser.end(); return true; }; CStream.prototype.on = function (ev, handler) { var me = this; if (!me._parser["on"+ev] && streamWraps.indexOf(ev) !== -1) { me._parser["on"+ev] = function () { var args = arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments); args.splice(0, 0, ev); me.emit.apply(me, args); }; } return Stream.prototype.on.call(me, ev, handler); }; CStream.prototype.destroy = function () { clearBuffers(this._parser); this.emit("close"); }; function emit(parser, event, data) { if(clarinet.INFO) console.log('-- emit', event, data); if (parser[event]) parser[event](data); } function emitNode(parser, event, data) { closeValue(parser); emit(parser, event, data); } function closeValue(parser, event) { parser.textNode = textopts(parser.opt, parser.textNode); if (parser.textNode !== undefined) { emit(parser, (event ? event : "onvalue"), parser.textNode); } parser.textNode = undefined; } function closeNumber(parser) { if (parser.numberNode) emit(parser, "onvalue", parseFloat(parser.numberNode)); parser.numberNode = ""; } function textopts (opt, text) { if (text === undefined) { return text; } if (opt.trim) text = text.trim(); if (opt.normalize) text = text.replace(/\s+/g, " "); return text; } function error (parser, er) { closeValue(parser); er += "\nLine: "+parser.line+ "\nColumn: "+parser.column+ "\nChar: "+parser.c; er = new Error(er); parser.error = er; emit(parser, "onerror", er); return parser; } function end(parser) { if (parser.state !== S.VALUE || parser.depth !== 0) error(parser, "Unexpected end"); closeValue(parser); parser.c = ""; parser.closed = true; emit(parser, "onend"); CParser.call(parser, parser.opt); return parser; } function isWhitespace(c) { return c === Char.carriageReturn || c === Char.lineFeed || c === Char.space || c === Char.tab; } function write (chunk) { var parser = this; if (this.error) throw this.error; if (parser.closed) return error(parser, "Cannot write after close. Assign an onready handler."); if (chunk === null) return end(parser); var i = 0, c = chunk.charCodeAt(0), p = parser.p; if (clarinet.DEBUG) console.log('write -> [' + chunk + ']'); while (c) { p = c; parser.c = c = chunk.charCodeAt(i++); // if chunk doesnt have next, like streaming char by char // this way we need to check if previous is really previous // if not we need to reset to what the parser says is the previous // from buffer if(p !== c ) parser.p = p; else p = parser.p; if(!c) break; if (clarinet.DEBUG) console.log(i,c,clarinet.STATE[parser.state]); parser.position ++; if (c === Char.lineFeed) { parser.line ++; parser.column = 0; } else parser.column ++; switch (parser.state) { case S.BEGIN: if (c === Char.openBrace) parser.state = S.OPEN_OBJECT; else if (c === Char.openBracket) parser.state = S.OPEN_ARRAY; else if (!isWhitespace(c)) error(parser, "Non-whitespace before {[."); continue; case S.OPEN_KEY: case S.OPEN_OBJECT: if (isWhitespace(c)) continue; if(parser.state === S.OPEN_KEY) parser.stack.push(S.CLOSE_KEY); else { if(c === Char.closeBrace) { emit(parser, 'onopenobject'); this.depth++; emit(parser, 'oncloseobject'); this.depth--; parser.state = parser.stack.pop() || S.VALUE; continue; } else parser.stack.push(S.CLOSE_OBJECT); } if(c === Char.doubleQuote) parser.state = S.STRING; else error(parser, "Malformed object key should start with \""); continue; case S.CLOSE_KEY: case S.CLOSE_OBJECT: if (isWhitespace(c)) continue; (parser.state === S.CLOSE_KEY) ? 'key' : 'object'; if(c === Char.colon) { if(parser.state === S.CLOSE_OBJECT) { parser.stack.push(S.CLOSE_OBJECT); closeValue(parser, 'onopenobject'); this.depth++; } else closeValue(parser, 'onkey'); parser.state = S.VALUE; } else if (c === Char.closeBrace) { emitNode(parser, 'oncloseobject'); this.depth--; parser.state = parser.stack.pop() || S.VALUE; } else if(c === Char.comma) { if(parser.state === S.CLOSE_OBJECT) parser.stack.push(S.CLOSE_OBJECT); closeValue(parser); parser.state = S.OPEN_KEY; } else error(parser, 'Bad object'); continue; case S.OPEN_ARRAY: // after an array there always a value case S.VALUE: if (isWhitespace(c)) continue; if(parser.state===S.OPEN_ARRAY) { emit(parser, 'onopenarray'); this.depth++; parser.state = S.VALUE; if(c === Char.closeBracket) { emit(parser, 'onclosearray'); this.depth--; parser.state = parser.stack.pop() || S.VALUE; continue; } else { parser.stack.push(S.CLOSE_ARRAY); } } if(c === Char.doubleQuote) parser.state = S.STRING; else if(c === Char.openBrace) parser.state = S.OPEN_OBJECT; else if(c === Char.openBracket) parser.state = S.OPEN_ARRAY; else if(c === Char.t) parser.state = S.TRUE; else if(c === Char.f) parser.state = S.FALSE; else if(c === Char.n) parser.state = S.NULL; else if(c === Char.minus) { // keep and continue parser.numberNode += "-"; } else if(Char._0 <= c && c <= Char._9) { parser.numberNode += String.fromCharCode(c); parser.state = S.NUMBER_DIGIT; } else error(parser, "Bad value"); continue; case S.CLOSE_ARRAY: if(c === Char.comma) { parser.stack.push(S.CLOSE_ARRAY); closeValue(parser, 'onvalue'); parser.state = S.VALUE; } else if (c === Char.closeBracket) { emitNode(parser, 'onclosearray'); this.depth--; parser.state = parser.stack.pop() || S.VALUE; } else if (isWhitespace(c)) continue; else error(parser, 'Bad array'); continue; case S.STRING: if (parser.textNode === undefined) { parser.textNode = ""; } // thanks thejh, this is an about 50% performance improvement. var starti = i-1 , slashed = parser.slashed , unicodeI = parser.unicodeI ; STRING_BIGLOOP: while (true) { if (clarinet.DEBUG) console.log(i,c,clarinet.STATE[parser.state] ,slashed); // zero means "no unicode active". 1-4 mean "parse some more". end after 4. while (unicodeI > 0) { parser.unicodeS += String.fromCharCode(c); c = chunk.charCodeAt(i++); parser.position++; if (unicodeI === 4) { // TODO this might be slow? well, probably not used too often anyway parser.textNode += String.fromCharCode(parseInt(parser.unicodeS, 16)); unicodeI = 0; starti = i-1; } else { unicodeI++; } // we can just break here: no stuff we skipped that still has to be sliced out or so if (!c) break STRING_BIGLOOP; } if (c === Char.doubleQuote && !slashed) { parser.state = parser.stack.pop() || S.VALUE; parser.textNode += chunk.substring(starti, i-1); parser.position += i - 1 - starti; break; } if (c === Char.backslash && !slashed) { slashed = true; parser.textNode += chunk.substring(starti, i-1); parser.position += i - 1 - starti; c = chunk.charCodeAt(i++); parser.position++; if (!c) break; } if (slashed) { slashed = false; if (c === Char.n) { parser.textNode += '\n'; } else if (c === Char.r) { parser.textNode += '\r'; } else if (c === Char.t) { parser.textNode += '\t'; } else if (c === Char.f) { parser.textNode += '\f'; } else if (c === Char.b) { parser.textNode += '\b'; } else if (c === Char.u) { // \uxxxx. meh! unicodeI = 1; parser.unicodeS = ''; } else { parser.textNode += String.fromCharCode(c); } c = chunk.charCodeAt(i++); parser.position++; starti = i-1; if (!c) break; else continue; } stringTokenPattern.lastIndex = i; var reResult = stringTokenPattern.exec(chunk); if (reResult === null) { i = chunk.length+1; parser.textNode += chunk.substring(starti, i-1); parser.position += i - 1 - starti; break; } i = reResult.index+1; c = chunk.charCodeAt(reResult.index); if (!c) { parser.textNode += chunk.substring(starti, i-1); parser.position += i - 1 - starti; break; } } parser.slashed = slashed; parser.unicodeI = unicodeI; continue; case S.TRUE: if (c === Char.r) parser.state = S.TRUE2; else error(parser, 'Invalid true started with t'+ c); continue; case S.TRUE2: if (c === Char.u) parser.state = S.TRUE3; else error(parser, 'Invalid true started with tr'+ c); continue; case S.TRUE3: if(c === Char.e) { emit(parser, "onvalue", true); parser.state = parser.stack.pop() || S.VALUE; } else error(parser, 'Invalid true started with tru'+ c); continue; case S.FALSE: if (c === Char.a) parser.state = S.FALSE2; else error(parser, 'Invalid false started with f'+ c); continue; case S.FALSE2: if (c === Char.l) parser.state = S.FALSE3; else error(parser, 'Invalid false started with fa'+ c); continue; case S.FALSE3: if (c === Char.s) parser.state = S.FALSE4; else error(parser, 'Invalid false started with fal'+ c); continue; case S.FALSE4: if (c === Char.e) { emit(parser, "onvalue", false); parser.state = parser.stack.pop() || S.VALUE; } else error(parser, 'Invalid false started with fals'+ c); continue; case S.NULL: if (c === Char.u) parser.state = S.NULL2; else error(parser, 'Invalid null started with n'+ c); continue; case S.NULL2: if (c === Char.l) parser.state = S.NULL3; else error(parser, 'Invalid null started with nu'+ c); continue; case S.NULL3: if(c === Char.l) { emit(parser, "onvalue", null); parser.state = parser.stack.pop() || S.VALUE; } else error(parser, 'Invalid null started with nul'+ c); continue; case S.NUMBER_DECIMAL_POINT: if(c === Char.period) { parser.numberNode += "."; parser.state = S.NUMBER_DIGIT; } else error(parser, 'Leading zero not followed by .'); continue; case S.NUMBER_DIGIT: if(Char._0 <= c && c <= Char._9) parser.numberNode += String.fromCharCode(c); else if (c === Char.period) { if(parser.numberNode.indexOf('.')!==-1) error(parser, 'Invalid number has two dots'); parser.numberNode += "."; } else if (c === Char.e || c === Char.E) { if(parser.numberNode.indexOf('e')!==-1 || parser.numberNode.indexOf('E')!==-1 ) error(parser, 'Invalid number has two exponential'); parser.numberNode += "e"; } else if (c === Char.plus || c === Char.minus) { if(!(p === Char.e || p === Char.E)) error(parser, 'Invalid symbol in number'); parser.numberNode += String.fromCharCode(c); } else { closeNumber(parser); i--; // go back one parser.state = parser.stack.pop() || S.VALUE; } continue; default: error(parser, "Unknown state: " + parser.state); } } if (parser.position >= parser.bufferCheckPosition) checkBufferLength(parser); return parser; } })(exports); }); function JsonStream(blob) { var pos = 0; var parser = JsonParser(true); var rv = { pullAsync: function (numBytes) { return __awaiter(this, void 0, void 0, function () { var slize, jsonPart, result; return __generator(this, function (_a) { switch (_a.label) { case 0: slize = blob.slice(pos, pos + numBytes); pos += numBytes; return [4 /*yield*/, readBlobAsync(slize, 'text')]; case 1: jsonPart = _a.sent(); result = parser.write(jsonPart); rv.result = result || {}; return [2 /*return*/, result]; } }); }); }, pullSync: function (numBytes) { var slize = blob.slice(pos, pos + numBytes); pos += numBytes; var jsonPart = readBlobSync(slize, 'text'); var result = parser.write(jsonPart); rv.result = result || {}; return result; }, done: function () { return parser.done(); }, eof: function () { return pos >= blob.size; }, result: {} }; return rv; } function JsonParser(allowPartial) { var parser = clarinet_1.parser(); var level = 0; var result; var stack = []; var obj; var key; var done = false; var array = false; parser.onopenobject = function (newKey) { var newObj = {}; newObj.incomplete = true; if (!result) result = newObj; if (obj) { stack.push([key, obj, array]); if (allowPartial) { if (array) { obj.push(newObj); } else { obj[key] = newObj; } } } obj = newObj; key = newKey; array = false; ++level; }; parser.onkey = function (newKey) { return key = newKey; }; parser.onvalue = function (value) { return array ? obj.push(value) : obj[key] = value; }; parser.oncloseobject = function () { var _a; delete obj.incomplete; key = null; if (--level === 0) { done = true; } else { var completedObj = obj; _a = stack.pop(), key = _a[0], obj = _a[1], array = _a[2]; if (!allowPartial) { if (array) { obj.push(completedObj); } else { obj[key] = completedObj; } } } }; parser.onopenarray = function () { var newObj = []; newObj.incomplete = true; if (!result) result = newObj; if (obj) { stack.push([key, obj, array]); if (allowPartial) { if (array) { obj.push(newObj); } else { obj[key] = newObj; } } } obj = newObj; array = true; key = null; ++level; }; parser.onclosearray = function () { var _a; delete obj.incomplete; key = null; if (--level === 0) { done = true; } else { var completedObj = obj; _a = stack.pop(), key = _a[0], obj = _a[1], array = _a[2]; if (!allowPartial) { if (array) { obj.push(completedObj); } else { obj[key] = completedObj; } } } }; return { write: function (jsonPart) { parser.write(jsonPart); return result; }, done: function () { return done; } }; } var DEFAULT_KILOBYTES_PER_CHUNK = 1024; function importDB(exportedData, options) { return __awaiter(this, void 0, void 0, function () { var CHUNK_SIZE, stream, dbExport, db; return __generator(this, function (_a) { switch (_a.label) { case 0: options = options || {}; // All booleans defaults to false. CHUNK_SIZE = options.chunkSizeBytes || (DEFAULT_KILOBYTES_PER_CHUNK * 1024); return [4 /*yield*/, loadUntilWeGotEnoughData(exportedData, CHUNK_SIZE)]; case 1: stream = _a.sent(); dbExport = stream.result.data; db = new Dexie__default["default"](dbExport.databaseName); db.version(dbExport.databaseVersion).stores(extractDbSchema(dbExport)); return [4 /*yield*/, importInto(db, stream, options)]; case 2: _a.sent(); return [2 /*return*/, db]; } }); }); } function peakImportFile(exportedData) { return __awaiter(this, void 0, void 0, function () { var stream; return __generator(this, function (_a) { switch (_a.label) { case 0: stream = JsonStream(exportedData); _a.label = 1; case 1: if (!!stream.eof()) return [3 /*break*/, 3]; return [4 /*yield*/, stream.pullAsync(5 * 1024)]; case 2: _a.sent(); // 5 k is normally enough for the headers. If not, it will just do another go. if (stream.result.data && stream.result.data.data) { // @ts-ignore - TS won't allow us to delete a required property - but we are going to cast it. delete stream.result.data.data; // Don't return half-baked data array. return [3 /*break*/, 3]; } return [3 /*break*/, 1]; case 3: return [2 /*return*/, stream.result]; } }); }); } function importInto(db, exportedData, options) { return __awaiter(this, void 0, void 0, function () { function importAll() { return __awaiter(this, void 0, void 0, function () { var _loop_1, _i, _a, tableExport, state_1; return __generator(this, function (_b) { switch (_b.label) { case 0: _loop_1 = function (tableExport) { var tableName, table, tableSchemaStr, sourceRows, rows, i, obj, filter, filteredRows, _c, keys, values; return __generator(this, function (_d) { switch (_d.label) { case 0: if (!tableExport.rows) return [2 /*return*/, "break"]; // Need to pull more! if (!tableExport.rows.incomplete && tableExport.rows.length === 0) return [2 /*return*/, "continue"]; if (progressCallback) { // Keep ongoing transaction private Dexie__default["default"].ignoreTransaction(function () { return progressCallback(progress); }); } tableName = tableExport.tableName; table = db.table(tableName); tableSchemaStr = dbExport.tables.filter(function (t) { return t.name === tableName; })[0].schema; if (!table) { if (!options.acceptMissingTables) throw new Error("Exported table ".concat(tableExport.tableName, " is missing in installed database")); else return [2 /*return*/, "continue"]; } if (!options.acceptChangedPrimaryKey && tableSchemaStr.split(',')[0] != table.schema.primKey.src) { throw new Error("Primary key differs for table ".concat(tableExport.tableName, ". ")); } sourceRows = tableExport.rows; rows = []; for (i = 0; i < sourceRows.length; i++) { obj = sourceRows[i]; if (!obj.incomplete) { rows.push(TSON.revive(obj)); } else { break; } } filter = options.filter; filteredRows = filter ? tableExport.inbound ? rows.filter(function (value) { return filter(tableName, value); }) : rows.filter(function (_a) { var key = _a[0], value = _a[1]; return filter(tableName, value, key); }) : rows; _c = tableExport.inbound ? [undefined, filteredRows] : [filteredRows.map(function (row) { return row[0]; }), rows.map(function (row) { return row[1]; })], keys = _c[0], values = _c[1]; if (!options.overwriteValues) return [3 /*break*/, 2]; return [4 /*yield*/, table.bulkPut(values, keys)]; case 1: _d.sent(); return [3 /*break*/, 4]; case 2: return [4 /*yield*/, table.bulkAdd(values, keys)]; case 3: _d.sent(); _d.label = 4; case 4: progress.completedRows += rows.length; if (!rows.incomplete) { progress.completedTables += 1; } sourceRows.splice(0, rows.length); // Free up RAM, keep existing array instance. return [2 /*return*/]; } }); }; _i = 0, _a = dbExport.data; _b.label = 1; case 1: if (!(_i < _a.length)) return [3 /*break*/, 4]; tableExport = _a[_i]; return [5 /*yield**/, _loop_1(tableExport)]; case 2: state_1 = _b.sent(); if (state_1 === "break") return [3 /*break*/, 4]; _b.label = 3; case 3: _i++; return [3 /*break*/, 1]; case 4: // Avoid unnescessary loops in "for (const tableExport of dbExport.data)" while (dbExport.data.length > 0 && dbExport.data[0].rows && !dbExport.data[0].rows.incomplete) { // We've already imported all rows from the first table. Delete its occurrence dbExport.data.splice(0, 1); } if (!(!jsonStream.done() && !jsonStream.eof())) return [3 /*break*/, 8]; if (!readBlobsSynchronously) return [3 /*break*/, 5]; // If we can pull from blob synchronically, we don't have to // keep transaction alive using Dexie.waitFor(). // This will only be possible in workers. jsonStream.pullSync(CHUNK_SIZE); return [3 /*break*/, 7]; case 5: return [4 /*yield*/, Dexie__default["default"].waitFor(jsonStream.pullAsync(CHUNK_SIZE))]; case 6: _b.sent(); _b.label = 7; case 7: return [3 /*break*/, 9]; case 8: return [3 /*break*/, 10]; case 9: return [3 /*break*/, 0]; case 10: return [2 /*return*/]; } }); }); } var CHUNK_SIZE, jsonStream, dbExportFile, readBlobsSynchronously, dbExport, progressCallback, progress, _i, _a, table; return __generator(this, function (_b) { switch (_b.label) { case 0: options = options || {}; // All booleans defaults to false. CHUNK_SIZE = options.chunkSizeBytes || (DEFAULT_KILOBYTES_PER_CHUNK * 1024); return [4 /*yield*/, loadUntilWeGotEnoughData(exportedData, CHUNK_SIZE)]; case 1: jsonStream = _b.sent(); dbExportFile = jsonStream.result; readBlobsSynchronously = 'FileReaderSync' in self; dbExport = dbExportFile.data; if (!options.acceptNameDiff && db.name !== dbExport.databaseName) throw new Error("Name differs. Current database name is ".concat(db.name, " but export is ").concat(dbExport.databaseName)); if (!options.acceptVersionDiff && db.verno !== dbExport.databaseVersion) { // Possible feature: Call upgraders in some isolated way if this happens... ? throw new Error("Database version differs. Current database is in version ".concat(db.verno, " but export is ").concat(dbExport.databaseVersion)); } progressCallback = options.progressCallback; progress = { done: false, completedRows: 0, completedTables: 0, totalRows: dbExport.tables.reduce(function (p, c) { return p + c.rowCount; }, 0), totalTables: dbExport.tables.length }; if (progressCallback) { // Keep ongoing transaction private Dexie__default["default"].ignoreTransaction(function () { return progressCallback(progress); }); } if (!options.clearTablesBeforeImport) return [3 /*break*/, 5]; _i = 0, _a = db.tables; _b.label = 2; case 2: if (!(_i < _a.length)) return [3 /*break*/, 5]; table = _a[_i]; return [4 /*yield*/, table.clear()]; case 3: _b.sent(); _b.label = 4; case 4: _i++; return [3 /*break*/, 2]; case 5: if (!options.noTransaction) return [3 /*break*/, 7]; return [4 /*yield*/, importAll()]; case 6: _b.sent(); return [3 /*break*/, 9]; case 7: return [4 /*yield*/, db.transaction('rw', db.tables, importAll)]; case 8: _b.sent(); _b.label = 9; case 9: progress.done = true; if (progressCallback) { // Keep ongoing transaction private Dexie__default["default"].ignoreTransaction(function () { return progressCallback(progress); }); } return [2 /*return*/]; } }); }); } function loadUntilWeGotEnoughData(exportedData, CHUNK_SIZE) { return __awaiter(this, void 0, void 0, function () { var stream, dbExportFile; return __generator(this, function (_a) { switch (_a.label) { case 0: stream = ('slice' in exportedData ? JsonStream(exportedData) : exportedData); _a.label = 1; case 1: if (!!stream.eof()) return [3 /*break*/, 3]; return [4 /*yield*/, stream.pullAsync(CHUNK_SIZE)]; case 2: _a.sent(); if (stream.result.data && stream.result.data.data) return [3 /*break*/, 3]; return [3 /*break*/, 1]; case 3: dbExportFile = stream.result; if (!dbExportFile || dbExportFile.formatName != "dexie") throw new Error("Given file is not a dexie export"); if (dbExportFile.formatVersion > VERSION) { throw new Error("Format version ".concat(dbExportFile.formatVersion, " not supported")); } if (!dbExportFile.data) { throw new Error("No data in export file"); } if (!dbExportFile.data.databaseName) { throw new Error("Missing databaseName in export file"); } if (!dbExportFile.data.databaseVersion) { throw new Error("Missing databaseVersion in export file"); } if (!dbExportFile.data.tables) { throw new Error("Missing tables in export file"); } return [2 /*return*/, stream]; } }); }); } // // Extend Dexie interface (runtime wise) // Dexie__default["default"].prototype.export = function (options) { return exportDB(this, options); }; Dexie__default["default"].prototype.import = function (blob, options) { return importInto(this, blob, options); }; Dexie__default["default"].import = function (blob, options) { return importDB(blob, options); }; var dexieExportImport = (function () { throw new Error("This addon extends Dexie.prototype globally and does not have be included in Dexie constructor's addons options."); }); exports["default"] = dexieExportImport; exports.exportDB = exportDB; exports.importDB = importDB; exports.importInto = importInto; exports.peakImportFile = peakImportFile; Object.defineProperty(exports, '__esModule', { value: true }); })); //# sourceMappingURL=dexie-export-import.js.map