'use strict'; var Y = require('yjs'); function _interopNamespace(e) { if (e && e.__esModule) return e; var n = Object.create(null); if (e) { Object.keys(e).forEach(function (k) { if (k !== 'default') { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); } n['default'] = e; return Object.freeze(n); } var Y__namespace = /*#__PURE__*/_interopNamespace(Y); /*! ***************************************************************************** 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); }; var ChangeType; (function (ChangeType) { ChangeType["NONE"] = "none"; ChangeType["INSERT"] = "insert"; ChangeType["UPDATE"] = "update"; ChangeType["DELETE"] = "delete"; ChangeType["PENDING"] = "pending"; })(ChangeType || (ChangeType = {})); var isDiffable = function (v) { return isArray(v) || isString(v) || v instanceof Object; }; var isArray = function (d) { return d instanceof Array; }; var isString = function (d) { return typeof d === "string"; }; var isRecord = function (d) { return !isArray(d) && !isString(d); }; var getChanges = function (a, b) { if (isString(a) && isString(b)) return getStringChanges(a, b); else if (isArray(a) && isArray(b)) return getArrayChanges(a, b); else if (isRecord(a) && isRecord(b)) return getRecordChanges(a, b); else return []; }; var getStringChanges = function (a, b) { if (a === b) return []; else if (a.length === 0) { return b.split("").map(function (character, index) { return [ChangeType.INSERT, index, character]; }); } else if (b.length === 0) { return a.split("").map(function () { return [ChangeType.DELETE, 0, undefined]; }); } else if (!hasCommonSubsequence(a, b)) { var deletes = a.split("").map(function () { return [ChangeType.DELETE, 0, undefined]; }); var inserts = b.split("").map(function (character, index) { return [ChangeType.INSERT, index, character]; }); return deletes.concat(inserts); } else { var m = a.length, n = b.length; var reverse = m >= n; return reverse ? _diffText(b, a, reverse) : _diffText(a, b, reverse); } }; var getArrayChanges = function (a, b) { var changeList = []; var finalIndices = 0; var bOffset = 0; for (var index = 0; index < a.length; index++) { var value = a[index]; var bIndex = index + bOffset; if (b[bIndex] === undefined) changeList.push([ChangeType.DELETE, index, undefined]); else if (isDiffable(value) && isDiffable(b[bIndex])) { var currentDiff = getChanges(value, b[bIndex]); var nextDiff = typeof b[bIndex + 1] === "undefined" ? [] : getChanges(value, b[bIndex + 1]); if (typeof b[bIndex + 1] !== "undefined" && nextDiff.length === 0) { changeList.push([ChangeType.INSERT, index, b[bIndex]]); finalIndices += 2; bOffset++; } else if (currentDiff.length !== 0) { changeList.push([ChangeType.PENDING, index, currentDiff]); finalIndices++; } else finalIndices++; } else if (value !== b[bIndex] && value === b[bIndex + 1]) { changeList.push([ChangeType.INSERT, bIndex, b[bIndex]]); finalIndices += 2; bOffset++; } else if (value !== b[bIndex] && value !== b[bIndex + 1]) { changeList.push([ChangeType.UPDATE, bIndex, b[bIndex]]); finalIndices++; } else finalIndices++; } if (finalIndices < b.length) { b.slice(a.length).forEach(function (value, index) { return changeList.push([ChangeType.INSERT, finalIndices + index, value]); }); } return changeList; }; var getRecordChanges = function (a, b) { var changeList = []; Object.entries(a).forEach(function (_a) { var property = _a[0], value = _a[1]; if (!(property in b) && !(value instanceof Function)) changeList.push([ChangeType.DELETE, property, undefined]); }); Object.entries(b).forEach(function (_a) { var property = _a[0], value = _a[1]; if (!(property in a)) changeList.push([ChangeType.INSERT, property, value]); else if (isDiffable(a[property]) && isDiffable(value)) { var d = getChanges(a[property], value); if (d.length !== 0) changeList.push([ChangeType.PENDING, property, d]); } else if (a[property] !== value) changeList.push([ChangeType.UPDATE, property, value]); }); return changeList; }; var hasCommonSubsequence = function (a, b) { var alphabetOfA = a.split(""); var alphabetOfB = b.split(""); var hasCommonSubsequence = false; for (var _i = 0, alphabetOfA_1 = alphabetOfA; _i < alphabetOfA_1.length; _i++) { var c = alphabetOfA_1[_i]; hasCommonSubsequence = hasCommonSubsequence || alphabetOfB.includes(c); } return hasCommonSubsequence; }; var _diffText = function (a, b, isReversed) { var m = a.length, n = b.length; var offset = m; var delta = n - m; var size = m + n + 1; var frontierPoints = []; for (var i = 0; i < size; i++) frontierPoints[i] = -1; var path = []; for (var i = 0; i < size; i++) path[i] = -1; var pathPositions = []; var snake = function (k, p, q) { var y = Math.max(p, q); var x = y - k; while (x < m && y < n && a[x] === b[y]) { x++; y++; } path[k + offset] = pathPositions.length; pathPositions[pathPositions.length] = { "x": x, "y": y, "k": p > q ? path[k + offset - 1] : path[k + offset + 1], }; return y; }; var p = -1; do { p++; for (var k_1 = -p; k_1 < delta; k_1++) { frontierPoints[k_1 + offset] = snake(k_1, frontierPoints[k_1 + offset - 1] + 1, frontierPoints[k_1 + offset + 1]); } for (var k_2 = delta + p; k_2 > delta; k_2--) { frontierPoints[k_2 + offset] = snake(k_2, frontierPoints[k_2 + offset - 1] + 1, frontierPoints[k_2 + offset + 1]); } frontierPoints[delta + offset] = snake(delta, frontierPoints[delta + offset - 1] + 1, frontierPoints[delta + offset + 1]); } while (frontierPoints[delta + offset] !== n); var k = path[delta + offset]; var editPath = []; while (k !== -1) { editPath[editPath.length] = { "x": pathPositions[k].x, "y": pathPositions[k].y, }; k = pathPositions[k].k; } var changeList = []; var x = 0, y = 0, index = -1; for (var i = editPath.length - 1; i >= 0; i--) { while (x <= editPath[i].x || y <= editPath[i].y) { if (editPath[i].y - editPath[i].x > y - x) { if (isReversed) { changeList[changeList.length] = [ ChangeType.DELETE, index, undefined ]; } else { changeList[changeList.length] = [ ChangeType.INSERT, index, b[y - 1] ]; index++; } y++; } else if (editPath[i].y - editPath[i].x < y - x) { if (isReversed) { changeList[changeList.length] = [ ChangeType.INSERT, index, a[x - 1] ]; index++; } else { changeList[changeList.length] = [ ChangeType.DELETE, index, undefined ]; } x++; } else { x++; y++; index++; } } } return changeList; }; var arrayToYArray = function (array) { var yarray = new Y__namespace.Array(); array.forEach(function (value) { if (value instanceof Array) yarray.push([arrayToYArray(value)]); else if (value instanceof Object) yarray.push([objectToYMap(value)]); else if (typeof value === "string") yarray.push([stringToYText(value)]); else yarray.push([value]); }); return yarray; }; var objectToYMap = function (object) { var ymap = new Y__namespace.Map(); Object.entries(object).forEach(function (_a) { var property = _a[0], value = _a[1]; if (value instanceof Array) ymap.set(property, arrayToYArray(value)); else if (value instanceof Object) ymap.set(property, objectToYMap(value)); else if (typeof value === "string") ymap.set(property, stringToYText(value)); else ymap.set(property, value); }); return ymap; }; var stringToYText = function (string) { return new Y__namespace.Text(string); }; var patchSharedType = function (sharedType, newState) { var changes = getChanges(sharedType.toJSON(), newState); changes.forEach(function (_a) { var type = _a[0], property = _a[1], value = _a[2]; switch (type) { case ChangeType.INSERT: case ChangeType.UPDATE: if ((value instanceof Function) === false) { if (sharedType instanceof Y__namespace.Map) { if (typeof value === "string") sharedType.set(property, stringToYText(value)); else if (value instanceof Array) sharedType.set(property, arrayToYArray(value)); else if (value instanceof Object) sharedType.set(property, objectToYMap(value)); else sharedType.set(property, value); } else if (sharedType instanceof Y__namespace.Array) { var index = property; if (type === ChangeType.UPDATE) sharedType.delete(index); if (typeof value === "string") sharedType.insert(index, [stringToYText(value)]); else if (value instanceof Array) sharedType.insert(index, [arrayToYArray(value)]); else if (value instanceof Object) sharedType.insert(index, [objectToYMap(value)]); else sharedType.insert(index, [value]); } else if (sharedType instanceof Y__namespace.Text) sharedType.insert(property, value); } break; case ChangeType.DELETE: if (sharedType instanceof Y__namespace.Map) sharedType.delete(property); else if (sharedType instanceof Y__namespace.Array) { var index = property; sharedType.delete(sharedType.length <= index ? sharedType.length - 1 : index); } else if (sharedType instanceof Y__namespace.Text) sharedType.delete(property, 1); break; case ChangeType.PENDING: if (sharedType instanceof Y__namespace.Map) { patchSharedType(sharedType.get(property), newState[property]); } else if (sharedType instanceof Y__namespace.Array) { patchSharedType(sharedType.get(property), newState[property]); } break; } }); }; var patchState = function (oldState, newState) { var changes = getChanges(oldState, newState); var applyChanges = function (state, changes) { if (typeof state === "string") return applyChangesToString(state, changes); else if (state instanceof Array) return applyChangesToArray(state, changes); else if (state instanceof Object) return applyChangesToObject(state, changes); }; var applyChangesToArray = function (array, changes) { return changes .sort(function (_a, _b) { var indexA = _a[1]; var indexB = _b[1]; return Math.sign(indexA - indexB); }) .reduce(function (revisedArray, _a) { var type = _a[0], index = _a[1], value = _a[2]; switch (type) { case ChangeType.INSERT: { revisedArray.splice(index, 0, value); return revisedArray; } case ChangeType.UPDATE: { revisedArray[index] = value; return revisedArray; } case ChangeType.PENDING: { revisedArray[index] = applyChanges(array[index], value); return revisedArray; } case ChangeType.DELETE: { revisedArray.splice(index, 1); return revisedArray; } case ChangeType.NONE: default: return revisedArray; } }, array); }; var applyChangesToObject = function (object, changes) { return changes .reduce(function (revisedObject, _a) { var type = _a[0], property = _a[1], value = _a[2]; switch (type) { case ChangeType.INSERT: case ChangeType.UPDATE: { revisedObject[property] = value; return revisedObject; } case ChangeType.PENDING: { revisedObject[property] = applyChanges(object[property], value); return revisedObject; } case ChangeType.DELETE: { delete revisedObject[property]; return revisedObject; } case ChangeType.NONE: default: return revisedObject; } }, object); }; var applyChangesToString = function (string, changes) { return changes .reduce(function (revisedString, _a) { var type = _a[0], index = _a[1], value = _a[2]; switch (type) { case ChangeType.INSERT: { var left = revisedString.slice(0, index); var right = revisedString.slice(index); return left + value + right; } case ChangeType.DELETE: { var left = revisedString.slice(0, index); var right = revisedString.slice(index + 1); return left + right; } default: { return revisedString; } } }, string); }; if (changes.length === 0) return oldState; else return applyChanges(oldState, changes); }; var patchStore = function (store, newState) { var oldState = __assign({}, store.getState()); store.setState(patchState(oldState, newState), true); }; var yjs = function (doc, name, config, transactionOrigin) { var map = doc.getMap(name); return function (set, get, api) { var initialState = config(function (partial, replace) { set(partial, replace); doc.transact(function () { return patchSharedType(map, get()); }, transactionOrigin); }, get, __assign(__assign({}, api), { "setState": function (partial, replace) { api.setState(partial, replace); doc.transact(function () { return patchSharedType(map, api.getState()); }, transactionOrigin); } })); map.observeDeep(function () { patchStore(api, map.toJSON()); }); return initialState; }; }; module.exports = yjs;