Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ignore subdocuments? #98

Open
joakim opened this issue Feb 24, 2023 · 3 comments
Open

Ignore subdocuments? #98

joakim opened this issue Feb 24, 2023 · 3 comments

Comments

@joakim
Copy link

joakim commented Feb 24, 2023

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?

@YousefED
Copy link
Owner

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!

@zzph
Copy link

zzph commented May 10, 2023

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>)
}

@trenta3
Copy link

trenta3 commented Jul 30, 2023

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants