UNPKG

dexie-export-import

Version:

Dexie addon that adds export and import capabilities

1,378 lines (1,167 loc) 173 kB
/* ========================================================================== * dexie-export-import.js * ========================================================================== * * Dexie addon for exporting and importing databases to / from Blobs. * * By David Fahlander, david.fahlander@gmail.com, * * ========================================================================== * * Version 4.1.4, Fri Nov 15 2024 * * 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. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; 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<string>} */ }, { 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<Any>} */ 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