Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

gulf

Package Overview
Dependencies
Maintainers
1
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gulf - npm Package Compare versions

Comparing version 0.2.0 to 0.3.0

LICENSE.txt

6

component.json

@@ -5,6 +5,10 @@ {

"description": "OT managing library",
"version": "0.2.0",
"version": "0.3.0",
"dependencies": {
"marcelklehr/browser-stream": "*"
, "timoxley/next-tick": "*"
},
"devDependencies": {
"marcelklehr/ottypes": "*"
},
"license": "MIT",

@@ -11,0 +15,0 @@ "main": "index.js",

@@ -80,2 +80,5 @@ var Link = require('./Link')

link.on('link:requestInit', function() {
if(null === this.content) {
return // I don't know either!
}
link.send('init', {content: this.content, initialEdit: this.history.latest().pack()})

@@ -119,2 +122,7 @@ }.bind(this))

this.history.pushEdit(initialEdit)
// I got an init, so my slaves get one, too
this.slaves.forEach(function(slave) {
slave.send('init', {content: this.content, initialEdit: this.history.latest().pack()})
}.bind(this))
}

@@ -129,8 +137,9 @@

Document.prototype.receiveEdit = function(edit, fromLink) {
edit = Edit.unpack(edit, this.ottype)
if (!this.master || fromLink === this.master) {
// Edit comes from master, or even better: we are master, yea baby!
this.dispatchEdit(Edit.unpack(edit, this.ottype), fromLink)
this.dispatchEdit(edit, fromLink)
}else {
// check with master first
this.master.sendEdit(edit, function onack() {
this.master.sendEdit(edit, function onack(err, edit) {
this.dispatchEdit(edit, fromLink)

@@ -183,2 +192,6 @@ }.bind(this))

// so we don't need to transform anything coming from master.
// add to history + set id
this.history.pushEdit(edit)
return edit

@@ -194,3 +207,3 @@ }else {

// add to history
// add to history + set id
this.history.pushEdit(edit)

@@ -217,5 +230,6 @@

if(link === fromLink) return
if(link === this.master) return
link.sendEdit(edit)
})
}.bind(this))
}

14

lib/Edit.js

@@ -17,5 +17,3 @@ function Edit(ottype) {

if(json.cs) {
edit.changeset = ottype.deserialize?
ottype.deserialize(json.cs)
: JSON.parse(json.cs)
edit.changeset = json.cs
}

@@ -31,3 +29,2 @@ edit.parent = json.parent

var edit = new Edit(ottype)
edit.id = randString()
return edit

@@ -41,3 +38,2 @@ }

var edit = new Edit(ottype)
edit.id = randString()
edit.changeset = cs

@@ -73,2 +69,6 @@ return edit

