@cocreate/crdt
Advanced tools
Comparing version 1.5.5 to 1.6.0
@@ -0,1 +1,18 @@ | ||
# [1.6.0](https://github.com/CoCreate-app/CoCreate-crdt/compare/v1.5.5...v1.6.0) (2021-10-29) | ||
### Bug Fixes | ||
* removed utils folder ([ffe19f9](https://github.com/CoCreate-app/CoCreate-crdt/commit/ffe19f902e504dc2d03ead651dd82ea370a073c7)) | ||
* renamed init to getDoc and created a new init ([6ba16c3](https://github.com/CoCreate-app/CoCreate-crdt/commit/6ba16c360400b54883460ca3e89ef492dfa907cf)) | ||
* syntax error in package.json ([a68379b](https://github.com/CoCreate-app/CoCreate-crdt/commit/a68379bbc3c888243694579e17f4482bc40577d7)) | ||
* updated crdt position to start ([22628f5](https://github.com/CoCreate-app/CoCreate-crdt/commit/22628f52a26e7482dd32ddbd61fbc2692a6e1443)) | ||
* updated package.json dependencies ([5fa5901](https://github.com/CoCreate-app/CoCreate-crdt/commit/5fa5901998961148723c7fec707fbefdacd6e9a7)) | ||
### Features | ||
* conflict resolution when inserts have same posions just milliseconds apart. ([fd1b245](https://github.com/CoCreate-app/CoCreate-crdt/commit/fd1b245fb1252582089d1879418d1bbc184d4f6b)) | ||
* crdtDoc made from javascript map ([be90e1d](https://github.com/CoCreate-app/CoCreate-crdt/commit/be90e1d33a5350ae12c0aeca532250dc2b01f76d)) | ||
## [1.5.5](https://github.com/CoCreate-app/CoCreate-crdt/compare/v1.5.4...v1.5.5) (2021-10-16) | ||
@@ -2,0 +19,0 @@ |
{ | ||
"name": "@cocreate/crdt", | ||
"version": "1.5.5", | ||
"version": "1.6.0", | ||
"description": "CoCreate crdt", | ||
@@ -10,2 +10,9 @@ "author": "CoCreate LLC", | ||
}, | ||
"scripts": { | ||
"start": "npx webpack --config webpack.config.js", | ||
"build": "NODE_ENV=production npx webpack --config webpack.config.js", | ||
"dev": "npx webpack --config webpack.config.js --watch", | ||
"docs": "node ./node_modules/@cocreate/docs/src/index.js", | ||
"hosting": "node ./node_modules/@cocreate/hosting/src/index.js" | ||
}, | ||
"repository": { | ||
@@ -15,2 +22,6 @@ "type": "git", | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/CoCreate-app/CoCreate-crdt/issues" | ||
}, | ||
"homepage": "https://cocreate.app/docs/crdt", | ||
"funding": { | ||
@@ -21,16 +32,2 @@ "type": "GitHub Sponsors ❤", | ||
"main": "./src/index.js", | ||
"scripts": { | ||
"start": "npx webpack --config webpack.config.js", | ||
"build": "NODE_ENV=production npx webpack --config webpack.config.js", | ||
"dev": "npx webpack --config webpack.config.js --watch", | ||
"docs": "node ./node_modules/@cocreate/docs/src/index.js", | ||
"hosting": "node ./node_modules/@cocreate/hosting/src/index.js" | ||
}, | ||
"dependencies": { | ||
"@cocreate/crud-client": "^1.4.15", | ||
"@cocreate/utils": "^1.1.35", | ||
"y-indexeddb": "^9.0.6", | ||
"y-websocket": "^1.3.16", | ||
"yjs": "^13.5.11" | ||
}, | ||
"devDependencies": { | ||
@@ -41,15 +38,18 @@ "@babel/core": "^7.9.6", | ||
"clean-webpack-plugin": "^3.0.0", | ||
"concurrently": "^3.6.1", | ||
"file-loader": "^6.2.0", | ||
"html-webpack-plugin": "^4.5.0", | ||
"http-server": "^0.12.3", | ||
"mini-css-extract-plugin": "^1.5.0", | ||
"standard": "^14.3.4", | ||
"style-loader": "^2.0.0", | ||
"terser-webpack-plugin": "^5.1.1", | ||
"typescript": "^4.1.5", | ||
"uglifyjs-webpack-plugin": "^2.2.0", | ||
"webpack": "^5.24.4", | ||
"webpack-cli": "^4.5.0", | ||
"webpack-log": "^3.0.1" | ||
}, | ||
"dependencies": { | ||
"@cocreate/action": "^1.3.4", | ||
"@cocreate/crud-client": "^1.4.15", | ||
"@cocreate/message-client": "^1.1.38", | ||
"@cocreate/utils": "^1.1.35" | ||
} | ||
} |
772
src/index.js
@@ -1,285 +0,325 @@ | ||
/*globals config, atob, btoa, CustomEvent*/ | ||
import * as Y from 'yjs'; | ||
import { WebsocketProvider } from 'y-websocket'; | ||
// import { IndexeddbPersistence } from 'y-indexeddb'; | ||
/*globals config, atob, btoa, localStorage, CustomEvent*/ | ||
import crud from '@cocreate/crud-client'; | ||
import message from '@cocreate/message-client'; | ||
import uuid from '@cocreate/uuid'; | ||
import action from '@cocreate/action'; | ||
const docs = new Map(); | ||
const clientId = uuid.generate(12); | ||
class CoCreateCRDTClass { | ||
constructor(org, ydoc) { | ||
this.org = config.organization_Id; | ||
this.doc = ydoc; | ||
this.docs = {}; | ||
} | ||
function init(info){ | ||
getDoc(info).then(response => { | ||
getText(info).then(value => { | ||
info.value = value; | ||
info.start = 0; | ||
info['clientId'] = clientId; | ||
localChange(info); | ||
}); | ||
}); | ||
} | ||
async function getDoc(info) { | ||
try { | ||
let docName = generateDocName(info); | ||
let typeName = info.name; | ||
/* | ||
crdt.init({ | ||
collection: "module", | ||
document_id: "", | ||
name: "", | ||
metadata: "xxxx" | ||
}) | ||
*/ | ||
init(info) { | ||
try { | ||
this.createDoc(info); | ||
} catch(e) { | ||
console.log('Invalid param', e); | ||
if (!docs.has(docName)) { | ||
let docNameMap = new Map(); | ||
docs.set(docName, docNameMap); | ||
} | ||
if (!docs.get(docName).has(typeName)) { | ||
let typeNameMap = new Map(); | ||
docs.get(docName).set(typeName, typeNameMap); | ||
} | ||
if (!docs.get(docName).get(typeName).has('changeLog')) { | ||
let response = await crud.readDocumentList({ | ||
collection: "crdtNew", | ||
operator: { | ||
filters: [{ | ||
name: 'name', | ||
operator: "$eq", | ||
value: [docName] | ||
}] | ||
} | ||
}); | ||
let changeLog; | ||
if (response.data.length && response.data[0][typeName]) { | ||
changeLog = response.data[0][typeName]; | ||
} | ||
else { | ||
changeLog = []; | ||
} | ||
docs.get(docName).get(typeName).set('changeLog', changeLog); | ||
generateText(docs.get(docName).get(typeName)); | ||
if (!changeLog.length) | ||
checkDb(info); | ||
} | ||
if (!docs.get(docName).get(typeName).has('cursors')) { | ||
let cursorMap = new Map(); | ||
docs.get(docName).get(typeName).set('cursors', cursorMap); | ||
} | ||
return true; | ||
} | ||
createDoc(info) { | ||
catch (e) { | ||
console.log('Invalid param', e); | ||
} | ||
} | ||
let docName = this.generateDocName(info); | ||
let typeName = this.generateTypeName(info); | ||
String.prototype.customSplice = function (index, absIndex, string) { | ||
return this.slice(0, index) + string+ this.slice(index + Math.abs(absIndex)); | ||
}; | ||
if (this.docs[docName]) { | ||
if (!this.docs[docName].types.some((type) => type === typeName)) { | ||
this.docs[docName].types.push(typeName); | ||
this._registerUpdateEvent(this.docs[docName], typeName); | ||
} | ||
return false; | ||
} | ||
const crdtDoc = this.doc; | ||
const url_socket = this.__getSocketUrl(); | ||
const sharedType = crdtDoc.getText(typeName); | ||
async function generateText(name) { | ||
try { | ||
let string = ''; | ||
let changeLog = name.get('changeLog'); | ||
for (let change of changeLog) { | ||
string = string.customSplice(change.start, change.length, change.value); | ||
} | ||
name.set('text', string); | ||
} | ||
catch (e) { | ||
console.error(e); | ||
} | ||
} | ||
var socketProvider = new WebsocketProvider(url_socket, docName, crdtDoc); | ||
// const indexeddbProvider = new IndexeddbPersistence(docName, crdtDoc); | ||
// indexeddbProvider.on('synced', () => {}); | ||
function checkDb(info) { | ||
let { collection, document_id, name } = info; | ||
crud.readDocument({ collection, document_id, name }).then(response => { | ||
let string = response.data[name]; | ||
if (string) { | ||
info.value = string; | ||
insertChange(info); | ||
} | ||
}); | ||
} | ||
const awareness = socketProvider.awareness; | ||
this._cursors = new Map(); | ||
this._awarenessListener = event => { | ||
const f = clientId => { | ||
this.updateSelection(crdtDoc, typeName, sharedType, this._cursors, clientId, awareness); | ||
}; | ||
event.added.forEach(f); | ||
event.removed.forEach(f); | ||
event.updated.forEach(f); | ||
}; | ||
awareness.on('update', this._awarenessListener); | ||
let isTimerActive; | ||
let timer; | ||
function startTimer() { | ||
isTimerActive = true; | ||
restartTimer(); | ||
timer = setTimeout(() => { | ||
isTimerActive = false; | ||
}, 500); | ||
} | ||
this.docs[docName] = { | ||
id: docName, | ||
doc: crdtDoc, | ||
socket: socketProvider, | ||
awareness: awareness, | ||
types: [typeName], | ||
// indexeddb: indexeddbProvider | ||
}; | ||
this._registerUpdateEvent(this.docs[docName], typeName); | ||
function restartTimer() { | ||
clearTimeout(timer); | ||
} | ||
return true; | ||
function insertChange(info, broadcast) { | ||
let docName = generateDocName(info); | ||
let typeName = info.name; | ||
let type = 'insert'; | ||
if(info.start == undefined) return; | ||
if (info.length > 0) | ||
type = 'delete'; | ||
let change = { | ||
datetime: info.datetime || new Date().toISOString(), | ||
value: info.value || '', | ||
start: info.start, | ||
end: info.end, | ||
length: info.length || 0, | ||
clientId: info.clientId || clientId, | ||
user_id: info.user_id || localStorage.getItem("user_id"), | ||
type | ||
}; | ||
let name = docs.get(docName).get(typeName); | ||
let changeLog = name.get('changeLog'); | ||
let lastChange = changeLog[changeLog.length - 1]; | ||
if (lastChange && change.datetime < lastChange.datetime){ | ||
console.log('requires changeLog rebuild'); | ||
} | ||
__getSocketUrl() { | ||
let w_location = window.location || window.parent.location; | ||
let w_protocol = w_location.protocol; | ||
let w_host = w_location.host; | ||
if (w_location.protocol === "about:") { | ||
w_protocol = w_location.protocol; | ||
w_host = document.referrer; | ||
if (lastChange && change.value.length == 1) { | ||
if (isTimerActive || change.start == lastChange.start){ | ||
startTimer(); | ||
change.start = lastChange.start + lastChange.value.length; | ||
info.start = change.start; | ||
} | ||
let protocol = w_protocol === 'http:' ? 'ws' : 'wss'; | ||
let url_socket = `${protocol}://${w_host}:8080/`; | ||
if (window.config && window.config.host) { | ||
if (window.config.host.includes("://")) { | ||
url_socket = `${window.config.host}/`; | ||
} else { | ||
url_socket = `${protocol}://${window.config.host}/`; | ||
} | ||
} | ||
if (lastChange && change.length == 1) { | ||
if (isTimerActive || change.start == lastChange.start){ | ||
startTimer(); | ||
change.start = lastChange.start - lastChange.length; | ||
info.start = change.start; | ||
} | ||
url_socket += "crdt/"; | ||
return url_socket; | ||
} | ||
_registerUpdateEvent(docName, typeName) { | ||
const crdtDoc = docName.doc; | ||
const sharedType = crdtDoc.getText(typeName); | ||
let self = this; | ||
sharedType.observe((event) => { | ||
self._crdtUpdateEvent(event, typeName); | ||
}); | ||
} | ||
_crdtUpdateEvent(event, typeName) { | ||
const eventDelta = event.delta; | ||
if (eventDelta.length == 0) return; | ||
changeLog.push(change); | ||
let string = name.get('text'); | ||
name.set('text', string.customSplice(change.start, change.length, change.value)); | ||
const info = JSON.parse(atob(typeName)); | ||
// let is_save_value = false | ||
if(!info.clientId){ | ||
info['datetime'] = change.datetime; | ||
info['clientId'] = change.clientId; | ||
const update_event = new CustomEvent('cocreate-crdt-update', { | ||
detail: {eventDelta,...info}, | ||
}); | ||
window.dispatchEvent(update_event); | ||
broadcastChange(info); | ||
localChange(info); | ||
persistChange(info); | ||
} | ||
else | ||
localChange(info); | ||
} | ||
function undoChange(){ | ||
sendPosition(info) { | ||
let docName = this.generateDocName(info); | ||
let typeName = this.generateTypeName(info); | ||
let type = this.docs[docName].doc.getText(typeName); | ||
if (!type) return; | ||
if (info.start != null && info.end != null){ | ||
var anchor = Y.createRelativePositionFromTypeIndex(type, info.start); | ||
var head = Y.createRelativePositionFromTypeIndex(type, info.end); | ||
this.docs[docName].socket.awareness.setLocalStateField('cursor', {anchor, head}); | ||
} | ||
else { | ||
this.docs[docName].socket.awareness.setLocalStateField('cursor', null); | ||
} | ||
} | ||
updateSelection (y, cm, type, cursors, clientId, awareness) { | ||
} | ||
if(clientId !== this.doc.clientID){ | ||
const m = cursors.get(clientId); | ||
if (m !== undefined) { | ||
m.caret.clear(); | ||
if (m.sel !== null) { | ||
m.sel.clear(); | ||
} | ||
cursors.delete(clientId); | ||
} | ||
const aw = awareness.getStates().get(clientId); | ||
function redoChange(){ | ||
if (aw === undefined) { | ||
this.removeCursor(clientId, aw); | ||
return; | ||
} | ||
const user = aw.user || {}; | ||
if (user.color == null) { | ||
user.color = '#ffa500'; | ||
} | ||
if (user.name == null) { | ||
user.name = `User: ${clientId}`; | ||
} | ||
const cursor = aw.cursor; | ||
if (cursor == null || cursor.anchor == null || cursor.head == null) { | ||
this.removeCursor(clientId, aw); | ||
return; | ||
} | ||
// const start = cursor.anchor.item.clock; | ||
// const end = cursor.head.item.clock; | ||
} | ||
const anchor = Y.createAbsolutePositionFromRelativePosition(Y.createRelativePositionFromJSON(cursor.anchor), y); | ||
const head = Y.createAbsolutePositionFromRelativePosition(Y.createRelativePositionFromJSON(cursor.head), y); | ||
if (anchor !== null && head !== null ) { | ||
let info = this.parseName(cursor.anchor['tname']); | ||
let selection = { | ||
collection: info.collection, | ||
document_id: info.document_id, | ||
name: info.name, | ||
start: anchor.index, | ||
end: head.index, | ||
clientId: clientId, | ||
user:{ | ||
'color':user.color, | ||
'name':user.name | ||
}, | ||
}; | ||
const cursorUpdate = new CustomEvent('updateCursor', { | ||
detail: {selection}, | ||
}); | ||
window.dispatchEvent(cursorUpdate); | ||
} | ||
function broadcastChange(info){ | ||
message.send({ | ||
room: "", | ||
broadcast_sender: 'false', | ||
emit: { | ||
message: "crdt", | ||
data: info | ||
} | ||
}); | ||
} | ||
function localChange(data) { | ||
const localChange = new CustomEvent('cocreate-crdt-update', { | ||
detail: { ...data }, | ||
}); | ||
window.dispatchEvent(localChange); | ||
} | ||
function persistChange(info) { | ||
let docName = generateDocName(info); | ||
let typeName = info.name; | ||
let name = docs.get(docName).get(typeName); | ||
let changeLog = name.get('changeLog'); | ||
crud.updateDocument({ | ||
collection: 'crdtNew', | ||
document_id: info.document_id, | ||
data: { | ||
name: docName, | ||
[typeName]: changeLog | ||
}, | ||
upsert: true, | ||
namespace: info.namespace, | ||
room: info.room, | ||
broadcast: info.broadcast, | ||
broadcast_sender: info.broadcast_sender, | ||
metadata: 'crdt-change' | ||
}); | ||
} | ||
message.listen('crdt', function(data) { | ||
if (docs.get(`${data.collection}${data.document_id}`).get(data.name)){ | ||
if (data.clientId !== clientId){ | ||
insertChange(data); | ||
} | ||
} | ||
removeCursor(clientId, aw){ | ||
const cursorRemove = new CustomEvent('removeCursor', { | ||
detail: {clientId, aw}, | ||
}); | ||
window.dispatchEvent(cursorRemove); | ||
return; | ||
}); | ||
} | ||
deleteDoc(docName) { | ||
if (this.docs[docName]) { | ||
delete this.docs[docName]; | ||
/* | ||
crdt.getText({ | ||
collection: 'modules', | ||
document_id: '5e4802ce3ed96d38e71fc7e5', | ||
name: 'name' | ||
}) | ||
*/ | ||
async function getText(info) { | ||
try { | ||
let docName = generateDocName(info); | ||
let typeName = info.name; | ||
let doc = await getDoc(info); | ||
if (doc) { | ||
return docs.get(docName).get(typeName).get('text'); | ||
} | ||
} | ||
destroyObserver(docName, typeName) { | ||
this.docs[docName].doc.getText(typeName).unobserve((event) => {}); | ||
this.docs[docName].socket.awareness.off('change', this._awarenessListener); | ||
catch (e) { | ||
console.error(e); | ||
return ""; | ||
} | ||
parseName(id) { | ||
let data = JSON.parse(atob(id)); | ||
let name = {org: data.org, collection: data.collection, document_id: data.document_id}; | ||
return { | ||
id: btoa(JSON.stringify(name)), | ||
collection: data.collection, | ||
document_id: data.document_id, | ||
name: data.name | ||
}; | ||
} | ||
/* | ||
crdt.replaceText({ | ||
collection: "module", | ||
document_id: "", | ||
name: "", | ||
value: "", | ||
crud: true | false, | ||
element: dom_object, | ||
metadata: "xxxx" | ||
}) | ||
*/ | ||
async function replaceText(info) { | ||
try { | ||
let doc = await getDoc(info); | ||
if (doc) { | ||
let oldValue = getText(info); | ||
let newValue = info['value'].toString(); | ||
if (oldValue && oldValue.length > 0) { | ||
deleteText({ collection: info.collection, document_id: info.document_id, name: info.name, start: 0, length: Math.max(oldValue.length, newValue.length), crud: false }); | ||
} | ||
insertText({ collection: info.collection, document_id: info.document_id, name: info.name, start: 0, value: newValue, crud: info.crud }); | ||
} | ||
} | ||
generateDocName(info) { | ||
let docName = {org: config.organization_Id, collection: info.collection, document_id: info.document_id}; | ||
return btoa(JSON.stringify(docName)); | ||
catch (e) { | ||
console.error(e); | ||
} | ||
generateTypeName(info) { | ||
let nameId = {org: config.organization_Id, collection: info.collection, document_id: info.document_id, name: info.name}; | ||
return btoa(JSON.stringify(nameId)); | ||
} | ||
} | ||
/* | ||
crdt.replaceText({ | ||
collection: "module", | ||
document_id: "", | ||
name: "", | ||
value: "", | ||
updateCrud: true | false, | ||
element: dom_object, | ||
metadata: "xxxx" | ||
}) | ||
*/ | ||
replaceText(info){ | ||
let docName = this.generateDocName(info); | ||
let typeName = this.generateTypeName(info); | ||
if (!this.docs[docName]){ | ||
this.init(info); | ||
} | ||
if (info.updateCrud != false) info.updateCrud = true; | ||
/* | ||
crdt.insertText({ | ||
collection: 'module_activities', | ||
document_id: '5e4802ce3ed96d38e71fc7e5', | ||
name: 'name', | ||
value: 'T', | ||
start: '8', | ||
attributes: {bold: true} | ||
}) | ||
*/ | ||
function insertText(info) { | ||
updateCrdt(info); | ||
} | ||
/* | ||
crdt.deleteText({ | ||
collection: 'module_activities', | ||
document_id: '5e4802ce3ed96d38e71fc7e5', | ||
name: 'name', | ||
start: '8', | ||
length: 2, | ||
}) | ||
*/ | ||
function deleteText(info) { | ||
updateCrdt(info); | ||
} | ||
async function updateCrdt(info) { | ||
let broadcast = true; | ||
let doc = await getDoc(info); | ||
if (doc) { | ||
if (docName) { | ||
let oldData = this.docs[docName].doc.getText(typeName).toString(); | ||
let textValue = info['value'].toString(); | ||
if (oldData && oldData.length > 0) { | ||
this.deleteText({collection: info.collection, document_id: info.document_id, name: info.name, position: 0, length: Math.max(oldData.length, textValue.length), crud: info['crud']}); | ||
} | ||
this.insertText({ collection: info.collection, document_id: info.document_id, name: info.name, position: 0, value: textValue, crud: info.crud }); | ||
} | ||
insertChange(info, broadcast); | ||
if (info.crud != 'false') { | ||
let wholestring = await getText(info); | ||
crud.updateDocument({ | ||
collection: info.collection, | ||
document_id: info.document_id, | ||
data: {[info.name]: info.value}, | ||
data: { | ||
[info.name]: wholestring | ||
}, | ||
upsert: info.upsert, | ||
// element: info.element, | ||
namespace: info.namespace, | ||
@@ -289,156 +329,120 @@ room: info.room, | ||
broadcast_sender: info.broadcast_sender, | ||
metadata:info.metadata | ||
metadata: 'crdt-change' | ||
}); | ||
} | ||
} | ||
/* | ||
crdt.insertText({ | ||
collection: 'module_activities', | ||
document_id: '5e4802ce3ed96d38e71fc7e5', | ||
name: 'name', | ||
value: 'T', | ||
position: '8', | ||
attributes: {bold: true} | ||
}) | ||
*/ | ||
insertText(info) { | ||
try { | ||
let docName = this.generateDocName(info); | ||
let typeName = this.generateTypeName(info); | ||
if (docName) { | ||
this.docs[docName].doc.getText(typeName).insert(info['position'], info['value'], info['attributes']); | ||
if (info.crud != 'false') { | ||
let wholestring = this.docs[docName].doc.getText(typeName).toString(); | ||
crud.updateDocument({ | ||
collection: info.collection, | ||
document_id: info.document_id, | ||
data: { | ||
[info.name]: wholestring | ||
}, | ||
upsert: info.upsert, | ||
namespace: info.namespace, | ||
room: info.room, | ||
broadcast: info.broadcast, | ||
broadcast_sender: info.broadcast_sender, | ||
metadata: 'crdt-change' | ||
}); | ||
} | ||
} | ||
} | ||
/* | ||
crdt.getPosition(function(data)) | ||
crdt.getPosition(function(data){console.log(" EScuchando ahora ", data)}) | ||
*/ | ||
function getPosition(callback) { | ||
if (typeof miFuncion === 'function') | ||
this.changeListenAwereness(callback); | ||
else | ||
console.error('Callback should be a function'); | ||
} | ||
function sendPosition(info) { | ||
try { | ||
let docName = generateDocName(info); | ||
let typeName = info.name; | ||
let type = docs.get(docName).get(typeName); | ||
let start = info.start; | ||
let end = info.end; | ||
let color = info.color || localStorage.getItem("cursorColor");; | ||
let background = info.background || localStorage.getItem("cursorBackground");; | ||
let userName = info.userName || localStorage.getItem("userName"); | ||
let user_id = info.user_id || localStorage.getItem("user_id"); | ||
info['clientId'] = clientId; | ||
if (!type) return; | ||
if (start != null && end != null) { | ||
type.get('cursors').set(clientId, { start, end, background, color, userName, user_id }); | ||
} | ||
catch (e) { | ||
console.error(e); | ||
else { | ||
type.get('cursors').delete(clientId); | ||
} | ||
} | ||
/* | ||
crdt.deleteText({ | ||
collection: 'module_activities', | ||
document_id: '5e4802ce3ed96d38e71fc7e5', | ||
name: 'name', | ||
position: '8', | ||
length: 2, | ||
}) | ||
*/ | ||
deleteText(info) { | ||
try{ | ||
let docName = this.generateDocName(info); | ||
let typeName = this.generateTypeName(info); | ||
if (docName) { | ||
this.docs[docName].doc.getText(typeName).delete(info['position'], info['length']); | ||
if (info.crud != 'false') { | ||
let wholestring = this.docs[docName].doc.getText(typeName).toString(); | ||
crud.updateDocument({ | ||
collection: info.collection, | ||
document_id: info.document_id, | ||
data: { | ||
[info.name]: wholestring | ||
}, | ||
upsert: info.upsert, | ||
namespace: info.namespace, | ||
room: info.room, | ||
broadcast: info.broadcast, | ||
broadcast_sender: info.broadcast_sender, | ||
metadata: 'crdt-change' | ||
}); | ||
message.send({ | ||
room: "", | ||
emit: { | ||
message: "cursor", | ||
data: { | ||
collection: info.collection, | ||
document_id: info.document_id, | ||
name: info.name, | ||
start, | ||
end, | ||
clientId: info.clientId || clientId, | ||
color, | ||
background, | ||
userName, | ||
user_id | ||
} | ||
} | ||
} | ||
catch (e) { | ||
console.error(e); | ||
} | ||
}, | ||
}); | ||
} | ||
/* | ||
crdt.getText({ | ||
collection: 'module_activities', | ||
document_id: '5e4802ce3ed96d38e71fc7e5', | ||
name: 'name' | ||
}) | ||
*/ | ||
getText(info) { | ||
try{ | ||
let docName = this.generateDocName(info); | ||
let typeName = this.generateTypeName(info); | ||
if (docName) { | ||
if (!this.docs[docName]){ | ||
this.init(info); | ||
} | ||
return this.docs[docName].doc.getText(typeName).toString(); | ||
} | ||
else return "--"; | ||
} | ||
catch (e) { | ||
console.error(e); | ||
return ""; | ||
} | ||
catch (e) { | ||
console.error(e); | ||
} | ||
} | ||
/* | ||
crdt.getDoc({ | ||
collection: 'module_activities', | ||
document_id: '5e4802ce3ed96d38e71fc7e5', | ||
name: 'name' | ||
}) | ||
*/ | ||
getDoc(info) { | ||
try{ | ||
let docName = this.generateDocName(info); | ||
let typeName = this.generateTypeName(info); | ||
if (docName) { | ||
if (!this.docs[docName]){ | ||
this.init(info); | ||
} | ||
return this.docs[docName].doc.getText(typeName); | ||
} | ||
else return false; | ||
} | ||
catch (e) { | ||
console.error(e); | ||
return false; | ||
} | ||
} | ||
message.listen('cursor', function(selection) { | ||
if (selection.clientId == clientId) return; | ||
if (selection.start != null && selection.end != null) | ||
updateCursor(selection); | ||
else | ||
removeCursor(selection.clientId); | ||
}); | ||
/* | ||
crdt.getPosition(function(data)) | ||
crdt.getPosition(function(data){console.log(" EScuchando ahora ",data)}) | ||
*/ | ||
getPosition(callback){ | ||
if(typeof miFuncion === 'function') | ||
this.changeListenAwereness(callback); | ||
else | ||
console.error('Callback should be a function'); | ||
} | ||
function updateCursor(selection) { | ||
const cursorUpdate = new CustomEvent('updateCursor', { | ||
detail: { selection }, | ||
}); | ||
window.dispatchEvent(cursorUpdate); | ||
} | ||
window.Y = Y; | ||
const cDoc = new Y.Doc(); | ||
let org = config.organization_Id; | ||
let CoCreateCrdt = new CoCreateCRDTClass(org, cDoc); | ||
function removeCursor(clientId) { | ||
const cursorRemove = new CustomEvent('removeCursor', { | ||
detail: { clientId }, | ||
}); | ||
window.dispatchEvent(cursorRemove); | ||
} | ||
export default CoCreateCrdt; | ||
// function deleteDoc(docName) { | ||
// if (this.docs[docName]) { | ||
// delete this.docs[docName]; | ||
// } | ||
// } | ||
// function destroyObserver(docName, typeName) { | ||
// this.docs[docName].doc.getText(typeName).unobserve((event) => {}); | ||
// this.docs[docName].socket.awareness.off('change', this._awarenessListener); | ||
// } | ||
function generateDocName(info) { | ||
let docName = { collection: info.collection, document_id: info.document_id }; | ||
return `${info.collection}${info.document_id}`; | ||
// return btoa(JSON.stringify(docName)); | ||
} | ||
action.init({ | ||
action: "undo", | ||
endEvent: "undo", | ||
callback: (btn, data) => { | ||
undoChange(btn); | ||
} | ||
}); | ||
action.init({ | ||
action: "redo", | ||
endEvent: "redo", | ||
callback: (btn, data) => { | ||
redoChange(btn); | ||
} | ||
}); | ||
export default { init, getText, insertText, deleteText, replaceText, getPosition, sendPosition }; |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
4
13
0
95882
14
520
1
+ Added@cocreate/action@^1.3.4
- Removedy-indexeddb@^9.0.6
- Removedy-websocket@^1.3.16
- Removedyjs@^13.5.11
- Removedabstract-leveldown@6.2.3(transitive)
- Removedasync-limiter@1.0.1(transitive)
- Removedbase64-js@1.5.1(transitive)
- Removedbuffer@5.7.1(transitive)
- Removeddeferred-leveldown@5.3.0(transitive)
- Removedencoding-down@6.3.0(transitive)
- Removederrno@0.1.8(transitive)
- Removedieee754@1.2.1(transitive)
- Removedimmediate@3.3.0(transitive)
- Removedinherits@2.0.4(transitive)
- Removedisomorphic.js@0.2.5(transitive)
- Removedlevel@6.0.1(transitive)
- Removedlevel-codec@9.0.2(transitive)
- Removedlevel-concat-iterator@2.0.1(transitive)
- Removedlevel-errors@2.0.1(transitive)
- Removedlevel-iterator-stream@4.0.2(transitive)
- Removedlevel-js@5.0.2(transitive)
- Removedlevel-packager@5.1.1(transitive)
- Removedlevel-supports@1.0.1(transitive)
- Removedleveldown@5.6.0(transitive)
- Removedlevelup@4.4.0(transitive)
- Removedlib0@0.2.99(transitive)
- Removedlodash.debounce@4.0.8(transitive)
- Removedltgt@2.2.1(transitive)
- Removednapi-macros@2.0.0(transitive)
- Removednode-gyp-build@4.1.1(transitive)
- Removedprr@1.0.1(transitive)
- Removedreadable-stream@3.6.2(transitive)
- Removedsafe-buffer@5.2.1(transitive)
- Removedstring_decoder@1.3.0(transitive)
- Removedutil-deprecate@1.0.2(transitive)
- Removedws@6.2.3(transitive)
- Removedxtend@4.0.2(transitive)
- Removedy-indexeddb@9.0.12(transitive)
- Removedy-leveldb@0.1.2(transitive)
- Removedy-protocols@1.0.6(transitive)
- Removedy-websocket@1.5.4(transitive)
- Removedyjs@13.6.20(transitive)