switched to *standard* coding style
This commit is contained in:
247
src/Connector.js
247
src/Connector.js
@@ -1,192 +1,191 @@
|
||||
|
||||
class AbstractConnector { //eslint-disable-line no-unused-vars
|
||||
class AbstractConnector { // eslint-disable-line no-unused-vars
|
||||
/*
|
||||
opts
|
||||
.role : String Role of this client ("master" or "slave")
|
||||
.userId : String that uniquely defines the user.
|
||||
*/
|
||||
constructor (y, opts) {
|
||||
this.y = y;
|
||||
if (opts == null){
|
||||
opts = {};
|
||||
this.y = y
|
||||
if (opts == null) {
|
||||
opts = {}
|
||||
}
|
||||
if (opts.role == null || opts.role === "master") {
|
||||
this.role = "master";
|
||||
} else if (opts.role === "slave") {
|
||||
this.role = "slave";
|
||||
if (opts.role == null || opts.role === 'master') {
|
||||
this.role = 'master'
|
||||
} else if (opts.role === 'slave') {
|
||||
this.role = 'slave'
|
||||
} else {
|
||||
throw new Error("Role must be either 'master' or 'slave'!");
|
||||
throw new Error("Role must be either 'master' or 'slave'!")
|
||||
}
|
||||
this.role = opts.role;
|
||||
this.connections = {};
|
||||
this.userEventListeners = [];
|
||||
this.whenSyncedListeners = [];
|
||||
this.currentSyncTarget = null;
|
||||
this.syncingClients = [];
|
||||
this.forwardToSyncingClients = (opts.forwardToSyncingClients === false) ? false : true;
|
||||
this.debug = opts.debug ? true : false;
|
||||
this.broadcastedHB = false;
|
||||
this.role = opts.role
|
||||
this.connections = {}
|
||||
this.userEventListeners = []
|
||||
this.whenSyncedListeners = []
|
||||
this.currentSyncTarget = null
|
||||
this.syncingClients = []
|
||||
this.forwardToSyncingClients = opts.forwardToSyncingClients !== false
|
||||
this.debug = opts.debug === true
|
||||
this.broadcastedHB = false
|
||||
}
|
||||
setUserId (userId) {
|
||||
this.userId = userId;
|
||||
this.y.db.setUserId(userId);
|
||||
this.userId = userId
|
||||
this.y.db.setUserId(userId)
|
||||
}
|
||||
onUserEvent (f) {
|
||||
this.userEventListeners.push(f);
|
||||
this.userEventListeners.push(f)
|
||||
}
|
||||
userLeft (user : string) {
|
||||
delete this.connections[user];
|
||||
if (user === this.currentSyncTarget){
|
||||
this.currentSyncTarget = null;
|
||||
this.findNextSyncTarget();
|
||||
userLeft (user) {
|
||||
delete this.connections[user]
|
||||
if (user === this.currentSyncTarget) {
|
||||
this.currentSyncTarget = null
|
||||
this.findNextSyncTarget()
|
||||
}
|
||||
for (var f of this.userEventListeners){
|
||||
for (var f of this.userEventListeners) {
|
||||
f({
|
||||
action: "userLeft",
|
||||
action: 'userLeft',
|
||||
user: user
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
userJoined (user, role) {
|
||||
if(role == null){
|
||||
throw new Error("You must specify the role of the joined user!");
|
||||
if (role == null) {
|
||||
throw new Error('You must specify the role of the joined user!')
|
||||
}
|
||||
if (this.connections[user] != null) {
|
||||
throw new Error("This user already joined!");
|
||||
throw new Error('This user already joined!')
|
||||
}
|
||||
this.connections[user] = {
|
||||
isSynced: false,
|
||||
role: role
|
||||
};
|
||||
}
|
||||
for (var f of this.userEventListeners) {
|
||||
f({
|
||||
action: "userJoined",
|
||||
action: 'userJoined',
|
||||
user: user,
|
||||
role: role
|
||||
});
|
||||
})
|
||||
}
|
||||
if (this.currentSyncTarget == null) {
|
||||
this.findNextSyncTarget();
|
||||
this.findNextSyncTarget()
|
||||
}
|
||||
}
|
||||
// Execute a function _when_ we are connected.
|
||||
// If not connected, wait until connected
|
||||
whenSynced (f) {
|
||||
if (this.isSynced === true) {
|
||||
f();
|
||||
f()
|
||||
} else {
|
||||
this.whenSyncedListeners.push(f);
|
||||
this.whenSyncedListeners.push(f)
|
||||
}
|
||||
}
|
||||
// returns false, if there is no sync target
|
||||
// true otherwise
|
||||
findNextSyncTarget () {
|
||||
if (this.currentSyncTarget != null) {
|
||||
return; // "The current sync has not finished!"
|
||||
return // "The current sync has not finished!"
|
||||
}
|
||||
|
||||
var syncUser = null;
|
||||
var syncUser = null
|
||||
for (var uid in this.connections) {
|
||||
if (!this.connections[uid].isSynced) {
|
||||
syncUser = uid;
|
||||
break;
|
||||
syncUser = uid
|
||||
break
|
||||
}
|
||||
}
|
||||
if (syncUser != null){
|
||||
var conn = this;
|
||||
this.currentSyncTarget = syncUser;
|
||||
this.y.db.requestTransaction(function*(){
|
||||
if (syncUser != null) {
|
||||
var conn = this
|
||||
this.currentSyncTarget = syncUser
|
||||
this.y.db.requestTransaction(function *() {
|
||||
conn.send(syncUser, {
|
||||
type: "sync step 1",
|
||||
type: 'sync step 1',
|
||||
stateVector: yield* this.getStateVector()
|
||||
});
|
||||
});
|
||||
})
|
||||
})
|
||||
}
|
||||
// set the state to synced!
|
||||
if (!this.isSynced) {
|
||||
this.isSynced = true;
|
||||
this.isSynced = true
|
||||
for (var f of this.whenSyncedListeners) {
|
||||
f();
|
||||
f()
|
||||
}
|
||||
this.whenSyncedListeners = null;
|
||||
this.whenSyncedListeners = null
|
||||
}
|
||||
}
|
||||
send (uid, message) {
|
||||
if (this.debug) {
|
||||
console.log(`me -> ${uid}: ${message.type}`);//eslint-disable-line
|
||||
console.dir(m); //eslint-disable-line
|
||||
console.log(`me -> ${uid}: ${message.type}`);// eslint-disable-line
|
||||
console.dir(m); // eslint-disable-line
|
||||
}
|
||||
super(uid, message);
|
||||
super(uid, message)
|
||||
}
|
||||
// You received a raw message, and you know that it is intended for to Yjs. Then call this function.
|
||||
receiveMessage (sender, m){
|
||||
receiveMessage (sender, m) {
|
||||
if (sender === this.userId) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
if (this.debug) {
|
||||
console.log(`${sender} -> me: ${m.type}`);//eslint-disable-line
|
||||
console.dir(m); //eslint-disable-line
|
||||
console.log(`${sender} -> me: ${m.type}`);// eslint-disable-line
|
||||
console.dir(m); // eslint-disable-line
|
||||
}
|
||||
if (m.type === "sync step 1") {
|
||||
if (m.type === 'sync step 1') {
|
||||
// TODO: make transaction, stream the ops
|
||||
let conn = this;
|
||||
this.y.db.requestTransaction(function*(){
|
||||
var ops = yield* this.getOperations(m.stateVector);
|
||||
var sv = yield* this.getStateVector();
|
||||
let conn = this
|
||||
this.y.db.requestTransaction(function *() {
|
||||
var ops = yield* this.getOperations(m.stateVector)
|
||||
var sv = yield* this.getStateVector()
|
||||
conn.send(sender, {
|
||||
type: "sync step 2",
|
||||
type: 'sync step 2',
|
||||
os: ops,
|
||||
stateVector: sv
|
||||
});
|
||||
})
|
||||
if (this.forwardToSyncingClients) {
|
||||
conn.syncingClients.push(sender);
|
||||
setTimeout(function(){
|
||||
conn.syncingClients = conn.syncingClients.filter(function(cli){
|
||||
return cli !== sender;
|
||||
});
|
||||
conn.syncingClients.push(sender)
|
||||
setTimeout(function () {
|
||||
conn.syncingClients = conn.syncingClients.filter(function (cli) {
|
||||
return cli !== sender
|
||||
})
|
||||
conn.send(sender, {
|
||||
type: "sync done"
|
||||
});
|
||||
}, conn.syncingClientDuration);
|
||||
type: 'sync done'
|
||||
})
|
||||
}, conn.syncingClientDuration)
|
||||
} else {
|
||||
conn.send(sender, {
|
||||
type: "sync done"
|
||||
});
|
||||
type: 'sync done'
|
||||
})
|
||||
}
|
||||
});
|
||||
} else if (m.type === "sync step 2") {
|
||||
this.y.db.apply(m.os);
|
||||
let conn = this;
|
||||
var broadcastHB = !this.broadcastedHB;
|
||||
this.broadcastedHB = true;
|
||||
this.y.db.requestTransaction(function*(){
|
||||
var ops = yield* this.getOperations(m.stateVector);
|
||||
})
|
||||
} else if (m.type === 'sync step 2') {
|
||||
this.y.db.apply(m.os)
|
||||
let conn = this
|
||||
var broadcastHB = !this.broadcastedHB
|
||||
this.broadcastedHB = true
|
||||
this.y.db.requestTransaction(function *() {
|
||||
var ops = yield* this.getOperations(m.stateVector)
|
||||
if (ops.length > 0) {
|
||||
m = {
|
||||
type: "update",
|
||||
type: 'update',
|
||||
ops: ops
|
||||
};
|
||||
}
|
||||
if (!broadcastHB) {
|
||||
conn.send(sender, m);
|
||||
conn.send(sender, m)
|
||||
} else {
|
||||
// broadcast only once!
|
||||
conn.broadcast(m);
|
||||
conn.broadcast(m)
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (m.type === "sync done") {
|
||||
this.connections[sender].isSynced = true;
|
||||
})
|
||||
} else if (m.type === 'sync done') {
|
||||
this.connections[sender].isSynced = true
|
||||
if (sender === this.currentSyncTarget) {
|
||||
this.currentSyncTarget = null;
|
||||
this.findNextSyncTarget();
|
||||
this.currentSyncTarget = null
|
||||
this.findNextSyncTarget()
|
||||
}
|
||||
} else if (m.type === "update") {
|
||||
} else if (m.type === 'update') {
|
||||
if (this.forwardToSyncingClients) {
|
||||
for (var client of this.syncingClients) {
|
||||
this.send(client, m);
|
||||
this.send(client, m)
|
||||
}
|
||||
}
|
||||
this.y.db.apply(m.ops);
|
||||
this.y.db.apply(m.ops)
|
||||
}
|
||||
}
|
||||
// Currently, the HB encodes operations as JSON. For the moment I want to keep it
|
||||
@@ -202,36 +201,36 @@ class AbstractConnector { //eslint-disable-line no-unused-vars
|
||||
// expects an ltx (less than xml) object
|
||||
parseMessageFromXml (m) {
|
||||
function parseArray (node) {
|
||||
for (var n of node.children){
|
||||
if (n.getAttribute("isArray") === "true") {
|
||||
return parseArray(n);
|
||||
for (var n of node.children) {
|
||||
if (n.getAttribute('isArray') === 'true') {
|
||||
return parseArray(n)
|
||||
} else {
|
||||
return parseObject(n);
|
||||
return parseObject(n)
|
||||
}
|
||||
}
|
||||
}
|
||||
function parseObject (node) {
|
||||
var json = {};
|
||||
var json = {}
|
||||
for (var attrName in node.attrs) {
|
||||
var value = node.attrs[attrName];
|
||||
var int = parseInt(value);
|
||||
if (isNaN(int) || ("" + int) !== value){
|
||||
json[attrName] = value;
|
||||
var value = node.attrs[attrName]
|
||||
var int = parseInt(value, 10)
|
||||
if (isNaN(int) || ('' + int) !== value) {
|
||||
json[attrName] = value
|
||||
} else {
|
||||
json[attrName] = int;
|
||||
json[attrName] = int
|
||||
}
|
||||
}
|
||||
for (var n in node.children){
|
||||
var name = n.name;
|
||||
if (n.getAttribute("isArray") === "true") {
|
||||
json[name] = parseArray(n);
|
||||
for (var n in node.children) {
|
||||
var name = n.name
|
||||
if (n.getAttribute('isArray') === 'true') {
|
||||
json[name] = parseArray(n)
|
||||
} else {
|
||||
json[name] = parseObject(n);
|
||||
json[name] = parseObject(n)
|
||||
}
|
||||
}
|
||||
return json;
|
||||
return json
|
||||
}
|
||||
parseObject(m);
|
||||
parseObject(m)
|
||||
}
|
||||
// encode message in xml
|
||||
// we use string because Strophe only accepts an "xml-string"..
|
||||
@@ -245,34 +244,34 @@ class AbstractConnector { //eslint-disable-line no-unused-vars
|
||||
// attributes is optional
|
||||
function encodeObject (m, json) {
|
||||
for (var name in json) {
|
||||
var value = json[name];
|
||||
var value = json[name]
|
||||
if (name == null) {
|
||||
// nop
|
||||
} else if (value.constructor === Object) {
|
||||
encodeObject(m.c(name), value);
|
||||
encodeObject(m.c(name), value)
|
||||
} else if (value.constructor === Array) {
|
||||
encodeArray(m.c(name), value);
|
||||
encodeArray(m.c(name), value)
|
||||
} else {
|
||||
m.setAttribute(name, value);
|
||||
m.setAttribute(name, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
function encodeArray (m, array) {
|
||||
m.setAttribute("isArray", "true");
|
||||
m.setAttribute('isArray', 'true')
|
||||
for (var e of array) {
|
||||
if (e.constructor === Object) {
|
||||
encodeObject(m.c("array-element"), e);
|
||||
encodeObject(m.c('array-element'), e)
|
||||
} else {
|
||||
encodeArray(m.c("array-element"), e);
|
||||
encodeArray(m.c('array-element'), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (obj.constructor === Object) {
|
||||
encodeObject(msg.c("y", { xmlns: "http://y.ninja/connector-stanza" }), obj);
|
||||
encodeObject(msg.c('y', { xmlns: 'http://y.ninja/connector-stanza' }), obj)
|
||||
} else if (obj.constructor === Array) {
|
||||
encodeArray(msg.c("y", { xmlns: "http://y.ninja/connector-stanza" }), obj);
|
||||
encodeArray(msg.c('y', { xmlns: 'http://y.ninja/connector-stanza' }), obj)
|
||||
} else {
|
||||
throw new Error("I can't encode this json!");
|
||||
throw new Error("I can't encode this json!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user