back to .js extension
This commit is contained in:
parent
9bd199a6e7
commit
3ddff186c2
@ -5,7 +5,7 @@
|
||||
"dictionaries": ["jsdoc"]
|
||||
},
|
||||
"source": {
|
||||
"include": ["./types", "./utils/UndoManager.mjs", "./utils/Y.mjs", "./provider", "./bindings"],
|
||||
"include": ["./types", "./utils/UndoManager.js", "./utils/Y.js", "./provider", "./bindings"],
|
||||
"includePattern": ".js$"
|
||||
},
|
||||
"plugins": [
|
||||
|
1
bindings/dom.js
Normal file
1
bindings/dom.js
Normal file
@ -0,0 +1 @@
|
||||
export * from './dom/DomBinding.js'
|
@ -1 +0,0 @@
|
||||
export * from './dom/DomBinding.mjs'
|
@ -4,14 +4,14 @@
|
||||
|
||||
/* global MutationObserver, getSelection */
|
||||
|
||||
import { fromRelativePosition } from '../../utils/relativePosition.mjs'
|
||||
import { createMutex } from '../../lib/mutex.mjs'
|
||||
import { createAssociation, removeAssociation } from './util.mjs'
|
||||
import { beforeTransactionSelectionFixer, afterTransactionSelectionFixer, getCurrentRelativeSelection } from './selection.mjs'
|
||||
import { defaultFilter, applyFilterOnType } from './filter.mjs'
|
||||
import { typeObserver } from './typeObserver.mjs'
|
||||
import { domObserver } from './domObserver.mjs'
|
||||
import { YXmlFragment } from '../../types/YXmlElement.mjs' // eslint-disable-line
|
||||
import { fromRelativePosition } from '../../utils/relativePosition.js'
|
||||
import { createMutex } from '../../lib/mutex.js'
|
||||
import { createAssociation, removeAssociation } from './util.js'
|
||||
import { beforeTransactionSelectionFixer, afterTransactionSelectionFixer, getCurrentRelativeSelection } from './selection.js'
|
||||
import { defaultFilter, applyFilterOnType } from './filter.js'
|
||||
import { typeObserver } from './typeObserver.js'
|
||||
import { domObserver } from './domObserver.js'
|
||||
import { YXmlFragment } from '../../types/YXmlElement.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
* @callback DomFilter
|
@ -2,13 +2,13 @@
|
||||
* @module bindings/dom
|
||||
*/
|
||||
|
||||
import { YXmlHook } from '../../types/YXmlHook.mjs'
|
||||
import { YXmlHook } from '../../types/YXmlHook.js'
|
||||
import {
|
||||
iterateUntilUndeleted,
|
||||
removeAssociation,
|
||||
insertNodeHelper } from './util.mjs'
|
||||
import { simpleDiff } from '../../lib/diff.mjs'
|
||||
import { YXmlFragment } from '../../types/YXmlElement.mjs'
|
||||
insertNodeHelper } from './util.js'
|
||||
import { simpleDiff } from '../../lib/diff.js'
|
||||
import { YXmlFragment } from '../../types/YXmlElement.js'
|
||||
|
||||
/**
|
||||
* 1. Check if any of the nodes was deleted
|
||||
@ -20,6 +20,8 @@ import { YXmlFragment } from '../../types/YXmlElement.mjs'
|
||||
* recreate a new yxml element that is bound to that node.
|
||||
* You can detect that a node was moved because expectedId
|
||||
* !== actualId in the list
|
||||
*
|
||||
* @function
|
||||
* @private
|
||||
*/
|
||||
const applyChangesFromDom = (binding, dom, yxml, _document) => {
|
||||
@ -85,6 +87,7 @@ const applyChangesFromDom = (binding, dom, yxml, _document) => {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @function
|
||||
*/
|
||||
export function domObserver (mutations, _document) {
|
||||
this._mutualExclude(() => {
|
@ -3,12 +3,12 @@
|
||||
*/
|
||||
|
||||
/* eslint-env browser */
|
||||
import { YXmlText } from '../../types/YXmlText.mjs'
|
||||
import { YXmlHook } from '../../types/YXmlHook.mjs'
|
||||
import { YXmlElement } from '../../types/YXmlElement.mjs'
|
||||
import { createAssociation, domsToTypes } from './util.mjs'
|
||||
import { filterDomAttributes, defaultFilter } from './filter.mjs'
|
||||
import { DomBinding } from './DomBinding.mjs' // eslint-disable-line
|
||||
import { YXmlText } from '../../types/YXmlText.js'
|
||||
import { YXmlHook } from '../../types/YXmlHook.js'
|
||||
import { YXmlElement } from '../../types/YXmlElement.js'
|
||||
import { createAssociation, domsToTypes } from './util.js'
|
||||
import { filterDomAttributes, defaultFilter } from './filter.js'
|
||||
import { DomBinding } from './DomBinding.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
* @callback DomFilter
|
||||
@ -20,6 +20,7 @@ import { DomBinding } from './DomBinding.mjs' // eslint-disable-line
|
||||
/**
|
||||
* Creates a Yjs type (YXml) based on the contents of a DOM Element.
|
||||
*
|
||||
* @function
|
||||
* @param {Element|Text} element The DOM Element
|
||||
* @param {?Document} _document Optional. Provide the global document object
|
||||
* @param {Object<string, any>} [hooks = {}] Optional. Set of Yjs Hooks
|
@ -2,14 +2,15 @@
|
||||
* @module bindings/dom
|
||||
*/
|
||||
|
||||
import { Y } from '../../utils/Y.mjs' // eslint-disable-line
|
||||
import { YXmlElement, YXmlFragment } from '../../types/YXmlElement.mjs' // eslint-disable-line
|
||||
import { isParentOf } from '../../utils/isParentOf.mjs'
|
||||
import { DomBinding } from './DomBinding.mjs' // eslint-disable-line
|
||||
import { Y } from '../../utils/Y.js' // eslint-disable-line
|
||||
import { YXmlElement, YXmlFragment } from '../../types/YXmlElement.js' // eslint-disable-line
|
||||
import { isParentOf } from '../../utils/isParentOf.js'
|
||||
import { DomBinding } from './DomBinding.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Default filter method (does nothing).
|
||||
*
|
||||
* @function
|
||||
* @param {String} nodeName The nodeName of the element
|
||||
* @param {Map} attrs Map of key-value pairs that are attributes of the node.
|
||||
* @return {Map | null} The allowed attributes or null, if the element should be
|
||||
@ -21,7 +22,10 @@ export const defaultFilter = (nodeName, attrs) => {
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @private
|
||||
* @function
|
||||
* @param {Element} dom
|
||||
* @param {Function} filter
|
||||
*/
|
||||
export const filterDomAttributes = (dom, filter) => {
|
||||
const attrs = new Map()
|
||||
@ -35,11 +39,11 @@ export const filterDomAttributes = (dom, filter) => {
|
||||
/**
|
||||
* Applies a filter on a type.
|
||||
*
|
||||
* @private
|
||||
* @function
|
||||
* @param {Y} y The Yjs instance.
|
||||
* @param {DomBinding} binding The DOM binding instance that has the dom filter.
|
||||
* @param {YXmlElement | YXmlFragment } type The type to apply the filter to.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export const applyFilterOnType = (y, binding, type) => {
|
||||
if (isParentOf(binding.type, type) && type instanceof YXmlElement) {
|
@ -4,10 +4,13 @@
|
||||
|
||||
/* globals getSelection */
|
||||
|
||||
import { getRelativePosition } from '../../utils/relativePosition.mjs'
|
||||
import { getRelativePosition } from '../../utils/relativePosition.js'
|
||||
|
||||
let relativeSelection = null
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
const _getCurrentRelativeSelection = domBinding => {
|
||||
const { baseNode, baseOffset, extentNode, extentOffset } = getSelection()
|
||||
const baseNodeType = domBinding.domToType.get(baseNode)
|
||||
@ -21,8 +24,14 @@ const _getCurrentRelativeSelection = domBinding => {
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export const getCurrentRelativeSelection = typeof getSelection !== 'undefined' ? _getCurrentRelativeSelection : domBinding => null
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export const beforeTransactionSelectionFixer = domBinding => {
|
||||
relativeSelection = getCurrentRelativeSelection(domBinding)
|
||||
}
|
||||
@ -30,6 +39,7 @@ export const beforeTransactionSelectionFixer = domBinding => {
|
||||
/**
|
||||
* Reset the browser range after every transaction.
|
||||
* This prevents any collapsing issues with the local selection.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export const afterTransactionSelectionFixer = domBinding => {
|
@ -5,9 +5,9 @@
|
||||
/* eslint-env browser */
|
||||
/* global getSelection */
|
||||
|
||||
import { YXmlText } from '../../types/YXmlText.mjs'
|
||||
import { YXmlHook } from '../../types/YXmlHook.mjs'
|
||||
import { removeDomChildrenUntilElementFound } from './util.mjs'
|
||||
import { YXmlText } from '../../types/YXmlText.js'
|
||||
import { YXmlHook } from '../../types/YXmlHook.js'
|
||||
import { removeDomChildrenUntilElementFound } from './util.js'
|
||||
|
||||
const findScrollReference = scrollingElement => {
|
||||
if (scrollingElement !== null) {
|
@ -2,8 +2,8 @@
|
||||
* @module bindings/dom
|
||||
*/
|
||||
|
||||
import { domToType } from './domToType.mjs'
|
||||
import { DomBinding } from './DomBinding.mjs' // eslint-disable-line
|
||||
import { domToType } from './domToType.js'
|
||||
import { DomBinding } from './DomBinding.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
* Iterates items until an undeleted item is found.
|
||||
@ -22,6 +22,7 @@ export const iterateUntilUndeleted = item => {
|
||||
* type).
|
||||
*
|
||||
* @private
|
||||
* @function
|
||||
* @param {DomBinding} domBinding The binding object
|
||||
* @param {Element} dom The dom that is to be associated with type
|
||||
* @param {YXmlElement|YXmlHook} type The type that is to be associated with dom
|
||||
@ -37,6 +38,7 @@ export const removeAssociation = (domBinding, dom, type) => {
|
||||
* type).
|
||||
*
|
||||
* @private
|
||||
* @function
|
||||
* @param {DomBinding} domBinding The binding object
|
||||
* @param {DocumentFragment|Element|Text} dom The dom that is to be associated with type
|
||||
* @param {YXmlFragment|YXmlElement|YXmlHook|YXmlText} type The type that is to be associated with dom
|
||||
@ -54,6 +56,7 @@ export const createAssociation = (domBinding, dom, type) => {
|
||||
* forget about oldDom. If oldDom is not associated with any type, nothing happens.
|
||||
*
|
||||
* @private
|
||||
* @function
|
||||
* @param {DomBinding} domBinding The binding object
|
||||
* @param {Element} oldDom The existing dom
|
||||
* @param {Element} newDom The new dom object
|
||||
@ -74,6 +77,7 @@ export const switchAssociation = (domBinding, oldDom, newDom) => {
|
||||
* specified position.
|
||||
*
|
||||
* @private
|
||||
* @function
|
||||
* @param {YXmlElement} type The type in which to insert DOM elements.
|
||||
* @param {YXmlElement|null} prev The reference node. New YxmlElements are
|
||||
* inserted after this node. Set null to insert at
|
||||
@ -101,6 +105,7 @@ export const domsToTypes = (doms, _document, hooks, filter, binding) => {
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @function
|
||||
*/
|
||||
export const insertNodeHelper = (yxml, prevExpectedNode, child, _document, binding) => {
|
||||
let insertedNodes = insertDomElementsAfter(yxml, prevExpectedNode, [child], _document, binding)
|
||||
@ -115,6 +120,7 @@ export const insertNodeHelper = (yxml, prevExpectedNode, child, _document, bindi
|
||||
* Remove children until `elem` is found.
|
||||
*
|
||||
* @private
|
||||
* @function
|
||||
* @param {Element} parent The parent of `elem` and `currentChild`.
|
||||
* @param {Node} currentChild Start removing elements with `currentChild`. If
|
||||
* `currentChild` is `elem` it won't be removed.
|
@ -2,10 +2,10 @@
|
||||
* @module bindings/prosemirror
|
||||
*/
|
||||
|
||||
import { BindMapping } from '../utils/BindMapping.mjs'
|
||||
import { YText } from '../types/YText.mjs' // eslint-disable-line
|
||||
import { YXmlElement, YXmlFragment } from '../types/YXmlElement.mjs' // eslint-disable-line
|
||||
import { createMutex } from '../lib/mutex.mjs'
|
||||
import { BindMapping } from '../utils/BindMapping.js'
|
||||
import { YText } from '../types/YText.js' // eslint-disable-line
|
||||
import { YXmlElement, YXmlFragment } from '../types/YXmlElement.js' // eslint-disable-line
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
import * as PModel from 'prosemirror-model'
|
||||
import { EditorView, Decoration, DecorationSet } from 'prosemirror-view' // eslint-disable-line
|
||||
import { Plugin, PluginKey, EditorState } from 'prosemirror-state' // eslint-disable-line
|
@ -2,7 +2,7 @@
|
||||
* @module bindings/quill
|
||||
*/
|
||||
|
||||
import { createMutex } from '../lib/mutex.mjs'
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
|
||||
const typeObserver = function (event) {
|
||||
const quill = this.target
|
||||
@ -53,7 +53,6 @@ export class QuillBinding {
|
||||
* @private
|
||||
*/
|
||||
this._mutualExclude = createMutex()
|
||||
|
||||
// Set initial value.
|
||||
quill.setContents(textType.toDelta(), 'yjs')
|
||||
// Observers are handled by this class.
|
@ -2,9 +2,9 @@
|
||||
* @module bindings/textarea
|
||||
*/
|
||||
|
||||
import { simpleDiff } from '../lib/diff.mjs'
|
||||
import { getRelativePosition, fromRelativePosition } from '../utils/relativePosition.mjs'
|
||||
import { createMutex } from '../lib/mutex.mjs'
|
||||
import { simpleDiff } from '../lib/diff.js'
|
||||
import { getRelativePosition, fromRelativePosition } from '../utils/relativePosition.js'
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
|
||||
function typeObserver () {
|
||||
this._mutualExclude(() => {
|
@ -18,9 +18,9 @@
|
||||
<div id="content" contenteditable=""></div>
|
||||
</div>
|
||||
<script class="code-js" src="./build/dom.js">
|
||||
import * as Y from 'yjs/index.mjs'
|
||||
import { WebsocketProvider } from 'yjs/provider/websocket.mjs'
|
||||
import { DomBinding } from 'yjs/bindings/dom.mjs'
|
||||
import * as Y from 'yjs/index.js'
|
||||
import { WebsocketProvider } from 'yjs/provider/websocket.js'
|
||||
import { DomBinding } from 'yjs/bindings/dom.js'
|
||||
|
||||
const provider = new WebsocketProvider('wss://api.yjs.website')
|
||||
const ydocument = provider.get('dom')
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as Y from '../index.mjs'
|
||||
import { WebsocketProvider } from '../provider/websocket.mjs'
|
||||
import { DomBinding } from '../bindings/dom.mjs'
|
||||
import * as Y from '../index.js'
|
||||
import { WebsocketProvider } from '../provider/websocket.js'
|
||||
import { DomBinding } from '../bindings/dom.js'
|
||||
|
||||
const provider = new WebsocketProvider('wss://api.yjs.website')
|
||||
const ydocument = provider.get('dom')
|
@ -50,7 +50,7 @@
|
||||
</div>
|
||||
<script class="code-js" src="./build/prosemirror.js">
|
||||
import * as Y from 'yjs'
|
||||
import { WebsocketProvider } from '../provider/websocket.mjs'
|
||||
import { WebsocketProvider } from '../provider/websocket.js'
|
||||
import { prosemirrorPlugin, cursorPlugin } from '../bindings/prosemirror'
|
||||
|
||||
import { EditorState } from 'prosemirror-state'
|
||||
|
@ -1,5 +1,5 @@
|
||||
import * as Y from '../index.mjs'
|
||||
import { WebsocketProvider } from '../provider/websocket.mjs'
|
||||
import * as Y from '../index.js'
|
||||
import { WebsocketProvider } from '../provider/websocket.js'
|
||||
import { prosemirrorPlugin, cursorPlugin } from '../bindings/prosemirror'
|
||||
|
||||
import { EditorState } from 'prosemirror-state'
|
@ -15,8 +15,8 @@
|
||||
</div>
|
||||
<script class="code-js" src="./build/quill.js">
|
||||
import * as Y from 'yjs'
|
||||
import { WebsocketProvider } from 'yjs/provider/websocket.mjs'
|
||||
import { QuillBinding } from 'yjs/bindings/quill.mjs'
|
||||
import { WebsocketProvider } from 'yjs/provider/websocket.js'
|
||||
import { QuillBinding } from 'yjs/bindings/quill.js'
|
||||
|
||||
import Quill from 'quill'
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as Y from '../index.mjs'
|
||||
import { WebsocketProvider } from '../provider/websocket.mjs'
|
||||
import { QuillBinding } from '../bindings/quill.mjs'
|
||||
import * as Y from '../index.js'
|
||||
import { WebsocketProvider } from '../provider/websocket.js'
|
||||
import { QuillBinding } from '../bindings/quill.js'
|
||||
|
||||
import Quill from 'quill'
|
||||
|
@ -12,8 +12,8 @@
|
||||
</div>
|
||||
<script class="code-js" src="./build/textarea.js">
|
||||
import * as Y from 'yjs'
|
||||
import { WebsocketProvider } from 'yjs/provider/websocket.mjs'
|
||||
import { TextareaBinding } from 'yjs/bindings/textarea.mjs'
|
||||
import { WebsocketProvider } from 'yjs/provider/websocket.js'
|
||||
import { TextareaBinding } from 'yjs/bindings/textarea.js'
|
||||
|
||||
const provider = new WebsocketProvider('wss://api.yjs.website')
|
||||
const ydocument = provider.get('textarea')
|
||||
|
@ -1,6 +1,6 @@
|
||||
import * as Y from '../index.mjs'
|
||||
import { WebsocketProvider } from '../provider/websocket.mjs'
|
||||
import { TextareaBinding } from '../bindings/textarea.mjs'
|
||||
import * as Y from '../index.js'
|
||||
import { WebsocketProvider } from '../provider/websocket.js'
|
||||
import { TextareaBinding } from '../bindings/textarea.js'
|
||||
|
||||
const provider = new WebsocketProvider('wss://api.yjs.website')
|
||||
const ydocument = provider.get('textarea')
|
@ -25,7 +25,7 @@
|
||||
|
||||
<div id="aceContainer"></div>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.mjs'></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/ace-builds/src/ace.js"></script>
|
||||
|
||||
<script src="./index.js"></script>
|
||||
|
@ -13,7 +13,7 @@
|
||||
<input type="submit" value="Send">
|
||||
</form>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.mjs'></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -6,7 +6,7 @@
|
||||
<div id="codeMirrorContainer"></div>
|
||||
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.mjs'></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/codemirror/lib/codemirror.js"></script>
|
||||
<script src="../bower_components/codemirror/mode/javascript/javascript.js"></script>
|
||||
<link rel="stylesheet" href="../bower_components/codemirror/lib/codemirror.css">
|
||||
|
@ -13,7 +13,7 @@
|
||||
<button type="button" id="clearDrawingCanvas">Clear Drawing</button>
|
||||
<svg id="drawingCanvas" viewbox="0 0 100 100" width="100%"></svg>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.mjs'></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/d3/d3.min.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<html>
|
||||
</head>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.mjs'></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/d3/d3.min.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
<style>
|
||||
|
@ -1,12 +1,12 @@
|
||||
|
||||
import YWebsocketsConnector from '../../src/Connectors/WebsocketsConnector/WebsocketsConnector.mjs'
|
||||
import Y from '../../src/Y.mjs'
|
||||
import DomBinding from '../../bindings/DomBinding/DomBinding.mjs'
|
||||
import UndoManager from '../../src/Util/UndoManager.mjs'
|
||||
import YXmlFragment from '../../src/Types/YXml/YXmlFragment.mjs'
|
||||
import YXmlText from '../../src/Types/YXml/YXmlText.mjs'
|
||||
import YXmlElement from '../../src/Types/YXml/YXmlElement.mjs'
|
||||
import YIndexdDBPersistence from '../../src/Persistences/IndexedDBPersistence.mjs'
|
||||
import YWebsocketsConnector from '../../src/Connectors/WebsocketsConnector/WebsocketsConnector.js'
|
||||
import Y from '../../src/Y.js'
|
||||
import DomBinding from '../../bindings/DomBinding/DomBinding.js'
|
||||
import UndoManager from '../../src/Util/UndoManager.js'
|
||||
import YXmlFragment from '../../src/Types/YXml/YXmlFragment.js'
|
||||
import YXmlText from '../../src/Types/YXml/YXmlText.js'
|
||||
import YXmlElement from '../../src/Types/YXml/YXmlElement.js'
|
||||
import YIndexdDBPersistence from '../../src/Persistences/IndexedDBPersistence.js'
|
||||
|
||||
const connector = new YWebsocketsConnector()
|
||||
const persistence = new YIndexdDBPersistence()
|
||||
|
@ -17,7 +17,7 @@
|
||||
}
|
||||
</style>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.mjs'></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -17,7 +17,7 @@
|
||||
</g>
|
||||
</svg>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.mjs'></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../bower_components/d3/d3.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
|
@ -14,7 +14,7 @@
|
||||
}
|
||||
</style>
|
||||
<script src="../../y.js"></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.mjs'></script>
|
||||
<script src='../../../y-websockets-client/y-websockets-client.js'></script>
|
||||
<script src="../node_modules/monaco-editor/min/vs/loader.js"></script>
|
||||
<script src="./index.js"></script>
|
||||
</body>
|
||||
|
@ -1,9 +1,9 @@
|
||||
/* eslint-env browser */
|
||||
|
||||
import { createYdbClient } from '../../YdbClient/index.mjs'
|
||||
import Y from '../../src/Y.dist.mjs'
|
||||
import * as ydb from '../../YdbClient/YdbClient.mjs'
|
||||
import DomBinding from '../../bindings/DomBinding/DomBinding.mjs'
|
||||
import { createYdbClient } from '../../YdbClient/index.js'
|
||||
import Y from '../../src/Y.dist.js'
|
||||
import * as ydb from '../../YdbClient/YdbClient.js'
|
||||
import DomBinding from '../../bindings/DomBinding/DomBinding.js'
|
||||
|
||||
const uuidv4 = () => 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
const r = Math.random() * 16 | 0
|
||||
|
50
index.js
Normal file
50
index.js
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
import { Delete } from './structs/Delete.js'
|
||||
import { ItemJSON } from './structs/ItemJSON.js'
|
||||
import { ItemString } from './structs/ItemString.js'
|
||||
import { ItemFormat } from './structs/ItemFormat.js'
|
||||
import { ItemEmbed } from './structs/ItemEmbed.js'
|
||||
import { GC } from './structs/GC.js'
|
||||
|
||||
import { YArray } from './types/YArray.js'
|
||||
import { YMap } from './types/YMap.js'
|
||||
import { YText } from './types/YText.js'
|
||||
import { YXmlText } from './types/YXmlText.js'
|
||||
import { YXmlHook } from './types/YXmlHook.js'
|
||||
import { YXmlElement, YXmlFragment } from './types/YXmlElement.js'
|
||||
|
||||
import { registerStruct } from './utils/structReferences.js'
|
||||
|
||||
export { Y } from './utils/Y.js'
|
||||
export { UndoManager } from './utils/UndoManager.js'
|
||||
export { Transaction } from './utils/Transaction.js'
|
||||
|
||||
export { YArray as Array } from './types/YArray.js'
|
||||
export { YMap as Map } from './types/YMap.js'
|
||||
export { YText as Text } from './types/YText.js'
|
||||
export { YXmlText as XmlText } from './types/YXmlText.js'
|
||||
export { YXmlHook as XmlHook } from './types/YXmlHook.js'
|
||||
export { YXmlElement as XmlElement, YXmlFragment as XmlFragment } from './types/YXmlElement.js'
|
||||
|
||||
export { getRelativePosition, fromRelativePosition } from './utils/relativePosition.js'
|
||||
export { registerStruct } from './utils/structReferences.js'
|
||||
export * from './protocols/syncProtocol.js'
|
||||
export * from './protocols/awarenessProtocol.js'
|
||||
export * from './lib/encoding.js'
|
||||
export * from './lib/decoding.js'
|
||||
export * from './lib/mutex.js'
|
||||
|
||||
registerStruct(0, GC)
|
||||
registerStruct(1, ItemJSON)
|
||||
registerStruct(2, ItemString)
|
||||
registerStruct(3, ItemFormat)
|
||||
registerStruct(4, Delete)
|
||||
|
||||
registerStruct(5, YArray)
|
||||
registerStruct(6, YMap)
|
||||
registerStruct(7, YText)
|
||||
registerStruct(8, YXmlFragment)
|
||||
registerStruct(9, YXmlElement)
|
||||
registerStruct(10, YXmlText)
|
||||
registerStruct(11, YXmlHook)
|
||||
registerStruct(12, ItemEmbed)
|
50
index.mjs
50
index.mjs
@ -1,50 +0,0 @@
|
||||
|
||||
import { Delete } from './structs/Delete.mjs'
|
||||
import { ItemJSON } from './structs/ItemJSON.mjs'
|
||||
import { ItemString } from './structs/ItemString.mjs'
|
||||
import { ItemFormat } from './structs/ItemFormat.mjs'
|
||||
import { ItemEmbed } from './structs/ItemEmbed.mjs'
|
||||
import { GC } from './structs/GC.mjs'
|
||||
|
||||
import { YArray } from './types/YArray.mjs'
|
||||
import { YMap } from './types/YMap.mjs'
|
||||
import { YText } from './types/YText.mjs'
|
||||
import { YXmlText } from './types/YXmlText.mjs'
|
||||
import { YXmlHook } from './types/YXmlHook.mjs'
|
||||
import { YXmlElement, YXmlFragment } from './types/YXmlElement.mjs'
|
||||
|
||||
import { registerStruct } from './utils/structReferences.mjs'
|
||||
|
||||
export { Y } from './utils/Y.mjs'
|
||||
export { UndoManager } from './utils/UndoManager.mjs'
|
||||
export { Transaction } from './utils/Transaction.mjs'
|
||||
|
||||
export { YArray as Array } from './types/YArray.mjs'
|
||||
export { YMap as Map } from './types/YMap.mjs'
|
||||
export { YText as Text } from './types/YText.mjs'
|
||||
export { YXmlText as XmlText } from './types/YXmlText.mjs'
|
||||
export { YXmlHook as XmlHook } from './types/YXmlHook.mjs'
|
||||
export { YXmlElement as XmlElement, YXmlFragment as XmlFragment } from './types/YXmlElement.mjs'
|
||||
|
||||
export { getRelativePosition, fromRelativePosition } from './utils/relativePosition.mjs'
|
||||
export { registerStruct } from './utils/structReferences.mjs'
|
||||
export * from './protocols/syncProtocol.mjs'
|
||||
export * from './protocols/awarenessProtocol.mjs'
|
||||
export * from './lib/encoding.mjs'
|
||||
export * from './lib/decoding.mjs'
|
||||
export * from './lib/mutex.mjs'
|
||||
|
||||
registerStruct(0, GC)
|
||||
registerStruct(1, ItemJSON)
|
||||
registerStruct(2, ItemString)
|
||||
registerStruct(3, ItemFormat)
|
||||
registerStruct(4, Delete)
|
||||
|
||||
registerStruct(5, YArray)
|
||||
registerStruct(6, YMap)
|
||||
registerStruct(7, YText)
|
||||
registerStruct(8, YXmlFragment)
|
||||
registerStruct(9, YXmlElement)
|
||||
registerStruct(10, YXmlText)
|
||||
registerStruct(11, YXmlHook)
|
||||
registerStruct(12, ItemEmbed)
|
@ -4,7 +4,7 @@
|
||||
|
||||
/* global Buffer */
|
||||
|
||||
import * as globals from './globals.mjs'
|
||||
import * as globals from './globals.js'
|
||||
|
||||
/**
|
||||
* A Decoder handles the decoding of an ArrayBuffer.
|
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @module encoding
|
||||
*/
|
||||
import * as globals from './globals.mjs'
|
||||
import * as globals from './globals.js'
|
||||
|
||||
const bits7 = 0b1111111
|
||||
const bits8 = 0b11111111
|
@ -1,4 +1,4 @@
|
||||
import * as encoding from './encoding.mjs'
|
||||
import * as encoding from './encoding.js'
|
||||
|
||||
/**
|
||||
* Check if binary encoding is compatible with golang binary encoding - binary.PutVarUint.
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
* @module idb
|
||||
* @module lib/idb
|
||||
*/
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
import * as globals from './globals.mjs'
|
||||
import * as globals from './globals.js'
|
||||
|
||||
/*
|
||||
* IDB Request to Promise transformer
|
@ -1,6 +1,6 @@
|
||||
import * as test from './testing.mjs'
|
||||
import * as idb from './idb.mjs'
|
||||
import * as logging from './logging.mjs'
|
||||
import * as test from './testing.js'
|
||||
import * as idb from './idb.js'
|
||||
import * as logging from './logging.js'
|
||||
|
||||
const initTestDB = db => idb.createStores(db, [['test']])
|
||||
const testDBName = 'idb-test'
|
@ -2,7 +2,7 @@
|
||||
* @module logging
|
||||
*/
|
||||
|
||||
import * as globals from './globals.mjs'
|
||||
import * as globals from './globals.js'
|
||||
|
||||
let date = new Date().getTime()
|
||||
|
@ -2,10 +2,10 @@
|
||||
* @module prng
|
||||
*/
|
||||
|
||||
import { Mt19937 } from './Mt19937.mjs'
|
||||
import { Xoroshiro128plus } from './Xoroshiro128plus.mjs'
|
||||
import { Xorshift32 } from './Xorshift32.mjs'
|
||||
import * as time from '../../time.mjs'
|
||||
import { Mt19937 } from './Mt19937.js'
|
||||
import { Xoroshiro128plus } from './Xoroshiro128plus.js'
|
||||
import { Xorshift32 } from './Xorshift32.js'
|
||||
import * as time from '../../time.js'
|
||||
|
||||
const DIAMETER = 300
|
||||
const NUMBERS = 10000
|
@ -2,7 +2,7 @@
|
||||
* @module prng
|
||||
*/
|
||||
|
||||
import { Xorshift32 } from './Xorshift32.mjs'
|
||||
import { Xorshift32 } from './Xorshift32.js'
|
||||
|
||||
/**
|
||||
* This is a variant of xoroshiro128plus - the fastest full-period generator passing BigCrush without systematic failures.
|
@ -2,12 +2,12 @@
|
||||
* @module prng
|
||||
*/
|
||||
|
||||
import * as binary from '../binary.mjs'
|
||||
import { fromCharCode, fromCodePoint } from '../string.mjs'
|
||||
import { MAX_SAFE_INTEGER, MIN_SAFE_INTEGER } from '../number.mjs'
|
||||
import * as math from '../math.mjs'
|
||||
import * as binary from '../binary.js'
|
||||
import { fromCharCode, fromCodePoint } from '../string.js'
|
||||
import { MAX_SAFE_INTEGER, MIN_SAFE_INTEGER } from '../number.js'
|
||||
import * as math from '../math.js'
|
||||
|
||||
import { Xoroshiro128plus as DefaultPRNG } from './PRNG/Xoroshiro128plus.mjs'
|
||||
import { Xoroshiro128plus as DefaultPRNG } from './PRNG/Xoroshiro128plus.js'
|
||||
|
||||
/**
|
||||
* Description of the function
|
||||
|
@ -1,134 +0,0 @@
|
||||
/**
|
||||
* @module prng
|
||||
*/
|
||||
|
||||
import * as binary from '../binary.mjs'
|
||||
import { fromCharCode, fromCodePoint } from '../string.mjs'
|
||||
import { MAX_SAFE_INTEGER, MIN_SAFE_INTEGER } from '../number.mjs'
|
||||
import * as math from '../math.mjs'
|
||||
|
||||
import { Xoroshiro128plus as DefaultPRNG } from './PRNG/Xoroshiro128plus.mjs'
|
||||
|
||||
/**
|
||||
* Description of the function
|
||||
* @callback generatorNext
|
||||
* @return {number} A 32bit integer
|
||||
*/
|
||||
|
||||
/**
|
||||
* A random type generator.
|
||||
*
|
||||
* @typedef {Object} PRNG
|
||||
* @property {generatorNext} next Generate new number
|
||||
*/
|
||||
|
||||
/**
|
||||
* Create a Xoroshiro128plus Pseudo-Random-Number-Generator.
|
||||
* This is the fastest full-period generator passing BigCrush without systematic failures.
|
||||
* But there are more PRNGs available in ./PRNG/.
|
||||
*
|
||||
* @param {number} seed A positive 32bit integer. Do not use negative numbers.
|
||||
* @return {PRNG}
|
||||
*/
|
||||
export const createPRNG = seed => new DefaultPRNG(Math.floor(seed < 1 ? seed * binary.BITS32 : seed))
|
||||
|
||||
/**
|
||||
* Generates a single random bool.
|
||||
*
|
||||
* @param {PRNG} gen A random number generator.
|
||||
* @return {Boolean} A random boolean
|
||||
*/
|
||||
export const bool = gen => (gen.next() & 2) === 2 // brackets are non-optional!
|
||||
|
||||
/**
|
||||
* Generates a random integer with 53 bit resolution.
|
||||
*
|
||||
* @param {PRNG} gen A random number generator.
|
||||
* @param {Number} [min = MIN_SAFE_INTEGER] The lower bound of the allowed return values (inclusive).
|
||||
* @param {Number} [max = MAX_SAFE_INTEGER] The upper bound of the allowed return values (inclusive).
|
||||
* @return {Number} A random integer on [min, max]
|
||||
*/
|
||||
export const int53 = (gen, min = MIN_SAFE_INTEGER, max = MAX_SAFE_INTEGER) => math.floor(real53(gen) * (max + 1 - min) + min)
|
||||
|
||||
/**
|
||||
* Generates a random integer with 32 bit resolution.
|
||||
*
|
||||
* @param {PRNG} gen A random number generator.
|
||||
* @param {Number} [min = MIN_SAFE_INTEGER] The lower bound of the allowed return values (inclusive).
|
||||
* @param {Number} [max = MAX_SAFE_INTEGER] The upper bound of the allowed return values (inclusive).
|
||||
* @return {Number} A random integer on [min, max]
|
||||
*/
|
||||
export const int32 = (gen, min = MIN_SAFE_INTEGER, max = MAX_SAFE_INTEGER) => min + ((gen.next() >>> 0) % (max + 1 - min))
|
||||
|
||||
/**
|
||||
* Generates a random real on [0, 1) with 32 bit resolution.
|
||||
*
|
||||
* @param {PRNG} gen A random number generator.
|
||||
* @return {Number} A random real number on [0, 1).
|
||||
*/
|
||||
export const real32 = gen => (gen.next() >>> 0) / binary.BITS32
|
||||
|
||||
/**
|
||||
* Generates a random real on [0, 1) with 53 bit resolution.
|
||||
*
|
||||
* @param {PRNG} gen A random number generator.
|
||||
* @return {Number} A random real number on [0, 1).
|
||||
*/
|
||||
export const real53 = gen => (((gen.next() >>> 5) * binary.BIT26) + (gen.next() >>> 6)) / MAX_SAFE_INTEGER
|
||||
|
||||
/**
|
||||
* Generates a random character from char code 32 - 126. I.e. Characters, Numbers, special characters, and Space:
|
||||
*
|
||||
* (Space)!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[/]^_`abcdefghijklmnopqrstuvwxyz{|}~
|
||||
*/
|
||||
export const char = gen => fromCharCode(int32(gen, 32, 126))
|
||||
|
||||
/**
|
||||
* @param {PRNG} gen
|
||||
* @return {string} A single letter (a-z)
|
||||
*/
|
||||
export const letter = gen => fromCharCode(int32(gen, 97, 122))
|
||||
|
||||
/**
|
||||
* @param {PRNG} gen
|
||||
* @return {string} A random word without spaces consisting of letters (a-z)
|
||||
*/
|
||||
export const word = gen => {
|
||||
const len = int32(gen, 0, 20)
|
||||
let str = ''
|
||||
for (let i = 0; i < len; i++) {
|
||||
str += letter(gen)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: this function produces invalid runes. Does not cover all of utf16!!
|
||||
*/
|
||||
export const utf16Rune = gen => {
|
||||
const codepoint = int32(gen, 0, 256)
|
||||
return fromCodePoint(codepoint)
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {PRNG} gen
|
||||
* @param {number} [maxlen = 20]
|
||||
*/
|
||||
export const utf16String = (gen, maxlen = 20) => {
|
||||
const len = int32(gen, 0, maxlen)
|
||||
let str = ''
|
||||
for (let i = 0; i < len; i++) {
|
||||
str += utf16Rune(gen)
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns one element of a given array.
|
||||
*
|
||||
* @param {PRNG} gen A random number generator.
|
||||
* @param {Array<T>} array Non empty Array of possible values.
|
||||
* @return {T} One of the values of the supplied Array.
|
||||
* @template T
|
||||
*/
|
||||
export const oneOf = (gen, array) => array[int32(gen, 0, array.length - 1)]
|
@ -4,14 +4,14 @@
|
||||
|
||||
/**
|
||||
*TODO: enable tests
|
||||
import * as rt from '../rich-text/formatters.mjs''
|
||||
import { test } from '../test/test.mjs''
|
||||
import Xoroshiro128plus from './PRNG/Xoroshiro128plus.mjs''
|
||||
import Xorshift32 from './PRNG/Xorshift32.mjs''
|
||||
import MT19937 from './PRNG/Mt19937.mjs''
|
||||
import { generateBool, generateInt, generateInt32, generateReal, generateChar } from './random.mjs''
|
||||
import { MAX_SAFE_INTEGER } from '../number/constants.mjs''
|
||||
import { BIT32 } from '../binary/constants.mjs''
|
||||
import * as rt from '../rich-text/formatters.js''
|
||||
import { test } from '../test/test.js''
|
||||
import Xoroshiro128plus from './PRNG/Xoroshiro128plus.js''
|
||||
import Xorshift32 from './PRNG/Xorshift32.js''
|
||||
import MT19937 from './PRNG/Mt19937.js''
|
||||
import { generateBool, generateInt, generateInt32, generateReal, generateChar } from './random.js''
|
||||
import { MAX_SAFE_INTEGER } from '../number/constants.js''
|
||||
import { BIT32 } from '../binary/constants.js''
|
||||
|
||||
function init (Gen) {
|
||||
return {
|
@ -2,8 +2,8 @@
|
||||
* @module testing
|
||||
*/
|
||||
|
||||
import * as logging from './logging.mjs'
|
||||
import { simpleDiff } from './diff.mjs'
|
||||
import * as logging from './logging.js'
|
||||
import { simpleDiff } from './diff.js'
|
||||
|
||||
export const run = async (name, f) => {
|
||||
console.log(`%cStart:%c ${name}`, 'color:blue;', '')
|
28
package-lock.json
generated
28
package-lock.json
generated
@ -3413,12 +3413,14 @@
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
@ -3433,17 +3435,20 @@
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
@ -3560,7 +3565,8 @@
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
@ -3572,6 +3578,7 @@
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
@ -3586,6 +3593,7 @@
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
@ -3593,12 +3601,14 @@
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.1",
|
||||
"yallist": "^3.0.0"
|
||||
@ -3617,6 +3627,7 @@
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
@ -3697,7 +3708,8 @@
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
@ -3709,6 +3721,7 @@
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
@ -3830,6 +3843,7 @@
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -2,7 +2,8 @@
|
||||
"name": "yjs",
|
||||
"version": "13.0.0-73",
|
||||
"description": "A ",
|
||||
"module": "./index.mjs'",
|
||||
"main": "./build/yjs.js",
|
||||
"module": "./index.js'",
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"test": "npm run lint",
|
||||
@ -13,7 +14,7 @@
|
||||
"docs": "rm -rf docs; jsdoc --configure ./.jsdoc.json --verbose --readme ./README.v13.md --package ./package.json || true",
|
||||
"serve-docs": "npm run docs && serve ./docs/",
|
||||
"postversion": "npm run build",
|
||||
"websocket-server": "node --experimental-modules ./provider/websocket/server.mjs",
|
||||
"websocket-server": "node ./provider/websocket/server.js",
|
||||
"now-start": "npm run websocket-server"
|
||||
},
|
||||
"files": [
|
||||
|
@ -1,10 +1,10 @@
|
||||
/*
|
||||
import fs from 'fs'
|
||||
import path from 'path'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import { createMutex } from '../lib/mutex.mjs'
|
||||
import { encodeUpdate, encodeStructsDS, decodePersisted } from './decodePersisted.mjs'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
import { encodeUpdate, encodeStructsDS, decodePersisted } from './decodePersisted.js'
|
||||
|
||||
function createFilePath (persistence, roomName) {
|
||||
// TODO: filename checking!
|
553
persistences/IndexedDBPersistence.js
Normal file
553
persistences/IndexedDBPersistence.js
Normal file
@ -0,0 +1,553 @@
|
||||
/*
|
||||
import { Y } from '../utils/Y.js'
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
import { decodePersisted, encodeStructsDS, encodeUpdate, PERSIST_STRUCTS_DS, PERSIST_UPDATE } from './decodePersisted.js'
|
||||
|
||||
function rtop (request) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
resolve(event.target.result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function openDB (room) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let request = indexedDB.open(room)
|
||||
request.onupgradeneeded = function (event) {
|
||||
const db = event.target.result
|
||||
if (db.objectStoreNames.contains('updates')) {
|
||||
db.deleteObjectStore('updates')
|
||||
}
|
||||
db.createObjectStore('updates', {autoIncrement: true})
|
||||
}
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
const db = event.target.result
|
||||
db.onversionchange = function () { db.close() }
|
||||
resolve(db)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function persist (room) {
|
||||
let t = room.db.transaction(['updates'], 'readwrite')
|
||||
let updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.getAll())
|
||||
.then(updates => {
|
||||
// apply all previous updates before deleting them
|
||||
room.mutex(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
})
|
||||
const encoder = new BinaryEncoder()
|
||||
encodeStructsDS(y, encoder)
|
||||
// delete all pending updates
|
||||
rtop(updatesStore.clear()).then(() => {
|
||||
// write current model
|
||||
updatesStore.put(encoder.createBuffer())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function saveUpdate (room, updateBuffer) {
|
||||
const db = room.db
|
||||
if (db !== null) {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
const updatePut = rtop(updatesStore.put(updateBuffer))
|
||||
rtop(updatesStore.count()).then(cnt => {
|
||||
if (cnt >= PREFERRED_TRIM_SIZE) {
|
||||
persist(room)
|
||||
}
|
||||
})
|
||||
return updatePut
|
||||
}
|
||||
}
|
||||
|
||||
function registerRoomInPersistence (documentsDB, roomName) {
|
||||
return documentsDB.then(
|
||||
db => Promise.all([
|
||||
db,
|
||||
rtop(db.transaction(['documents'], 'readonly').objectStore('documents').get(roomName))
|
||||
])
|
||||
).then(
|
||||
([db, doc]) => {
|
||||
if (doc === undefined) {
|
||||
return rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').add({ roomName, serverUpdateCounter: 0 }))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const PREFERRED_TRIM_SIZE = 400
|
||||
|
||||
export class IndexedDBPersistence {
|
||||
constructor () {
|
||||
this._rooms = new Map()
|
||||
this._documentsDB = new Promise(function (resolve, reject) {
|
||||
let request = indexedDB.open('_yjs_documents')
|
||||
request.onupgradeneeded = function (event) {
|
||||
const db = event.target.result
|
||||
if (db.objectStoreNames.contains('documents')) {
|
||||
db.deleteObjectStore('documents')
|
||||
}
|
||||
db.createObjectStore('documents', { keyPath: "roomName" })
|
||||
}
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
const db = event.target.result
|
||||
db.onversionchange = function () { db.close() }
|
||||
resolve(db)
|
||||
}
|
||||
})
|
||||
addEventListener('unload', () => {
|
||||
// close everything when page unloads
|
||||
this._rooms.forEach(room => {
|
||||
if (room.db !== null) {
|
||||
room.db.close()
|
||||
} else {
|
||||
room.dbPromise.then(db => db.close())
|
||||
}
|
||||
})
|
||||
this._documentsDB.then(db => db.close())
|
||||
})
|
||||
}
|
||||
getAllDocuments () {
|
||||
return this._documentsDB.then(
|
||||
db => rtop(db.transaction(['documents'], 'readonly').objectStore('documents').getAll())
|
||||
)
|
||||
}
|
||||
setRemoteUpdateCounter (roomName, remoteUpdateCounter) {
|
||||
this._documentsDB.then(
|
||||
db => rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').put({ roomName, remoteUpdateCounter }))
|
||||
)
|
||||
}
|
||||
|
||||
_createYInstance (roomName) {
|
||||
const room = this._rooms.get(roomName)
|
||||
if (room !== undefined) {
|
||||
return room.y
|
||||
}
|
||||
const y = new Y()
|
||||
return openDB(roomName).then(
|
||||
db => rtop(db.transaction(['updates'], 'readonly').objectStore('updates').getAll())
|
||||
).then(
|
||||
updates =>
|
||||
y.transact(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
}, true)
|
||||
).then(() => Promise.resolve(y))
|
||||
}
|
||||
|
||||
_persistStructsDS (roomName, structsDS) {
|
||||
const encoder = new BinaryEncoder()
|
||||
encoder.writeVarUint(PERSIST_STRUCTS_DS)
|
||||
encoder.writeArrayBuffer(structsDS)
|
||||
return openDB(roomName).then(db => {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.put(encoder.createBuffer()))
|
||||
})
|
||||
}
|
||||
|
||||
_persistStructs (roomName, structs) {
|
||||
const encoder = new BinaryEncoder()
|
||||
encoder.writeVarUint(PERSIST_UPDATE)
|
||||
encoder.writeArrayBuffer(structs)
|
||||
return openDB(roomName).then(db => {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.put(encoder.createBuffer()))
|
||||
})
|
||||
}
|
||||
|
||||
connectY (roomName, y) {
|
||||
if (this._rooms.has(roomName)) {
|
||||
throw new Error('A Y instance is already bound to this room!')
|
||||
}
|
||||
let room = {
|
||||
db: null,
|
||||
dbPromise: null,
|
||||
channel: null,
|
||||
mutex: createMutex(),
|
||||
y
|
||||
}
|
||||
if (typeof BroadcastChannel !== 'undefined') {
|
||||
room.channel = new BroadcastChannel('__yjs__' + roomName)
|
||||
room.channel.addEventListener('message', e => {
|
||||
room.mutex(function () {
|
||||
decodePersisted(y, new BinaryDecoder(e.data))
|
||||
})
|
||||
})
|
||||
}
|
||||
y.on('destroyed', () => {
|
||||
this.disconnectY(roomName, y)
|
||||
})
|
||||
y.on('afterTransaction', (y, transaction) => {
|
||||
room.mutex(() => {
|
||||
if (transaction.encodedStructsLen > 0) {
|
||||
const encoder = new BinaryEncoder()
|
||||
const update = new BinaryEncoder()
|
||||
encodeUpdate(y, transaction.encodedStructs, update)
|
||||
const updateBuffer = update.createBuffer()
|
||||
if (room.channel !== null) {
|
||||
room.channel.postMessage(updateBuffer)
|
||||
}
|
||||
if (transaction.encodedStructsLen > 0
|
||||
import { Y } from '../utils/Y.js'
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
import { decodePersisted, encodeStructsDS, encodeUpdate, PERSIST_STRUCTS_DS, PERSIST_UPDATE } from './decodePersisted.js'
|
||||
|
||||
function rtop (request) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
resolve(event.target.result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function openDB (room) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let request = indexedDB.open(room)
|
||||
request.onupgradeneeded = function (event) {
|
||||
const db = event.target.result
|
||||
if (db.objectStoreNames.contains('updates')) {
|
||||
db.deleteObjectStore('updates')
|
||||
}
|
||||
db.createObjectStore('updates', {autoIncrement: true})
|
||||
}
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
const db = event.target.result
|
||||
db.onversionchange = function () { db.close() }
|
||||
resolve(db)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function persist (room) {
|
||||
let t = room.db.transaction(['updates'], 'readwrite')
|
||||
let updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.getAll())
|
||||
.then(updates => {
|
||||
// apply all previous updates before deleting them
|
||||
room.mutex(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
})
|
||||
const encoder = new BinaryEncoder()
|
||||
encodeStructsDS(y, encoder)
|
||||
// delete all pending updates
|
||||
rtop(updatesStore.clear()).then(() => {
|
||||
// write current model
|
||||
updatesStore.put(encoder.createBuffer())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function saveUpdate (room, updateBuffer) {
|
||||
const db = room.db
|
||||
if (db !== null) {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
const updatePut = rtop(updatesStore.put(updateBuffer))
|
||||
rtop(updatesStore.count()).then(cnt => {
|
||||
if (cnt >= PREFERRED_TRIM_SIZE) {
|
||||
persist(room)
|
||||
}
|
||||
})
|
||||
return updatePut
|
||||
}
|
||||
}
|
||||
|
||||
function registerRoomInPersistence (documentsDB, roomName) {
|
||||
return documentsDB.then(
|
||||
db => Promise.all([
|
||||
db,
|
||||
rtop(db.transaction(['documents'], 'readonly').objectStore('documents').get(roomName))
|
||||
])
|
||||
).then(
|
||||
([db, doc]) => {
|
||||
if (doc === undefined) {
|
||||
return rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').add({ roomName, serverUpdateCounter: 0 }))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const PREFERRED_TRIM_SIZE = 400
|
||||
|
||||
export class IndexedDBPersistence {
|
||||
constructor () {
|
||||
this._rooms = new Map()
|
||||
this._documentsDB = new Promise(function (resolve, reject) {
|
||||
let request = indexedDB.open('_yjs_documents')
|
||||
request.onupgradeneeded = function (event) {
|
||||
const db = event.target.result
|
||||
if (db.objectStoreNames.contains('documents')) {
|
||||
db.deleteObjectStore('documents')
|
||||
}
|
||||
db.createObjectStore('documents', { keyPath: "roomName" })
|
||||
}
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
const db = event.target.result
|
||||
db.onversionchange = function () { db.close() }
|
||||
resolve(db)
|
||||
}
|
||||
})
|
||||
addEventListener('unload', () => {
|
||||
// close everything when page unloads
|
||||
this._rooms.forEach(room => {
|
||||
if (room.db !== null) {
|
||||
room.db.close()
|
||||
} else {
|
||||
room.dbPromise.then(db => db.close())
|
||||
}
|
||||
})
|
||||
this._documentsDB.then(db => db.close())
|
||||
})
|
||||
}
|
||||
getAllDocuments () {
|
||||
return this._documentsDB.then(
|
||||
db => rtop(db.transaction(['documents'], 'readonly').objectStore('documents').getAll())
|
||||
)
|
||||
}
|
||||
setRemoteUpdateCounter (roomName, remoteUpdateCounter) {
|
||||
this._documentsDB.then(
|
||||
db => rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').put({ roomName, remoteUpdateCounter }))
|
||||
)
|
||||
}
|
||||
|
||||
_createYInstance (roomName) {
|
||||
const room = this._rooms.get(roomName)
|
||||
if (room !== undefined) {
|
||||
return room.y
|
||||
}
|
||||
const y = new Y()
|
||||
return openDB(roomName).then(
|
||||
db => rtop(db.transaction(['updates'], 'readonly').objectStore('updates').getAll())
|
||||
).then(
|
||||
updates =>
|
||||
y.transact(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
}, true)
|
||||
).then(() => Promise.resolve(y))
|
||||
}
|
||||
|
||||
_persistStructsDS (roomName, structsDS) {
|
||||
const encoder = new BinaryEncoder()
|
||||
encoder.writeVarUint(PERSIST_STRUCTS_DS)
|
||||
encoder.writeArrayBuffer(structsDS)
|
||||
return openDB(roomName).then(db => {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.put(encoder.createBuffer()))
|
||||
})
|
||||
}
|
||||
|
||||
_persistStructs (roomName, structs) {
|
||||
const encoder = new BinaryEncoder()
|
||||
encoder.writeVarUint(PERSIST_UPDATE)
|
||||
encoder.writeArrayBuffer(structs)
|
||||
return openDB(roomName).then(db => {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.put(encoder.createBuffer()))
|
||||
})
|
||||
}
|
||||
|
||||
connectY (roomName, y) {
|
||||
if (this._rooms.has(roomName)) {
|
||||
throw new Error('A Y instance is already bound to this room!')
|
||||
}
|
||||
let room = {
|
||||
db: null,
|
||||
dbPromise: null,
|
||||
channel: null,
|
||||
mutex: createMutex(),
|
||||
y
|
||||
}
|
||||
if (typeof BroadcastChannel !== 'undefined') {
|
||||
room.channel = new BroadcastChannel('__yjs__' + roomName)
|
||||
room.channel.addEventListener('message', e => {
|
||||
room.mutex(function () {
|
||||
decodePersisted(y, new BinaryDecoder(e.data))
|
||||
})
|
||||
})
|
||||
}
|
||||
y.on('destroyed', () => {
|
||||
this.disconnectY(roomName, y)
|
||||
})
|
||||
y.on('afterTransaction', (y, transaction) => {
|
||||
room.mutex(() => {
|
||||
if (transaction.encodedStructsLen > 0) {
|
||||
const encoder = new BinaryEncoder()
|
||||
const update = new BinaryEncoder()
|
||||
encodeUpdate(y, transaction.encodedStructs, update)
|
||||
const updateBuffer = update.createBuffer()
|
||||
if (room.channel !== null) {
|
||||
room.channel.postMessage(updateBuffer)
|
||||
}
|
||||
if (transaction.encodedStructsLen > 0) {
|
||||
if (room.db !== null) {
|
||||
saveUpdate(room, updateBuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
// register document in documentsDB
|
||||
this._documentsDB.then(
|
||||
db =>
|
||||
rtop(db.transaction(['documents'], 'readonly').objectStore('documents').get(roomName))
|
||||
.then(
|
||||
doc => doc === undefined && rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').add({ roomName, serverUpdateCounter: -1 }))
|
||||
)
|
||||
)
|
||||
// open room db and read existing data
|
||||
return room.dbPromise = openDB(roomName)
|
||||
.then(db => {
|
||||
room.db = db
|
||||
const t = room.db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
// write current state as update
|
||||
const encoder = new BinaryEncoder()
|
||||
encodeStructsDS(y, encoder)
|
||||
return rtop(updatesStore.put(encoder.createBuffer())).then(() => {
|
||||
// read persisted state
|
||||
return rtop(updatesStore.getAll()).then(updates => {
|
||||
room.mutex(() => {
|
||||
y.transact(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
}, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
disconnectY (roomName) {
|
||||
const {
|
||||
db, channel
|
||||
} = this._rooms.get(roomName)
|
||||
db.close()
|
||||
if (channel !== null) {
|
||||
channel.close()
|
||||
}
|
||||
this._rooms.delete(roomName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all persisted data that belongs to a room.
|
||||
* Automatically destroys all Yjs all Yjs instances that persist to
|
||||
* the room. If `destroyYjsInstances = false` the persistence functionality
|
||||
* will be removed from the Yjs instances.
|
||||
*
|
||||
removePersistedData (roomName, destroyYjsInstances = true) {
|
||||
this.disconnectY(roomName)
|
||||
return rtop(indexedDB.deleteDatabase(roomName))
|
||||
}
|
||||
}
|
||||
{
|
||||
if (room.db !== null) {
|
||||
saveUpdate(room, updateBuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
// register document in documentsDB
|
||||
this._documentsDB.then(
|
||||
db =>
|
||||
rtop(db.transaction(['documents'], 'readonly').objectStore('documents').get(roomName))
|
||||
.then(
|
||||
doc => doc === undefined && rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').add({ roomName, serverUpdateCounter: -1 }))
|
||||
)
|
||||
)
|
||||
// open room db and read existing data
|
||||
return room.dbPromise = openDB(roomName)
|
||||
.then(db => {
|
||||
room.db = db
|
||||
const t = room.db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
// write current state as update
|
||||
const encoder = new BinaryEncoder()
|
||||
encodeStructsDS(y, encoder)
|
||||
return rtop(updatesStore.put(encoder.createBuffer())).then(() => {
|
||||
// read persisted state
|
||||
return rtop(updatesStore.getAll()).then(updates => {
|
||||
room.mutex(() => {
|
||||
y.transact(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
}, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
disconnectY (roomName) {
|
||||
const {
|
||||
db, channel
|
||||
} = this._rooms.get(roomName)
|
||||
db.close()
|
||||
if (channel !== null) {
|
||||
channel.close()
|
||||
}
|
||||
this._rooms.delete(roomName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all persisted data that belongs to a room.
|
||||
* Automatically destroys all Yjs all Yjs instances that persist to
|
||||
* the room. If `destroyYjsInstances = false` the persistence functionality
|
||||
* will be removed from the Yjs instances.
|
||||
*
|
||||
removePersistedData (roomName, destroyYjsInstances = true) {
|
||||
this.disconnectY(roomName)
|
||||
return rtop(indexedDB.deleteDatabase(roomName))
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,288 +0,0 @@
|
||||
|
||||
/*
|
||||
import { Y } from '../utils/Y.mjs'
|
||||
import { createMutex } from '../lib/mutex.mjs'
|
||||
import { decodePersisted, encodeStructsDS, encodeUpdate, PERSIST_STRUCTS_DS, PERSIST_UPDATE } from './decodePersisted.mjs'
|
||||
|
||||
function rtop (request) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
resolve(event.target.result)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function openDB (room) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
let request = indexedDB.open(room)
|
||||
request.onupgradeneeded = function (event) {
|
||||
const db = event.target.result
|
||||
if (db.objectStoreNames.contains('updates')) {
|
||||
db.deleteObjectStore('updates')
|
||||
}
|
||||
db.createObjectStore('updates', {autoIncrement: true})
|
||||
}
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
const db = event.target.result
|
||||
db.onversionchange = function () { db.close() }
|
||||
resolve(db)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function persist (room) {
|
||||
let t = room.db.transaction(['updates'], 'readwrite')
|
||||
let updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.getAll())
|
||||
.then(updates => {
|
||||
// apply all previous updates before deleting them
|
||||
room.mutex(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
})
|
||||
const encoder = new BinaryEncoder()
|
||||
encodeStructsDS(y, encoder)
|
||||
// delete all pending updates
|
||||
rtop(updatesStore.clear()).then(() => {
|
||||
// write current model
|
||||
updatesStore.put(encoder.createBuffer())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function saveUpdate (room, updateBuffer) {
|
||||
const db = room.db
|
||||
if (db !== null) {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
const updatePut = rtop(updatesStore.put(updateBuffer))
|
||||
rtop(updatesStore.count()).then(cnt => {
|
||||
if (cnt >= PREFERRED_TRIM_SIZE) {
|
||||
persist(room)
|
||||
}
|
||||
})
|
||||
return updatePut
|
||||
}
|
||||
}
|
||||
|
||||
function registerRoomInPersistence (documentsDB, roomName) {
|
||||
return documentsDB.then(
|
||||
db => Promise.all([
|
||||
db,
|
||||
rtop(db.transaction(['documents'], 'readonly').objectStore('documents').get(roomName))
|
||||
])
|
||||
).then(
|
||||
([db, doc]) => {
|
||||
if (doc === undefined) {
|
||||
return rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').add({ roomName, serverUpdateCounter: 0 }))
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const PREFERRED_TRIM_SIZE = 400
|
||||
|
||||
export class IndexedDBPersistence {
|
||||
constructor () {
|
||||
this._rooms = new Map()
|
||||
this._documentsDB = new Promise(function (resolve, reject) {
|
||||
let request = indexedDB.open('_yjs_documents')
|
||||
request.onupgradeneeded = function (event) {
|
||||
const db = event.target.result
|
||||
if (db.objectStoreNames.contains('documents')) {
|
||||
db.deleteObjectStore('documents')
|
||||
}
|
||||
db.createObjectStore('documents', { keyPath: "roomName" })
|
||||
}
|
||||
request.onerror = function (event) {
|
||||
reject(new Error(event.target.error))
|
||||
}
|
||||
request.onblocked = function () {
|
||||
location.reload()EventListener' is not defined.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:160:36: 'BinaryDecoder' is not defined.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:167:25: 'BinaryEncoder' is not defined.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:178:25: 'BinaryEncoder' is not defined.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:203:34: 'BinaryDecoder' is not defined.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:213:17: 'encoder' is assigned a value but never used.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:213:31: 'BinaryEncoder' is not defined.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:214:30: 'BinaryEncoder' is not defined.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:230:12: Trailing spaces not allowed.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:237:5: Return statement should not contain assignment.
|
||||
/home/dmonad/go/src/github.com/y-js/yjs/persistences/IndexedDBPersistence.js:243:29: 'BinaryEncoder' i
|
||||
}
|
||||
request.onsuccess = function (event) {
|
||||
const db = event.target.result
|
||||
db.onversionchange = function () { db.close() }
|
||||
resolve(db)
|
||||
}
|
||||
})
|
||||
addEventListener('unload', () => {
|
||||
// close everything when page unloads
|
||||
this._rooms.forEach(room => {
|
||||
if (room.db !== null) {
|
||||
room.db.close()
|
||||
} else {
|
||||
room.dbPromise.then(db => db.close())
|
||||
}
|
||||
})
|
||||
this._documentsDB.then(db => db.close())
|
||||
})
|
||||
}
|
||||
getAllDocuments () {
|
||||
return this._documentsDB.then(
|
||||
db => rtop(db.transaction(['documents'], 'readonly').objectStore('documents').getAll())
|
||||
)
|
||||
}
|
||||
setRemoteUpdateCounter (roomName, remoteUpdateCounter) {
|
||||
this._documentsDB.then(
|
||||
db => rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').put({ roomName, remoteUpdateCounter }))
|
||||
)
|
||||
}
|
||||
|
||||
_createYInstance (roomName) {
|
||||
const room = this._rooms.get(roomName)
|
||||
if (room !== undefined) {
|
||||
return room.y
|
||||
}
|
||||
const y = new Y()
|
||||
return openDB(roomName).then(
|
||||
db => rtop(db.transaction(['updates'], 'readonly').objectStore('updates').getAll())
|
||||
).then(
|
||||
updates =>
|
||||
y.transact(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
}, true)
|
||||
).then(() => Promise.resolve(y))
|
||||
}
|
||||
|
||||
_persistStructsDS (roomName, structsDS) {
|
||||
const encoder = new BinaryEncoder()
|
||||
encoder.writeVarUint(PERSIST_STRUCTS_DS)
|
||||
encoder.writeArrayBuffer(structsDS)
|
||||
return openDB(roomName).then(db => {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.put(encoder.createBuffer()))
|
||||
})
|
||||
}
|
||||
|
||||
_persistStructs (roomName, structs) {
|
||||
const encoder = new BinaryEncoder()
|
||||
encoder.writeVarUint(PERSIST_UPDATE)
|
||||
encoder.writeArrayBuffer(structs)
|
||||
return openDB(roomName).then(db => {
|
||||
const t = db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
return rtop(updatesStore.put(encoder.createBuffer()))
|
||||
})
|
||||
}
|
||||
|
||||
connectY (roomName, y) {
|
||||
if (this._rooms.has(roomName)) {
|
||||
throw new Error('A Y instance is already bound to this room!')
|
||||
}
|
||||
let room = {
|
||||
db: null,
|
||||
dbPromise: null,
|
||||
channel: null,
|
||||
mutex: createMutex(),
|
||||
y
|
||||
}
|
||||
if (typeof BroadcastChannel !== 'undefined') {
|
||||
room.channel = new BroadcastChannel('__yjs__' + roomName)
|
||||
room.channel.addEventListener('message', e => {
|
||||
room.mutex(function () {
|
||||
decodePersisted(y, new BinaryDecoder(e.data))
|
||||
})
|
||||
})
|
||||
}
|
||||
y.on('destroyed', () => {
|
||||
this.disconnectY(roomName, y)
|
||||
})
|
||||
y.on('afterTransaction', (y, transaction) => {
|
||||
room.mutex(() => {
|
||||
if (transaction.encodedStructsLen > 0) {
|
||||
const encoder = new BinaryEncoder()
|
||||
const update = new BinaryEncoder()
|
||||
encodeUpdate(y, transaction.encodedStructs, update)
|
||||
const updateBuffer = update.createBuffer()
|
||||
if (room.channel !== null) {
|
||||
room.channel.postMessage(updateBuffer)
|
||||
}
|
||||
if (transaction.encodedStructsLen > 0) {
|
||||
if (room.db !== null) {
|
||||
saveUpdate(room, updateBuffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
// register document in documentsDB
|
||||
this._documentsDB.then(
|
||||
db =>
|
||||
rtop(db.transaction(['documents'], 'readonly').objectStore('documents').get(roomName))
|
||||
.then(
|
||||
doc => doc === undefined && rtop(db.transaction(['documents'], 'readwrite').objectStore('documents').add({ roomName, serverUpdateCounter: -1 }))
|
||||
)
|
||||
)
|
||||
// open room db and read existing data
|
||||
return room.dbPromise = openDB(roomName)
|
||||
.then(db => {
|
||||
room.db = db
|
||||
const t = room.db.transaction(['updates'], 'readwrite')
|
||||
const updatesStore = t.objectStore('updates')
|
||||
// write current state as update
|
||||
const encoder = new BinaryEncoder()
|
||||
encodeStructsDS(y, encoder)
|
||||
return rtop(updatesStore.put(encoder.createBuffer())).then(() => {
|
||||
// read persisted state
|
||||
return rtop(updatesStore.getAll()).then(updates => {
|
||||
room.mutex(() => {
|
||||
y.transact(() => {
|
||||
updates.forEach(update => {
|
||||
decodePersisted(y, new BinaryDecoder(update))
|
||||
})
|
||||
}, true)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
disconnectY (roomName) {
|
||||
const {
|
||||
db, channel
|
||||
} = this._rooms.get(roomName)
|
||||
db.close()
|
||||
if (channel !== null) {
|
||||
channel.close()
|
||||
}
|
||||
this._rooms.delete(roomName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all persisted data that belongs to a room.
|
||||
* Automatically destroys all Yjs all Yjs instances that persist to
|
||||
* the room. If `destroyYjsInstances = false` the persistence functionality
|
||||
* will be removed from the Yjs instances.
|
||||
*
|
||||
removePersistedData (roomName, destroyYjsInstances = true) {
|
||||
this.disconnectY(roomName)
|
||||
return rtop(indexedDB.deleteDatabase(roomName))
|
||||
}
|
||||
}
|
||||
*/
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
import { integrateRemoteStructs } from '../MessageHandler/integrateRemoteStructs.mjs'
|
||||
import { writeStructs } from '../MessageHandler/syncStep1.mjs'
|
||||
import { writeDeleteSet, readDeleteSet } from '../MessageHandler/deleteSet.mjs'
|
||||
import { integrateRemoteStructs } from '../MessageHandler/integrateRemoteStructs.js'
|
||||
import { writeStructs } from '../MessageHandler/syncStep1.js'
|
||||
import { writeDeleteSet, readDeleteSet } from '../MessageHandler/deleteSet.js'
|
||||
|
||||
export const PERSIST_UPDATE = 0
|
||||
/**
|
1
persistences/indexeddb.js
Normal file
1
persistences/indexeddb.js
Normal file
@ -0,0 +1 @@
|
||||
import * as idb from '../lib/idb.js'
|
@ -2,9 +2,9 @@
|
||||
* @module awareness-protocol
|
||||
*/
|
||||
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
|
||||
const messageUsersStateChanged = 0
|
||||
|
@ -2,14 +2,14 @@
|
||||
* @module sync-protocol
|
||||
*/
|
||||
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import * as ID from '../utils/ID.mjs'
|
||||
import { getStruct } from '../utils/structReferences.mjs'
|
||||
import { deleteItemRange } from '../utils/structManipulation.mjs'
|
||||
import { integrateRemoteStruct } from '../utils/integrateRemoteStructs.mjs'
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import { Item } from '../structs/Item.mjs'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import * as ID from '../utils/ID.js'
|
||||
import { getStruct } from '../utils/structReferences.js'
|
||||
import { deleteItemRange } from '../utils/structManipulation.js'
|
||||
import { integrateRemoteStruct } from '../utils/integrateRemoteStructs.js'
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
import { Item } from '../structs/Item.js'
|
||||
|
||||
/**
|
||||
* @typedef {Map<number, number>} StateSet
|
||||
@ -83,7 +83,7 @@ export const writeDeleteSet = (encoder, y) => {
|
||||
const gc = n.gc
|
||||
if (currentUser !== user) {
|
||||
numberOfUsers++
|
||||
// a new user was foundimport { StateSet } from '../Store/StateStore.mjs' // eslint-disable-line
|
||||
// a new user was foundimport { StateSet } from '../Store/StateStore.js' // eslint-disable-line
|
||||
|
||||
if (currentUser !== null) { // happens on first iteration
|
||||
encoding.setUint32(encoder, lastLenPos, currentLength)
|
5
provider/websocket.js
Normal file
5
provider/websocket.js
Normal file
@ -0,0 +1,5 @@
|
||||
/**
|
||||
* @module provider/websocket
|
||||
*/
|
||||
|
||||
export * from './websocket/WebSocketProvider.js'
|
@ -1,5 +0,0 @@
|
||||
/**
|
||||
* @module provider/websocket
|
||||
*/
|
||||
|
||||
export * from './websocket/WebSocketProvider.mjs'
|
@ -4,8 +4,8 @@
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
import * as Y from '../../index.mjs'
|
||||
export * from '../../index.mjs'
|
||||
import * as Y from '../../index.js'
|
||||
export * from '../../index.js'
|
||||
|
||||
const messageSync = 0
|
||||
const messageAwareness = 1
|
@ -1,10 +1,10 @@
|
||||
/**
|
||||
* @module provider/websocket
|
||||
* @module provider/websocket/server
|
||||
*/
|
||||
|
||||
import * as Y from '../../index.mjs'
|
||||
import WebSocket from 'ws'
|
||||
import http from 'http'
|
||||
const Y = require('../../build/yjs.js')
|
||||
const WebSocket = require('ws')
|
||||
const http = require('http')
|
||||
|
||||
const port = process.env.PORT || 1234
|
||||
|
@ -2,7 +2,7 @@
|
||||
* @module provider/ydb
|
||||
*/
|
||||
|
||||
import * as globals from './globals.mjs'
|
||||
import * as globals from './globals.js'
|
||||
|
||||
export const Class = class NamedEventHandler {
|
||||
constructor () {
|
@ -3,19 +3,19 @@
|
||||
*/
|
||||
|
||||
/* eslint-env browser */
|
||||
import * as idbactions from './idbactions.mjs'
|
||||
import * as globals from '../../lib/globals.mjs'
|
||||
import * as message from './message.mjs'
|
||||
import * as bc from './broadcastchannel.mjs'
|
||||
import * as encoding from '../../lib/encoding.mjs'
|
||||
import * as logging from '../../lib/logging.mjs'
|
||||
import * as idb from '../../lib/idb.mjs'
|
||||
import * as decoding from '../../lib/decoding.mjs'
|
||||
import { Y } from '../../utils/Y.mjs'
|
||||
import { integrateRemoteStruct } from '../MessageHandler/integrateRemoteStructs.mjs'
|
||||
import { createMutualExclude } from '../../lib/mutualExclude.mjs'
|
||||
import * as idbactions from './idbactions.js'
|
||||
import * as globals from '../../lib/globals.js'
|
||||
import * as message from './message.js'
|
||||
import * as bc from './broadcastchannel.js'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as logging from '../../lib/logging.js'
|
||||
import * as idb from '../../lib/idb.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
import { Y } from '../../utils/Y.js'
|
||||
import { integrateRemoteStruct } from '../MessageHandler/integrateRemoteStructs.js'
|
||||
import { createMutualExclude } from '../../lib/mutualExclude.js'
|
||||
|
||||
import * as NamedEventHandler from './NamedEventHandler.mjs'
|
||||
import * as NamedEventHandler from './NamedEventHandler.js'
|
||||
|
||||
/**
|
||||
* @typedef RoomState
|
@ -4,11 +4,11 @@
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
import * as test from './test.mjs'
|
||||
import * as ydbClient from './YdbClient.mjs'
|
||||
import * as globals from './globals.mjs'
|
||||
import * as idbactions from './idbactions.mjs'
|
||||
import * as logging from './logging.mjs'
|
||||
import * as test from './test.js'
|
||||
import * as ydbClient from './YdbClient.js'
|
||||
import * as globals from './globals.js'
|
||||
import * as idbactions from './idbactions.js'
|
||||
import * as logging from './logging.js'
|
||||
|
||||
const wsUrl = 'ws://127.0.0.1:8899/ws'
|
||||
const testRoom = 'testroom'
|
@ -4,10 +4,10 @@
|
||||
|
||||
/* eslint-env browser */
|
||||
|
||||
import * as decoding from '../../lib/decoding.mjs'
|
||||
import * as encoding from '../../lib/encoding.mjs'
|
||||
import * as globals from '../../lib/globals.mjs'
|
||||
import * as NamedEventHandler from './NamedEventHandler.mjs'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as globals from '../../lib/globals.js'
|
||||
import * as NamedEventHandler from './NamedEventHandler.js'
|
||||
|
||||
const bc = new BroadcastChannel('ydb-client')
|
||||
/**
|
@ -33,11 +33,11 @@
|
||||
* - A client may update a room when the room is in either US or Co
|
||||
*/
|
||||
|
||||
import * as encoding from '../../lib/encoding.mjs'
|
||||
import * as decoding from '../../lib/decoding.mjs'
|
||||
import * as idb from '../../lib/idb.mjs'
|
||||
import * as globals from '../../lib/globals.mjs'
|
||||
import * as message from './message.mjs'
|
||||
import * as encoding from '../../lib/encoding.js'
|
||||
import * as decoding from '../../lib/decoding.js'
|
||||
import * as idb from '../../lib/idb.js'
|
||||
import * as globals from '../../lib/globals.js'
|
||||
import * as message from './message.js'
|
||||
|
||||
/**
|
||||
* Get 'client-unconfirmed' store from transaction
|
@ -1,6 +1,6 @@
|
||||
import * as globals from '../../lib/globals.mjs'
|
||||
import * as idbactions from './idbactions.mjs'
|
||||
import * as test from '../../lib/testing.mjs'
|
||||
import * as globals from '../../lib/globals.js'
|
||||
import * as idbactions from './idbactions.js'
|
||||
import * as test from '../../lib/testing.js'
|
||||
|
||||
idbactions.deleteDB().then(() => idbactions.openDB()).then(db => {
|
||||
test.run('update lifetime 1', async (testname) => {
|
@ -2,7 +2,7 @@
|
||||
* @module provider/ydb
|
||||
*/
|
||||
|
||||
import * as ydbclient from './YdbClient.mjs'
|
||||
import * as ydbclient from './YdbClient.js'
|
||||
|
||||
/**
|
||||
* @param {string} url
|
@ -2,11 +2,11 @@
|
||||
* @module provider/ydb
|
||||
*/
|
||||
|
||||
import * as encoding from './encoding.mjs'
|
||||
import * as decoding from './decoding.mjs'
|
||||
import * as idbactions from './idbactions.mjs'
|
||||
import * as logging from './logging.mjs'
|
||||
import * as bc from './broadcastchannel.mjs'
|
||||
import * as encoding from './encoding.js'
|
||||
import * as decoding from './decoding.js'
|
||||
import * as idbactions from './idbactions.js'
|
||||
import * as logging from './logging.js'
|
||||
import * as bc from './broadcastchannel.js'
|
||||
|
||||
/* make sure to update message.go in ydb when updating these values.. */
|
||||
export const MESSAGE_UPDATE = 0 // TODO: rename host_unconfirmed?
|
@ -4,7 +4,7 @@ import babel from 'rollup-plugin-babel'
|
||||
import uglify from 'rollup-plugin-uglify-es'
|
||||
|
||||
export default [{
|
||||
input: './index.mjs',
|
||||
input: './index.js',
|
||||
output: [{
|
||||
name: 'Y',
|
||||
file: 'build/yjs.js',
|
||||
@ -12,9 +12,9 @@ export default [{
|
||||
sourcemap: true
|
||||
}]
|
||||
}, {
|
||||
input: 'tests/index.mjs',
|
||||
input: 'tests/index.js',
|
||||
output: {
|
||||
file: 'build/y.test.mjs',
|
||||
file: 'build/y.test.js',
|
||||
format: 'iife',
|
||||
name: 'ytests',
|
||||
sourcemap: true
|
||||
@ -27,7 +27,7 @@ export default [{
|
||||
commonjs()
|
||||
]
|
||||
}, {
|
||||
input: './examples/prosemirror.mjs',
|
||||
input: './examples/prosemirror.js',
|
||||
output: {
|
||||
name: 'prosemirror',
|
||||
file: 'examples/build/prosemirror.js',
|
||||
@ -44,7 +44,7 @@ export default [{
|
||||
uglify()
|
||||
]
|
||||
}, {
|
||||
input: './examples/dom.mjs',
|
||||
input: './examples/dom.js',
|
||||
output: {
|
||||
name: 'dom',
|
||||
file: 'examples/build/dom.js',
|
||||
@ -56,7 +56,7 @@ export default [{
|
||||
uglify()
|
||||
]
|
||||
}, {
|
||||
input: './examples/textarea.mjs',
|
||||
input: './examples/textarea.js',
|
||||
output: {
|
||||
name: 'textarea',
|
||||
file: 'examples/build/textarea.js',
|
||||
@ -68,7 +68,7 @@ export default [{
|
||||
uglify()
|
||||
]
|
||||
}, {
|
||||
input: './examples/quill.mjs',
|
||||
input: './examples/quill.js',
|
||||
output: {
|
||||
name: 'textarea',
|
||||
file: 'examples/build/quill.js',
|
||||
|
@ -2,15 +2,15 @@
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { getStructReference } from '../utils/structReferences.mjs'
|
||||
import * as ID from '../utils/ID.mjs'
|
||||
import { stringifyID } from '../protocols/syncProtocol.mjs'
|
||||
import { writeStructToTransaction } from '../utils/Transaction.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import { Item } from './Item.mjs' // eslint-disable-line
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import { deleteItemRange } from '../utils/structManipulation.mjs'
|
||||
import { getStructReference } from '../utils/structReferences.js'
|
||||
import * as ID from '../utils/ID.js'
|
||||
import { stringifyID } from '../protocols/syncProtocol.js'
|
||||
import { writeStructToTransaction } from '../utils/Transaction.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import { Item } from './Item.js' // eslint-disable-line
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
import { deleteItemRange } from '../utils/structManipulation.js'
|
||||
|
||||
/**
|
||||
* @private
|
@ -2,12 +2,12 @@
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { getStructReference } from '../utils/structReferences.mjs'
|
||||
import * as ID from '../utils/ID.mjs'
|
||||
import { writeStructToTransaction } from '../utils/Transaction.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import { getStructReference } from '../utils/structReferences.js'
|
||||
import * as ID from '../utils/ID.js'
|
||||
import { writeStructToTransaction } from '../utils/Transaction.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
|
||||
// TODO should have the same base class as Item
|
||||
export class GC {
|
@ -2,15 +2,15 @@
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { getStructReference } from '../utils/structReferences.mjs'
|
||||
import * as ID from '../utils/ID.mjs'
|
||||
import { Delete } from './Delete.mjs'
|
||||
import { transactionTypeChanged, writeStructToTransaction } from '../utils/Transaction.mjs'
|
||||
import { GC } from './GC.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import { Y } from '../utils/Y.mjs'
|
||||
import { Type } from './Type.mjs' // eslint-disable-line
|
||||
import { getStructReference } from '../utils/structReferences.js'
|
||||
import * as ID from '../utils/ID.js'
|
||||
import { Delete } from './Delete.js'
|
||||
import { transactionTypeChanged, writeStructToTransaction } from '../utils/Transaction.js'
|
||||
import { GC } from './GC.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { Y } from '../utils/Y.js'
|
||||
import { Type } from './Type.js' // eslint-disable-line
|
||||
|
||||
/**
|
||||
* @private
|
@ -2,11 +2,11 @@
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { Item } from './Item.mjs'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import { Item } from './Item.js'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
|
||||
export class ItemEmbed extends Item {
|
||||
constructor () {
|
@ -2,11 +2,11 @@
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { Item } from './Item.mjs'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import { Item } from './Item.js'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
|
||||
export class ItemFormat extends Item {
|
||||
constructor () {
|
@ -2,11 +2,11 @@
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { Item, splitHelper } from './Item.mjs'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import { Item, splitHelper } from './Item.js'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
|
||||
export class ItemJSON extends Item {
|
||||
constructor () {
|
@ -2,11 +2,11 @@
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { Item, splitHelper } from './Item.mjs'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import { Item, splitHelper } from './Item.js'
|
||||
import { logItemHelper } from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
|
||||
export class ItemString extends Item {
|
||||
constructor () {
|
@ -2,11 +2,11 @@
|
||||
* @module structs
|
||||
*/
|
||||
|
||||
import { Item } from './Item.mjs'
|
||||
import { EventHandler } from '../utils/EventHandler.mjs'
|
||||
import { createID } from '../utils/ID.mjs'
|
||||
import { YEvent } from '../utils/YEvent.mjs'
|
||||
import { Y } from '../utils/Y.mjs' // eslint-disable-line
|
||||
import { Item } from './Item.js'
|
||||
import { EventHandler } from '../utils/EventHandler.js'
|
||||
import { createID } from '../utils/ID.js'
|
||||
import { YEvent } from '../utils/YEvent.js'
|
||||
import { Y } from '../utils/Y.js' // eslint-disable-line
|
||||
|
||||
// restructure children as if they were inserted one after another
|
||||
const integrateChildren = (y, start) => {
|
@ -1,7 +1,7 @@
|
||||
import { test } from 'cutest'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import { DeleteStore } from '../utils/DeleteStore.mjs'
|
||||
import * as ID from '../utils/ID.mjs'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
import { DeleteStore } from '../utils/DeleteStore.js'
|
||||
import * as ID from '../utils/ID.js'
|
||||
|
||||
/**
|
||||
* Converts a DS to an array of length 10.
|
@ -1,6 +1,6 @@
|
||||
import { test } from 'cutest'
|
||||
import { simpleDiff } from '../lib/diff.mjs'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import { simpleDiff } from '../lib/diff.js'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
|
||||
function runDiffTest (t, a, b, expected) {
|
||||
let result = simpleDiff(a, b)
|
@ -1,8 +1,8 @@
|
||||
import { test } from 'cutest'
|
||||
import { generateRandomUint32 } from '../utils/generateRandomUint32.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import { generateRandomUint32 } from '../utils/generateRandomUint32.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
|
||||
function testEncoding (t, write, read, val) {
|
||||
let encoder = encoding.createEncoder()
|
@ -1,19 +1,19 @@
|
||||
|
||||
import * as Y from '../index.mjs'
|
||||
import { ItemJSON } from '../structs/ItemJSON.mjs'
|
||||
import { ItemString } from '../structs/ItemString.mjs'
|
||||
import { defragmentItemContent } from '../utils/defragmentItemContent.mjs'
|
||||
import * as Y from '../index.js'
|
||||
import { ItemJSON } from '../structs/ItemJSON.js'
|
||||
import { ItemString } from '../structs/ItemString.js'
|
||||
import { defragmentItemContent } from '../utils/defragmentItemContent.js'
|
||||
import Quill from 'quill'
|
||||
import { GC } from '../structs/GC.mjs'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import * as syncProtocol from '../protocols/syncProtocol.mjs'
|
||||
import * as encoding from '../lib/encoding.mjs'
|
||||
import * as decoding from '../lib/decoding.mjs'
|
||||
import { createMutex } from '../lib/mutex.mjs'
|
||||
import { QuillBinding } from '../bindings/quill.mjs'
|
||||
import { DomBinding } from '../bindings/dom/DomBinding.mjs'
|
||||
import { GC } from '../structs/GC.js'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
import * as syncProtocol from '../protocols/syncProtocol.js'
|
||||
import * as encoding from '../lib/encoding.js'
|
||||
import * as decoding from '../lib/decoding.js'
|
||||
import { createMutex } from '../lib/mutex.js'
|
||||
import { QuillBinding } from '../bindings/quill.js'
|
||||
import { DomBinding } from '../bindings/dom/DomBinding.js'
|
||||
|
||||
export * from '../index.mjs'
|
||||
export * from '../index.js'
|
||||
|
||||
/**
|
||||
* @param {TestYInstance} y
|
9
tests/index.js
Normal file
9
tests/index.js
Normal file
@ -0,0 +1,9 @@
|
||||
// TODO: include all tests
|
||||
import './red-black-tree.js'
|
||||
import './y-array.tests.js'
|
||||
import './y-text.tests.js'
|
||||
import './y-map.tests.js'
|
||||
import './y-xml.tests.js'
|
||||
import './encode-decode.tests.js'
|
||||
import './diff.tests.js'
|
||||
import './prosemirror.test.js'
|
@ -1,9 +0,0 @@
|
||||
// TODO: include all tests
|
||||
import './red-black-tree.mjs'
|
||||
import './y-array.tests.mjs'
|
||||
import './y-text.tests.mjs'
|
||||
import './y-map.tests.mjs'
|
||||
import './y-xml.tests.mjs'
|
||||
import './encode-decode.tests.mjs'
|
||||
import './diff.tests.mjs'
|
||||
import './prosemirror.test.mjs'
|
@ -1,8 +1,8 @@
|
||||
import { test } from 'cutest'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import * as Y from '../index.mjs'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
import * as Y from '../index.js'
|
||||
|
||||
import { prosemirrorPlugin } from '../bindings/prosemirror.mjs'
|
||||
import { prosemirrorPlugin } from '../bindings/prosemirror.js'
|
||||
import {EditorState} from 'prosemirror-state'
|
||||
import {EditorView} from 'prosemirror-view'
|
||||
import {schema} from 'prosemirror-schema-basic'
|
@ -1,7 +1,7 @@
|
||||
import { Tree as RedBlackTree } from '../lib/Tree.mjs'
|
||||
import * as ID from '../utils/ID.mjs'
|
||||
import { Tree as RedBlackTree } from '../lib/Tree.js'
|
||||
import * as ID from '../utils/ID.js'
|
||||
import { test, proxyConsole } from 'cutest'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
|
||||
proxyConsole()
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { initArrays, compareUsers, applyRandomTests } from './helper.mjs'
|
||||
import * as Y from '../index.mjs'
|
||||
import { initArrays, compareUsers, applyRandomTests } from './helper.js'
|
||||
import * as Y from '../index.js'
|
||||
import { test, proxyConsole } from 'cutest'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
|
||||
proxyConsole()
|
||||
test('basic spec', async function array0 (t) {
|
@ -1,7 +1,7 @@
|
||||
import { initArrays, compareUsers, applyRandomTests } from './helper.mjs'
|
||||
import * as Y from '../index.mjs'
|
||||
import { initArrays, compareUsers, applyRandomTests } from './helper.js'
|
||||
import * as Y from '../index.js'
|
||||
import { test, proxyConsole } from 'cutest'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
|
||||
proxyConsole()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { initArrays, compareUsers } from './helper.mjs'
|
||||
import { initArrays, compareUsers } from './helper.js'
|
||||
import { test, proxyConsole } from 'cutest'
|
||||
|
||||
proxyConsole()
|
@ -1,7 +1,7 @@
|
||||
import { initArrays, compareUsers, applyRandomTests } from './helper.mjs'
|
||||
import { initArrays, compareUsers, applyRandomTests } from './helper.js'
|
||||
import { test } from 'cutest'
|
||||
import * as Y from '../index.mjs'
|
||||
import * as random from '../lib/prng/prng.mjs'
|
||||
import * as Y from '../index.js'
|
||||
import * as random from '../lib/prng/prng.js'
|
||||
|
||||
test('set property', async function xml0 (t) {
|
||||
var { testConnector, users, xml0, xml1 } = await initArrays(t, { users: 2 })
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user