YousefED / SyncedStore

SyncedStore CRDT is an easy-to-use library for building live, collaborative applications that sync automatically.

Home Page:https://syncedstore.org

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Ignore subdocuments?

joakim opened this issue · comments

commented

First of all, I have to say that SyncedStore is really nice! Thanks for your work on this.

I wonder, would it be possible to include a subdocument in a SyncedMap, and have SyncedStore ignore it so that I can manage it from another provider?

I use SyncedStore to persist and sync items (a bit like files), which works great. The data model is a generic Item of many kinds (like filetypes), where content is managed by SyncedStore.

type Item = {
  id: number
  kind: string
  content: CRDT
}

type CRDT = {
  data: Record<string, unknown>
  meta: Record<string, unknown>
}

const shape: CRDT = {
  data: {},
  meta: {},
}

// ... when later creating/loading an item:

item.content = syncedStore(shape, doc)

This works great for JSON-like kinds of items. I'm now adding support for rich text using Lexical (via svelte-lexical) and have reached a conundrum. Lexical has great support for Yjs collaboration out of the box, with awareness and all, so I'd like to use that. But it requires a YDoc passed to it. I don't want to pass it item.content, as I still want SyncedStore to manage meta.

If only I could include a subdoc in my data model:

item.content.data.text = new Y.Doc({ autoLoad: true })

But SyncedStore sees it as any other object and throws an Error: invalid on the first value it sees that's a function.

Any ideas?

commented

Hi @joakim !

Glad you like SyncedStore. Indeed, unfortunately it doesn't support subdocs yet. However, you could probably workaround this by jumping into "raw yjs" functionality for subdocs.

e.g. (pseudocode:

ymap = getYjsValue(item.content.data)
ymap.set("text", new Y.Doc(...));

You could probably even use SyncedStore again for the new subdoc by passing the doc to the syncedStore method.

Let me know whether these suggestions work!

commented

Hiya YousefED, awesome work on this!

Any progress on subdocs yet?

If not, mind showing how it might work with "raw yjs" functionality? I have tried and not succceeded on the below

My attempt:

// done by another client/server
const folder = rootDoc.getMap()

const subDoc = new Y.Doc()
subDoc.getArray().insert(0, ['a'])
folder.set('sub-doc-1', subDoc)

// store.js
const rootDoc = new Y.Doc
const subDoc = rootDoc.getMap().get('sub-doc-1')

export const store = syncedStore(subDoc);

// component
import { useSyncedStore } from "@syncedstore/react";

export default function App() {
  const subDoc = useSyncedStore(store);
  return subDoc.map(i=> <div> {i} </div>)
}

I'm interested as well in having a native subdocuments integration.
@YousefED Do you have tips on how I could implement it?
It is enough to copy the array implementation in the core package to mimick the methods that Y.Doc has?
https://github.com/YousefED/SyncedStore/blob/main/packages/core/src/array.ts