I need to communicate this better. Everything that is not documented in the Yjs readme is not stable.
The PermanentUserData feature works but I plan to improve it and I don’t want to give the intention that I will support this implementation in the future. I think that with the addition of Sets in Yjs we can represent PermanentUserData much more efficiently.
This is their use case:
They track insertions: Users produce changes using their client_ids (random integers that we use to generate unique identifiers for each change). The PermanentUserData associates client_ids with their respective user-name. This is currently a mapping from username to an array of client_ids. We could achieve slight improvements by using a Y.Set instead of a Y.Map.
They track deletions: Deletions are not associated to client_ids. We use encoded DeleteSets (ranges of deletions efficiently encoded) to track deletions. Deletions are tracked by associating a user-name to an Y.Array of DeleteSets for each deletion (typically just 5-8 bytes binary encoded). Deletions occur very frequently and we need to make sure that they are stored efficiently. It is currently not ideal in my opinion as each deletion will then be associated with an insertion in the PermanentUserMapping field. This is not too bad, and most other CRDTs represent deletions like this anyway. But we could do much better with the introduction of Y.Sets. DeleteSets are always mergeable and will eventually converge when all created DeleteSets are merged. I want to enable such a feature in Y.Set as well (the ability to implement State-based CRDTs on-top of the Yjs encoding format specifically).
So in short, the feature is working and you can certainly use it right now. I propose that you copy the PermanentUserStorage if you want to use it now. Future releases won’t break this feature, but I will certainly implement a V2 of the same API.
Now that I’m writing this I think the best approach would be to outsource PermanentUserData to a separate package that is versioned. You can use the v1 version (the current release) right now. I’m already planning a V2 release with improved encoding that you can use in the future. The encodings will be incompatible.
In order to use PermanentUserMapping, you need to be familiar with the Yjs document model. It basically only tracks client-ids and DeleteSets and associates them with users. If you want to find out who did a particular change (e.g. who deleted a range, or inserted specific content) then you search for meta-information in PermanentUserMapping.
If you want to understand the Yjs model I propose to tour through Yjs: https://www.youtube.com/watch?v=0l5XgnQ6rB4 It will be much clearer how you can do such a thing. At the moment there is no convenient API to calculate attribution of changes, you’d need to handle that yourself (unless you use y-prosemirror which already implements this feature).