valtiojs / valtio-yjs

valtio-yjs makes yjs state easy
MIT License
270 stars 15 forks source link

Support bindProxyAndYDoc #30

Closed cqh963852 closed 2 years ago

cqh963852 commented 2 years ago

bindProxyAndYDoc can support Yjs's subdoc.

cqh963852 commented 2 years ago

image

https://github.com/yjs/yjs/blob/97ef4ae1e0c7cefdaf1673a41b6cc83d68948457/src/utils/Doc.js#L150-L182

the share field can be used for get all exist props.

cqh963852 commented 2 years ago

A doc can be easily convert to json with subdoc. But It is hard to convert json to a doc has a subdoc.

cqh963852 commented 2 years ago
export const bindProxyAndYDoc = (
  p: Record<string, unknown>,
  y: Y.Doc,
  opts: Options = {},
) => {
  const binded: string[] = [];

  y.share.forEach((subY, k) => {
    if (subY instanceof Y.Doc) {
      const pv = proxy({});
      bindProxyAndYDoc(pv, subY, opts);
      p[k] = pv;
      binded.push(k);
      return;
    }
    if (subY instanceof Y.Array) {
      const pv = proxy([]);
      bindProxyAndYArray(pv, subY, opts);
      p[k] = pv;
      binded.push(k);
      return;
    }
    if (subY instanceof Y.Map) {
      const pv = proxy({});
      bindProxyAndYMap(pv, subY, opts);
      p[k] = pv;
      binded.push(k);
      return;
    }
  });

  y.on('update', () => {
    y.share.forEach((subY, k) => {
      if (!binded.includes(k)) {
        if (subY instanceof Y.Doc) {
          const pv = proxy({});
          bindProxyAndYDoc(pv, subY, opts);
          p[k] = pv;
          binded.push(k);
          return;
        }
        if (subY instanceof Y.Array) {
          const pv = proxy([]);
          bindProxyAndYArray(pv, subY, opts);
          p[k] = pv;
          binded.push(k);
          return;
        }
        if (subY instanceof Y.Map) {
          const pv = proxy({});
          bindProxyAndYMap(pv, subY, opts);
          p[k] = pv;
          binded.push(k);
          return;
        }
      }
    });
  });
};
dai-shi commented 2 years ago

(oops, I had my comment as a draft for a few days.)

I was thinking like #3, and Y.Doc can be supported. But,

A doc can be easily convert to json with subdoc. But It is hard to convert json to a doc has a subdoc.

subdocs seem too much trouble for us.