Here is what worked for me
Method #1 If you are using the Hocupocusās database extension
const { Server } = require(ā@hocuspocus/serverā);
const { Database } = require(ā@hocuspocus/extension-databaseā);
const { TiptapTransformer } = require(ā@hocuspocus/transformerā);
const Y = require(āyjsā);
// Express endpoint for websocket
app.ws(ā/:usernameā, (websocket, request) => {
const server = Server.configure({
port,
debounce: 500,
extensions: [
new Database({
fetch: async ({ documentName,document }) => {
document.gc = false // Disabling Garbage Collection on Server
const noteId = documentName
const note = await Notes.findById(noteId)
if (note.document) return note.document
const ydoc = TiptapTransformer.toYdoc(
// the actual JSON
note.description,
// the `field` youāre using in Tiptap. If you donāt know what that is, use 'default'.
"default",
// The Tiptap extensions youāre using. Those are important to create a valid schema.
tipTapExtensions
)
const state = Y.encodeStateAsUpdate(ydoc)
note.document = Buffer.from(state)
await note.save()
return state
},
store: async ({ documentName, state }) => {
const noteId = documentName;
const note = await Notes.findById(noteId)
note.document = state;
await note.save();
}
})
]
});
server.handleConnection(websocket, request);
});
Method #2 Without the database extension
const { Server } = require(ā@hocuspocus/serverā);
const { TiptapTransformer } = require(ā@hocuspocus/transformerā);
const Y = require(āyjsā);
app.ws(ā/:usernameā, (websocket, request) => {
const server = Server.configure({
port,
debounce: 500,
async onStoreDocument({ documentName, document }) {
const currentState = Y.encodeStateAsUpdate(document);
const noteId = documentName;
const note = await Notes.findById(noteId)
note.document = Buffer.from(currentState);
await note.save(); // save current document state to db
},
async onLoadDocument({ documentName, document }) {
document.gc = false;
const noteId = documentName;
const note = await Notes.findById(noteId)
//If the document state is present in DB
if (note.document) {
const stateInDb = note.document
const newDoc = new Y.Doc({ gc: false });
Y.applyUpdate(newDoc, stateInDb)
return newDoc
}
// Else Create Yjs document from Tiptap JSON
const docFromTiptapJSON = TiptapTransformer.toYdoc(
note.description,
// the `field` youāre using in Tiptap. If you donāt know what that is, use 'default'.
"default",
// The Tiptap extensions youāre using. Those are important to create a valid schema.
tipTapExtensions
)
const freshState = Y.encodeStateAsUpdate(docFromTiptapJSON)
note.document = Buffer.from(freshState)
await note.save() // save the state to db
const docFromTiptapJSONwithGCDisabled = new Y.Doc({ gc: false });
Y.applyUpdate(docFromTiptapJSONwithGCDisabled, freshState)
return docFromTiptapJSONwithGCDisabled
},
});
server.handleConnection(websocket, request);
});
This can seem confusing so let me know If you need any help.