I want to flush the yjs document into disk in y-websocket server side, this is how I do it:
const handleFileSync = async (docName, ydoc) => {
try {
let fileContent = await getFileJsonData(docName)
if (!fileContent) {
console.error(`get file info failed,file info: ${fileContent},docName:${docName}`)
return
}
let projectId = fileContent.result.project_id
let fileName = fileContent.result.name
let text = ydoc.getText(docName)
console.info('get file text:', text)
fs.writeFile(`/opt/data/project/${projectId}/${fileName}`, text, (err) => {
if (err) {
console.error('Failed to write file:', err)
}
})
} catch (err) {
console.error('Failed to sync file to disk', err)
}
}
in this function, I want to flush the latest ydoc document into disk, the docName is the file uniq id (guid/uuid). when I run into this code, I get the error:
Failed to sync file to disk TypeError [ERR_INVALID_ARG_TYPE]: The "data" argument must be of type string or an instance of Buffer, TypedArray, or DataView. Received an instance of YText
at Object.writeFile (node:fs:2155:5)
at handleFileSync (/home/node/app/bin/rd_file.js:15:8)
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
code: 'ERR_INVALID_ARG_TYPE'
}
{
result: {
id: 9,
name: 'main.tex',
created_time: 1691766535428,
updated_time: 1691766535428,
user_id: 1,
doc_status: 1,
project_id: '8919d43a4f034c41ab582c27a04a7058',
file_type: 1,
file_id: '298028e1a37d46abbe6b7105ab8cbb9b',
parent: '8919d43a4f034c41ab582c27a04a7058',
main_flag: 1
},
statusCode: '200',
resultCode: '200',
msg: 'ok'
}
get file text: <ref *2> YText {
_item: null,
_map: Map(0) {},
_start: <ref *1> Item {
id: ID { client: 587431845, clock: 0 },
length: 1,
origin: null,
left: null,
right: Item {
id: [ID],
length: 9,
origin: [ID],
left: [Circular *1],
right: [Item],
rightOrigin: null,
parent: [Circular *2],
parentSub: null,
redone: null,
content: [ContentDeleted],
info: 4
},
rightOrigin: null,
parent: [Circular *2],
parentSub: null,
redone: null,
content: ContentDeleted { len: 1 },
info: 4
},
doc: <ref *3> WSSharedDoc {
_observers: Map(4) {
'load' => [Set],
'sync' => [Set],
'destroy' => [Set],
'update' => [Set]
},
gc: true,
gcFilter: [Function: gcFilter],
clientID: 2850057843,
guid: '5a060d00-ed9d-4150-8ac7-4714a6f26bc3',
collectionid: null,
share: Map(1) { '298028e1a37d46abbe6b7105ab8cbb9b' => [Circular *2] },
store: StructStore {
clients: [Map],
pendingStructs: null,
pendingDs: null
},
_transaction: null,
_transactionCleanups: [],
subdocs: Set(0) {},
_item: null,
shouldLoad: true,
autoLoad: false,
meta: null,
isLoaded: false,
isSynced: false,
whenLoaded: Promise { <pending> },
whenSynced: Promise { <pending> },
name: '298028e1a37d46abbe6b7105ab8cbb9b',
conns: Map(2) { [WebSocket] => [Set], [WebSocket] => [Set] },
awareness: Awareness {
_observers: [Map],
doc: [Circular *3],
clientID: 2850057843,
states: [Map],
meta: [Map],
_checkInterval: Timeout {
_idleTimeout: 3000,
_idlePrev: [TimersList],
_idleNext: [Timeout],
_idleStart: 212717,
_onTimeout: [Function (anonymous)],
_timerArgs: undefined,
_repeat: 3000,
_destroyed: false,
[Symbol(refed)]: true,
[Symbol(kHasPrimitive)]: false,
[Symbol(asyncId)]: 280,
[Symbol(triggerId)]: 243
}
}
},
_length: 49,
_eH: EventHandler { l: [] },
_dEH: EventHandler { l: [] },
_searchMarker: [],
_pending: null
}
seems this line let text = ydoc.getText(docName)
is not the correct way to get the document text. Am I missing something? how can I get the ydoc document content and flush it into disk? I have read the document from here https://docs.yjs.dev/api/shared-types/y.text. I also tried to use this code to get the content:
const content = Y.decodeSnapshot(persistedYdoc.snapshot)
this is the full code:
if (typeof persistenceDir === 'string') {
console.info('Persisting documents to "' + persistenceDir + '"')
// @ts-ignore
const LeveldbPersistence = require('y-leveldb').LeveldbPersistence
const ldb = new LeveldbPersistence(persistenceDir)
persistence = {
provider: ldb,
bindState: async (docName, ydoc) => {
const persistedYdoc = await ldb.getYDoc(docName)
const newUpdates = Y.encodeStateAsUpdate(ydoc)
ldb.storeUpdate(docName, newUpdates)
Y.applyUpdate(ydoc, Y.encodeStateAsUpdate(persistedYdoc))
ydoc.on('update', update => {
ldb.storeUpdate(docName, update)
const content = Y.decodeSnapshot(persistedYdoc.snapshot)
handleFileSync(docName, ydoc, content)
})
},
writeState: async (docName, ydoc) => { }
}
}
shows error:
Caught error while handling a Yjs update TypeError: Cannot read properties of undefined (reading 'length')
at Object.readVarUint (/home/node/app/node_modules/lib0/dist/buffer-9b566988.cjs:1135:27)
at readDeleteSet (/home/node/app/node_modules/yjs/dist/yjs.cjs:309:42)
at decodeSnapshotV2 (/home/node/app/node_modules/yjs/dist/yjs.cjs:2614:23)
at Object.decodeSnapshot (/home/node/app/node_modules/yjs/dist/yjs.cjs:2621:31)
at /home/node/app/bin/utils.js:44:27
at /home/node/app/node_modules/lib0/dist/observable.cjs:77:90
at Array.forEach (<anonymous>)
at WSSharedDoc.emit (/home/node/app/node_modules/lib0/dist/observable.cjs:77:77)
at cleanupTransactions (/home/node/app/node_modules/yjs/dist/yjs.cjs:3259:15)
at transact (/home/node/app/node_modules/yjs/dist/yjs.cjs:3335:9)
Caught error while handling a Yjs update TypeError: Cannot read properties of undefined (reading 'length')
at Object.readVarUint (/home/node/app/node_modules/lib0/dist/buffer-9b566988.cjs:1135:27)
at readDeleteSet (/home/node/app/node_modules/yjs/dist/yjs.cjs:309:42)
at decodeSnapshotV2 (/home/node/app/node_modules/yjs/dist/yjs.cjs:2614:23)
at Object.decodeSnapshot (/home/node/app/node_modules/yjs/dist/yjs.cjs:2621:31)
at /home/node/app/bin/utils.js:44:27
at /home/node/app/node_modules/lib0/dist/observable.cjs:77:90
at Array.forEach (<anonymous>)
at WSSharedDoc.emit (/home/node/app/node_modules/lib0/dist/observable.cjs:77:77)
at cleanupTransactions (/home/node/app/node_modules/yjs/dist/yjs.cjs:3259:15)
at transact (/home/node/app/node_modules/yjs/dist/yjs.cjs:3335:9)
using this code to get the document text(not the binary data):
the
docName
is the document uniq id. more info: https://discuss.yjs.dev/t/how-to-get-the-document-text-the-decode-content-not-binary-content-in-y-websocket/2033