From 585265e9a520d4b436db7ea31ca664b4cbbfe170 Mon Sep 17 00:00:00 2001 From: Kevin Jahns Date: Wed, 13 Mar 2019 00:04:19 +0100 Subject: [PATCH] refactor and remove dependency circles --- .gitignore | 2 +- rollup.config.js | 4 +-- src/index.js | 4 +++ src/structs/Delete.js | 4 +-- src/structs/GC.js | 2 +- src/structs/Item.js | 2 +- src/structs/ItemBinary.js | 2 +- src/structs/ItemEmbed.js | 2 +- src/structs/ItemFormat.js | 2 +- src/structs/ItemJSON.js | 2 +- src/structs/ItemString.js | 2 +- src/types/YArray.js | 2 +- src/types/YMap.js | 2 +- src/types/YText.js | 2 +- src/types/YXmlElement.js | 2 +- src/utils/ID.js | 10 +++++-- src/utils/OperationStore.js | 4 +-- src/utils/integrateRemoteStructs.js | 2 +- src/utils/structReferences.js | 35 ++++++++++++++++++++++ src/utils/structStringify.js | 46 +++++++++++++++++++++++++++++ 20 files changed, 111 insertions(+), 22 deletions(-) create mode 100644 src/utils/structReferences.js create mode 100644 src/utils/structStringify.js diff --git a/.gitignore b/.gitignore index 875a48b9..4a9ecae0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ node_modules dist .vscode -./docs +docs diff --git a/rollup.config.js b/rollup.config.js index ac14611f..d3aa5f1f 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -15,8 +15,8 @@ const customModules = new Set([ * @type {Set} */ const customLibModules = new Set([ - // 'funlib', - // 'y-protocols' + 'lib0', + 'y-protocols' ]) const debugResolve = { resolveId (importee) { diff --git a/src/index.js b/src/index.js index dea27bf4..6271412e 100644 --- a/src/index.js +++ b/src/index.js @@ -26,3 +26,7 @@ export { DeleteStore, DSNode } from './utils/DeleteStore.js' export { deleteItemRange } from './utils/structManipulation.js' export { integrateRemoteStruct, integrateRemoteStructs } from './utils/integrateRemoteStructs.js' export { isParentOf } from './utils/isParentOf.js' + +export { stringifyItemID } from './utils/structStringify.js' + +export * from './utils/structReferences.js' diff --git a/src/structs/Delete.js b/src/structs/Delete.js index 835dac09..d75186c7 100644 --- a/src/structs/Delete.js +++ b/src/structs/Delete.js @@ -2,7 +2,7 @@ * @module structs */ -import { getStructReference } from 'y-protocols/sync.js' +import { getStructReference } from '../utils/structReferences.js' import * as ID from '../utils/ID.js' import { writeStructToTransaction } from '../utils/structEncoding.js' import * as decoding from 'lib0/decoding.js' @@ -10,7 +10,7 @@ import * as encoding from 'lib0/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' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' /** * @private diff --git a/src/structs/GC.js b/src/structs/GC.js index 4821c9da..251b8136 100644 --- a/src/structs/GC.js +++ b/src/structs/GC.js @@ -2,7 +2,7 @@ * @module structs */ -import { getStructReference } from 'y-protocols/sync.js' +import { getStructReference } from '../utils/structReferences.js' import * as ID from '../utils/ID.js' import { writeStructToTransaction } from '../utils/structEncoding.js' import * as decoding from 'lib0/decoding.js' diff --git a/src/structs/Item.js b/src/structs/Item.js index 80efc4c1..d4ee75a5 100644 --- a/src/structs/Item.js +++ b/src/structs/Item.js @@ -2,7 +2,7 @@ * @module structs */ -import { getStructReference } from 'y-protocols/sync.js' +import { getStructReference } from '../utils/structReferences.js' import * as ID from '../utils/ID.js' import { Delete } from './Delete.js' import { writeStructToTransaction } from '../utils/structEncoding.js' diff --git a/src/structs/ItemBinary.js b/src/structs/ItemBinary.js index 165d125e..dd1fe957 100644 --- a/src/structs/ItemBinary.js +++ b/src/structs/ItemBinary.js @@ -5,7 +5,7 @@ // TODO: ItemBinary should be able to merge with right (similar to other items). Or the other items (ItemJSON) should not be able to merge - extra byte + consistency import { Item } from './Item.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line diff --git a/src/structs/ItemEmbed.js b/src/structs/ItemEmbed.js index 1ad0fa5c..14cd85d6 100644 --- a/src/structs/ItemEmbed.js +++ b/src/structs/ItemEmbed.js @@ -3,7 +3,7 @@ */ import { Item } from './Item.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line diff --git a/src/structs/ItemFormat.js b/src/structs/ItemFormat.js index 9f005f7e..40fa3b26 100644 --- a/src/structs/ItemFormat.js +++ b/src/structs/ItemFormat.js @@ -3,7 +3,7 @@ */ import { Item } from './Item.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line diff --git a/src/structs/ItemJSON.js b/src/structs/ItemJSON.js index 88b976e8..7e29c8ae 100644 --- a/src/structs/ItemJSON.js +++ b/src/structs/ItemJSON.js @@ -3,7 +3,7 @@ */ import { Item, splitHelper } from './Item.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line diff --git a/src/structs/ItemString.js b/src/structs/ItemString.js index 84d2d850..0c613bfe 100644 --- a/src/structs/ItemString.js +++ b/src/structs/ItemString.js @@ -3,7 +3,7 @@ */ import { Item, splitHelper } from './Item.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' import * as encoding from 'lib0/encoding.js' import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line diff --git a/src/types/YArray.js b/src/types/YArray.js index 91fe3c93..e31b081d 100644 --- a/src/types/YArray.js +++ b/src/types/YArray.js @@ -5,7 +5,7 @@ import { Type } from '../structs/Type.js' import { ItemJSON } from '../structs/ItemJSON.js' import { ItemString } from '../structs/ItemString.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' import { YEvent } from '../utils/YEvent.js' import { Transaction } from '../utils/Transaction.js' // eslint-disable-line import { Item } from '../structs/Item.js' // eslint-disable-line diff --git a/src/types/YMap.js b/src/types/YMap.js index 220c596a..514ef2d5 100644 --- a/src/types/YMap.js +++ b/src/types/YMap.js @@ -5,7 +5,7 @@ import { Item } from '../structs/Item.js' import { Type } from '../structs/Type.js' import { ItemJSON } from '../structs/ItemJSON.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' import { YEvent } from '../utils/YEvent.js' import { ItemBinary } from '../structs/ItemBinary.js' import { isVisible } from '../utils/snapshot.js' diff --git a/src/types/YText.js b/src/types/YText.js index 7d5520df..c6d5f309 100644 --- a/src/types/YText.js +++ b/src/types/YText.js @@ -5,7 +5,7 @@ import { ItemEmbed } from '../structs/ItemEmbed.js' import { ItemString } from '../structs/ItemString.js' import { ItemFormat } from '../structs/ItemFormat.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' import { YArrayEvent, YArray } from './YArray.js' import { isVisible } from '../utils/snapshot.js' diff --git a/src/types/YXmlElement.js b/src/types/YXmlElement.js index 0a73731e..8d8ffad1 100644 --- a/src/types/YXmlElement.js +++ b/src/types/YXmlElement.js @@ -8,7 +8,7 @@ import * as decoding from 'lib0/decoding.js' import { Y } from '../utils/Y.js' // eslint-disable-line import { YArray } from './YArray.js' import { YXmlEvent } from './YXmlEvent.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from '../utils/structStringify.js' /** * Define the elements to which a set of CSS queries apply. diff --git a/src/utils/ID.js b/src/utils/ID.js index 6548bd3b..682bd0a3 100644 --- a/src/utils/ID.js +++ b/src/utils/ID.js @@ -2,7 +2,7 @@ * @module utils */ -import { getStructReference } from 'y-protocols/sync.js' +import { getStructReference } from '../utils/structReferences.js' import * as decoding from 'lib0/decoding.js' import * as encoding from 'lib0/encoding.js' @@ -38,10 +38,14 @@ export const createID = (user, clock) => new ID(user, clock) export const RootFakeUserID = 0xFFFFFF export class RootID { + /** + * @param {string} name + * @param {Function?} typeConstructor + */ constructor (name, typeConstructor) { this.user = RootFakeUserID this.name = name - this.type = getStructReference(typeConstructor) + this.type = typeConstructor === null ? null : getStructReference(typeConstructor) } equals (id) { return id !== null && id.user === this.user && id.name === this.name && id.type === this.type @@ -70,7 +74,7 @@ export class RootID { * y.define('name', Y.Array) // name, and typeConstructor * * @param {string} name - * @param {Function} typeConstructor must be defined in structReferences + * @param {Function?} typeConstructor must be defined in structReferences */ export const createRootID = (name, typeConstructor) => new RootID(name, typeConstructor) diff --git a/src/utils/OperationStore.js b/src/utils/OperationStore.js index 04a6b6a6..eb02aabb 100644 --- a/src/utils/OperationStore.js +++ b/src/utils/OperationStore.js @@ -4,9 +4,9 @@ import { Tree } from 'lib0/tree.js' import * as ID from '../utils/ID.js' -import { getStruct } from 'y-protocols/sync.js' +import { getStruct } from './structReferences.js' import { GC } from '../structs/GC.js' -import * as stringify from 'y-protocols/utils/structStringify.js' +import * as stringify from './structStringify.js' export class OperationStore extends Tree { constructor (y) { diff --git a/src/utils/integrateRemoteStructs.js b/src/utils/integrateRemoteStructs.js index 07f42851..62cc2c25 100644 --- a/src/utils/integrateRemoteStructs.js +++ b/src/utils/integrateRemoteStructs.js @@ -2,7 +2,7 @@ * @module utils */ -import { getStruct } from 'y-protocols/sync.js' +import { getStruct } from '../utils/structReferences.js' import * as decoding from 'lib0/decoding.js' import { GC } from '../structs/GC.js' import { Y } from '../utils/Y.js' // eslint-disable-line diff --git a/src/utils/structReferences.js b/src/utils/structReferences.js new file mode 100644 index 00000000..aefa5bb6 --- /dev/null +++ b/src/utils/structReferences.js @@ -0,0 +1,35 @@ + +/** + * @module utils + */ + +const structs = new Map() +const references = new Map() + +/** + * Register a new Yjs types. The same type must be defined with the same + * reference on all clients! + * + * @param {Number} reference + * @param {Function} structConstructor + * + * @public + */ +export const registerStruct = (reference, structConstructor) => { + structs.set(reference, structConstructor) + references.set(structConstructor, reference) +} + +/** + * @private + */ +export const getStruct = (reference) => { + return structs.get(reference) +} + +/** + * @private + */ +export const getStructReference = (typeConstructor) => { + return references.get(typeConstructor) +} diff --git a/src/utils/structStringify.js b/src/utils/structStringify.js new file mode 100644 index 00000000..53bcd2bc --- /dev/null +++ b/src/utils/structStringify.js @@ -0,0 +1,46 @@ + +import * as ID from './ID.js' + +/** + * Stringify an item id. + * + * @param {ID.ID | ID.RootID} id + * @return {string} + */ +export const stringifyID = id => id instanceof ID.ID ? `(${id.user},${id.clock})` : `(${id.name},${id.type})` + +/** + * Stringify an item as ID. HHere, an item could also be a Yjs instance (e.g. item._parent). + * + * @param {Y.Item | Y.Y | null} item + * @return {string} + */ +export const stringifyItemID = item => { + let result + if (item === null) { + result = '()' + } else if (item._id != null) { + result = stringifyID(item._id) + } else { + // must be a Yjs instance + // Don't include Y in this module, so we prevent circular dependencies. + result = 'y' + } + return result +} + +/** + * Helper utility to convert an item to a readable format. + * + * @param {String} name The name of the item class (YText, ItemString, ..). + * @param {Y.Item} item The item instance. + * @param {String} [append] Additional information to append to the returned + * string. + * @return {String} A readable string that represents the item object. + * + */ +export const logItemHelper = (name, item, append) => { + const left = item._left !== null ? stringifyID(item._left._lastId) : '()' + const origin = item._origin !== null ? stringifyID(item._origin._lastId) : '()' + return `${name}(id:${stringifyItemID(item)},left:${left},origin:${origin},right:${stringifyItemID(item._right)},parent:${stringifyItemID(item._parent)},parentSub:${item._parentSub}${append !== undefined ? ' - ' + append : ''})` +}