Edit.prototype.merge = function(edit) {
return Edit.newFromChangeset(this.ottype.compose(this.changeset, edit.changeset), this.ottype)
}
Edit.prototype.pack = function() {

@@ -80,5 +80,3 @@ var o = {

if(this.changeset) {
o.cs = this.ottype.serialize?
this.ottype.serialize(this.changeset)
: JSON.stringify(this.changeset)
o.cs = this.changeset
}

@@ -85,0 +83,0 @@ return JSON.stringify(o)

@@ -37,4 +37,18 @@ var Document = require('./Document')

this.master.sendEdit(edit, function onack() { // XXX: We could also merge into the queue
this.applyEdit(edit)
// Merge into the queue for increased collab speed
if(this.master.queue.length == 1) {
var parent = this.master.queue[0].parent
, callback =this.master.queue[0].callback
this.master.queue[0] = this.master.queue[0].merge(edit)
this.master.queue[0].callback = callback
this.master.queue[0].parent = parent
return
}
this.master.sendEdit(edit, function onack(err, edit) {
// Update queue
this.master.queue.forEach(function(queuedEdit) {
queuedEdit.parent = edit.id
})
this.applyEdit(edit, true)
//this.distributeEdit(edit) // Unnecessary round trip

@@ -58,3 +72,3 @@ this.history.pushEdit(edit)

incoming.transformAgainst(this.master.sentEdit)
this.master.sentEdit.follow(incomingOriginal)
this.master.sentEdit.follow(incomingOriginal) // Why!?
}

@@ -81,2 +95,5 @@

// add edit to history
this.history.pushEdit(incoming)
return incoming

@@ -86,3 +103,3 @@ }

// overrides Document#applyEdit
EditableDocument.prototype.applyEdit = function(edit) {
EditableDocument.prototype.applyEdit = function(edit, ownEdit) {
// apply changes

@@ -92,3 +109,3 @@ console.log('EditableDocument: apply edit', edit)

this.content = edit.apply(this.content)
this._change(this.content, edit.changeset)
if(!ownEdit) this._change(this.content, edit.changeset)
}catch(e) {

@@ -95,0 +112,0 @@ throw new Error('Applying edit "'+edit.id+'" failed: '+e.message)

@@ -18,3 +18,5 @@ // Stores revisions that are synced with the server

History.prototype.pushEdit = function(edit) {
if(this.remembers(edit.id)) return
// Only Master Document may set ids
if(!edit.id) edit.id = ++this.idCounter
if(this.latest() && this.latest().id != edit.parent) throw new Error('This edit\'s parent is not the latest edit in history: '+JSON.stringify(edit), console.log(this.history))

@@ -28,2 +30,3 @@ this.history.push(edit.id)

this.history = []
this.idCounter = 0
}

@@ -30,0 +33,0 @@

var Duplex = require('stream').Duplex
var nextTick = 'undefined' == typeof setImmediate? require('next-tick') : setImmediate
/**

@@ -14,3 +17,3 @@ * This is a Link

this.on('error', function(er) {
console.warn('Error in link', er.stack || er)
console.warn('Error in link', 'undefined'==typeof process? er : er.stack || er)
this.end()

@@ -50,3 +53,3 @@ // i dunno what to do here...

Link.prototype.sendEdit = function(edit, cb) {
if(cb) this.callbacks[edit.id] = cb
if(cb) edit.callback = cb

@@ -58,3 +61,5 @@ if(this.queue.length || this.sentEdit) {

this.sentEdit = edit
this.send('edit', edit.pack())
nextTick(function() {
this.send('edit', edit.pack())
}.bind(this))
}

@@ -69,3 +74,3 @@ }

this.sentEdit = this.queue.unshift()
this.sentEdit = this.queue.shift()
this.send('edit', this.sentEdit.pack())

@@ -80,10 +85,22 @@ }

if(args[0] == 'ack') {
var id = args[1]
if(args[1] != this.sentEdit.id) return cb() // XXX: Well that'd be embarrassing, what do we do here?
if(this.sentEdit && this.sentEdit.callback) {
// Callback
this.sentEdit.id = id
// The nextTick shim for browsers doesn't seem to enforce the call order
// (_read is called below and they must be in that order), so we call directly
//nextTick(this.sentEdit.callback.bind(null, null, this.sentEdit))
try {
this.sentEdit.callback(null, this.sentEdit)
}catch(e) {
this.emit('error', e)
}
delete this.sentEdit.callback
}
this.sentEdit = null
this.sentEdit = null
if(this.callbacks[args[1]]) {
setImmediate(this.callbacks[args[1]]) // XXX: Use a shim here...
delete this.callbacks[args[1]]
}
nextTick(function() {
this._read(0)
}.bind(this))
}

@@ -90,0 +107,0 @@

{
"name": "gulf",
"version": "0.2.0",
"version": "0.3.0",
"description": "Sync anything!",

@@ -5,0 +5,0 @@ "repository": {

# Gulf [![Build Status](https://travis-ci.org/marcelklehr/gulf.png)](https://travis-ci.org/marcelklehr/gulf)
The Gulf stream will sync your documents. Anywhere in the world, in node.js and the browser!
OT is too hard on you? The Gulf stream will sync your documents in real-time. Anywhere in the world, in node.js and the browser!
![Gulf stream (Public domain)](https://upload.wikimedia.org/wikipedia/commons/1/19/Golfstrom.jpg)
### How?
You choose an [OT](https://en.wikipedia.org/wiki/Operational_transformation) [type](https://github.com/marcelklehr/gulf#operational-transform-bling) algorithm, gulf will sync your documents.
## Show me!

@@ -10,13 +16,7 @@

*/
var gulf = require('gulf')
, net = require('net')
, textOT = require('ottypes').text
var textOT = require('ottypes').text
// Create a new master document
var doc = gulf.Document.create(textOT, 'abc')
doc.content // 'abc'
// Set up a server

@@ -39,13 +39,7 @@ net.createServer(function(socket) {

*/
var gulf = require('gulf')
, net = require('net')
, textOT = require('ottypes').text
var textOT = require('ottypes').text
// Create a new slave document (empty by default)
var doc = new gulf.Document(textOT)
doc.content // null -- it's really empty.
// Connect to alice's server

@@ -52,0 +46,0 @@ net.connect(7453, function(socket) {

@@ -7,6 +7,7 @@ /* global xdescribe, describe, it, xit */

try {
gulf = require('gulf')
}catch(e) {
console.log(e)
gulf = require('../')
expect = require('expect.js')
}catch(e) {
gulf = require('gulf')
}

@@ -35,3 +36,2 @@

var initialContent = 'abc'
, cs = [3, 'd']
var docA = gulf.Document.create(ottype, initialContent)

@@ -49,6 +49,6 @@ , docB = new gulf.EditableDocument(ottype)

linkA.on('link:edit', console.log.bind(console, 'edit in linkA'))
/*linkA.on('link:edit', console.log.bind(console, 'edit in linkA'))
linkA.on('link:ack', console.log.bind(console, 'ack in linkA'))
linkB.on('link:edit', console.log.bind(console, 'edit in linkB'))
linkB.on('link:ack', console.log.bind(console, 'ack in linkB'))
linkB.on('link:ack', console.log.bind(console, 'ack in linkB'))*/

@@ -69,3 +69,4 @@ it('should adopt the current document state correctly', function(done) {

it('should replicate insertions across links', function(done) {
docB.update(cs)
content = 'abcd' // We mimick some edit->cs algo here
docB.update([3, 'd']) // *bling*

@@ -77,5 +78,19 @@ setTimeout(function() {

done()
}, 10)
}, 100)
})
it('should replicate multiple insertions across links', function(done) {
content = 'abcdefg' // We mimick some edit->cs algo here
docB.update([4, 'e']) // *bling*
docB.update([5, 'f']) // *bling*
docB.update([6, 'g']) // *bling*
setTimeout(function() {
console.log('DocB:', docB.content, 'DocA', docA.content)
expect(docB.content).to.eql(docA.content)
expect(content).to.eql(docA.content)
done()
}, 100)
})
})
})

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc