napolab / y-durableobjects

Real-time collaboration with Yjs on Cloudflare Workers using Durable Objects, eliminating Node.js dependencies. Inspired by y-websocket
https://yjs.napochaan.dev/
MIT License
116 stars 7 forks source link

Get & update content of Y.Doc in normal API requests #49

Closed tobimori closed 3 months ago

tobimori commented 3 months ago

The package works great so far, thank you for that.

I'd like to make my Cloudflare Worker interact with the Durable Objects on a normal API request. How would I do that? I don't have much knowledge of DO yet, and the DO class seems to have all properties set to private.

Basically like this:

app.get('/state/:id', async (c) => {
  const id = c.env.Y_SYNC.idFromName(c.req.param('id'));
  const obj = c.env.Y_SYNC.get(id);

  return c.json({
    // ...state from doc
  })
})
app.get('/update/:id', async (c) => {
  const id = c.env.Y_SYNC.idFromName(c.req.param('id'));
  const obj = c.env.Y_SYNC.get(id);

  // change document
  // ...and make DO send out update to all clients

  return c.json({
    // new state from doc
  })
})
naporin0624 commented 3 months ago

Hi, @tobimori.

It is true that y-durableobjects cannot be obtained via jsprc because the YDoc on the server side is set to private.

From your usage example, it seems that you want to obtain/update YDoc via http request, but this library updates YDoc in yjs via websocket.

Can you tell me more about the use case? I will consider how to respond.

tobimori commented 3 months ago

Thanks for your answer, for my case, you can imagine my usecase like a todo app using y.js:

When using the normal app, syncing between clients should happen using websockets. But I also want to provide a REST API to customers, such as for adding to-dos. When adding a to-do, changes should be sent to all clients instantly via the websocket.

naporin0624 commented 3 months ago

Okay, I'll prepare a dedicated method using DurableObjects' js rpc. How about something that can be used in this format? I think an API that exchanges data using Uint8Array would be simple.


app.get('/state/:id', async (c) => {
  const id = c.env.Y_SYNC.idFromName(c.req.param('id'));
  const obj = c.env.Y_SYNC.get(id);
  const state: Uint8Array = await obj.getYDoc();

  return c.json({
    // ...state from doc
  })
})

app.get('/update/:id', async (c) => {
  const id = c.env.Y_SYNC.idFromName(c.req.param('id'));
  const obj = c.env.Y_SYNC.get(id);

  await obj.updateYDoc(/** update message Uint8Array */);

  return c.json({
    // new state from doc
  })
})
tobimori commented 3 months ago

looks good!

naporin0624 commented 3 months ago

@tobimori released! https://github.com/napolab/y-durableobjects/releases/tag/v1.0.0