Discussions related to Shared Editing, Distributed Apps, and Yjs. Questions about Yjs should go to discuss.yjs.dev. Bug reports to the issue tracker.
I am completely new to Yjs (and to npm etc.) I notice when I try to install y-array and y-text those have dependency issues. Could not resolve dependency: peer yjs@">= 12.3.1 < 13.0.0" from y-array@10.1.4
Is this a known issue?
Hello everyone :)
I've had some trouble getting the subdocs example code to work
https://docs.yjs.dev/api/subdocuments
and I suspect it's due to this line:
It is up to the providers to sync subdocuments.
as I'm trying to manually sync the two root docs usingY.applyUpdateV2(rootDoc2, Y.encodeStateAsUpdateV2(rootDoc1))
I'm assuming then that I need to use a fully fledged provider that can sync subdocuments properly.
Looking at the provider list, there doesn't seem to be anything useful for local testing - some kind of in-memory provider (beyond the manual application of updates as in my example above). Is this something that exists, and what have people used instead?
Would I have to implement it myself, similar to the code at the bottom of the subdocs docs page?
e.g. doc.on('subdocs', ...
Am I barking up the wrong tree here and overcomplicating it for myself?
Hi all, can someone point me to a current/good example of how to setup persistence on a server? I cant seem to find a recent oen
@yarnball you can check out this repo - https://github.com/kapv89/yjs-scalable-ws-backend
y-websocket
with subdocument support. I'll update the example server implementation to make use of the subdoc protocol I added later on but for now a working version is here: https://github.com/DAlperin/y-websocket/blob/master/src/y-websocket.js
i'm curious if the benefits of the current way of encoding/decoding data (lib0) are significant enough to warrant the added cost in complexity and resistance to adoption in other languages?
For example, readVarUint
:
numbers < 2^7 is stored in one bytlength
numbers < 2^14 is stored in two bylength
That pretty much eliminates using the standard buffer.readUInt8
, for example, right?
i'm trying to understand the reasoning and whether or not a port to go would be feasible.
uint8 would be a bad example.
There are few libraries that do variable-length encoding. buffer.readUint8 still uses 8 bytes for each integer. Furthermore, lib0/encoding also supports other types of efficient encoding and includes a library for RLE encoding. Node libraries are super bloated and have thousands of dependencies from questionable sources. And another thing: lib0 is much more performant than any other alternative. In some cases, lib0 is 1000x faster than alternatives.
If you are interested in writing a Go binding for Yjs, then I recommend to have a look at the yjs/y-crdt project that already includes some language bindings to other languages. I recommend to join the next Y Community meeting if you have any questions.
Item.js
, specially redoItem
, followRedone
, findIndexCleanStart
, splitItem
. I tried importing them directly from src/internals
but i realised I cant make it work since you have placed lots of instanceof Item
checks on these functions. The item instances are different for a doc created from the.mjs
file and providers and y-prosemirror depend on that mjs file as well, so creating Doc from 'internals.js' does not work. I have re-included the functions thatredoItem
and followRedone
depend on to fork out just the undomanager. And I dont want to fork yjs repo completely. So if you could export them, that would be great.
if I specify an origin for a Y.doc.transact, e.g.
const ydoc = new Y.Doc();
const ymap = ydoc.getMap('mymap');
ydoc.transact(() => {ymap.set('foo', 'bar')}, 'myOrigin')
and, using a WebSocket provider, use ymap.observe(event)
on another client, the value of event.transaction.origin
is not the expected myOrigin
, but WebsocketProvider {....}
. How can I get the origin I provided to ydoc.transact
to appear in the second client as the origin of the transaction?
Hi @micrology, if the update message from the first client is received by the second client, then the y-websocket provider will apply the message to the document. Hence, the origin is the provider. The transaction-origin concept only works locally. It is useful to determine where a change comes from so you can filter specific changes depending on where they come from (e.g. when implementing a 2-way binding).
@compwiz737:matrix.org you could implement something like this using the y-websocket server and an undo-manager (track and revert the changes that you want to undo). The authorative y-websocket server could also just filter messages if a client has only read-only access to a document.
@ellern you could look up how to install a typescript extension to webpack (maybe a babel plugin, but other people probably have better advice as I'm also not using webpack).
Hi @dmonad Yes, I concluded that the origin is always the provider and cannot be reassigned. But I am still keen to label a transaction with the client that originated it. I note that the transaction object has a meta field, which is a map, but it doesn't seem to be possible for a client to set the map (am I right?). Can you think of any other way of labelling a transaction with the originating client, such that the originating client Id would be visible to peers that observe the transaction?
That's not possible unformutately, as changes from multiple clients are often bundled. Then you could use something like the versioning approach that allows you to store which user created which content.
y-protocols
instead?
Hello everyone :)
I've just started with yjs and have found it amazing! I'm particularly interested in the subdocuments feature, but i'm facing some issues with the example in the docs (https://docs.yjs.dev/api/subdocuments) - it doesn't seem to be working right.
Here's what the docs say
A new feature that was introduced in Yjs@13.4.0 is that all documents are given a GUID. The documents are identified with GUIDs and used as a room-name to sync documents. This allows you to duplicate data in the document structure.
Here's some sample code:
const rootDoc = new Y.Doc();const doc = new Y.Doc(); doc.getMap().set("data", "some initial data");
rootDoc.getMap().set("file.txt", doc);
const copy = new Y.Doc({ guid: doc.guid });
rootDoc.getMap().set("copy.txt", copy);
console.log(copy.getMap().get("data"));
console.log(doc.getMap().get("data"));
Here's the output:
undefined
some initial data
Shouldn't the output be the same? Or did I miss something here? Any help is appreciated! Thank you.