Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e1108d4007 | ||
|
|
c00dee819f | ||
|
|
92b9cb8143 | ||
|
|
5dad1ed410 | ||
|
|
b613630cef | ||
|
|
afa05b62a1 | ||
|
|
957d650f81 | ||
|
|
9769968c1c | ||
|
|
1e30a877e6 | ||
|
|
549ab76b42 |
@@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style type="text/css" media="screen">
|
<style type="text/css" media="screen">
|
||||||
#ace {
|
#aceContainer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="ace"></div>
|
<div id="aceContainer"></div>
|
||||||
<script src="../bower_components/yjs/y.es6"></script>
|
<script src="../bower_components/yjs/y.es6"></script>
|
||||||
<script src="../bower_components/ace-builds/src/ace.js"></script>
|
<script src="../bower_components/ace-builds/src/ace.js"></script>
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Y({
|
|||||||
window.yAce = y
|
window.yAce = y
|
||||||
|
|
||||||
// bind the textarea to a shared text element
|
// bind the textarea to a shared text element
|
||||||
var editor = ace.edit('ace')
|
var editor = ace.edit('aceContainer')
|
||||||
editor.setTheme('ace/theme/chrome')
|
editor.setTheme('ace/theme/chrome')
|
||||||
editor.getSession().setMode('ace/mode/javascript')
|
editor.getSession().setMode('ace/mode/javascript')
|
||||||
|
|
||||||
|
|||||||
31
Examples/WebWorker/index.html
Normal file
31
Examples/WebWorker/index.html
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- quill does not include dist files! We are using the hosted version instead -->
|
||||||
|
<!--link rel="stylesheet" href="../bower_components/quill/dist/quill.snow.css" /-->
|
||||||
|
<link href="https://cdn.quilljs.com/1.0.4/quill.snow.css" rel="stylesheet">
|
||||||
|
<link href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css" rel="stylesheet">
|
||||||
|
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/monokai-sublime.min.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
#quill-container {
|
||||||
|
border: 1px solid gray;
|
||||||
|
box-shadow: 0px 0px 10px gray;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="quill-container">
|
||||||
|
<div id="quill">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.js" type="text/javascript"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/highlight.min.js" type="text/javascript"></script>
|
||||||
|
<script src="https://cdn.quilljs.com/1.0.4/quill.js"></script>
|
||||||
|
<!-- quill does not include dist files! We are using the hosted version instead (see above)
|
||||||
|
<script src="../bower_components/quill/dist/quill.js"></script>
|
||||||
|
-->
|
||||||
|
<script src="../bower_components/yjs/y.es6"></script>
|
||||||
|
<script src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
39
Examples/WebWorker/index.js
Normal file
39
Examples/WebWorker/index.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* global Y, Quill */
|
||||||
|
|
||||||
|
// initialize a shared object. This function call returns a promise!
|
||||||
|
Y({
|
||||||
|
db: {
|
||||||
|
name: 'memory'
|
||||||
|
},
|
||||||
|
connector: {
|
||||||
|
name: 'webworker',
|
||||||
|
url: '../bower_components/y-webworker/yjs-webworker.js',
|
||||||
|
room: 'WebWorkerExample2'
|
||||||
|
},
|
||||||
|
sourceDir: '/bower_components',
|
||||||
|
share: {
|
||||||
|
richtext: 'Richtext' // y.share.richtext is of type Y.Richtext
|
||||||
|
}
|
||||||
|
}).then(function (y) {
|
||||||
|
window.yQuill = y
|
||||||
|
|
||||||
|
// create quill element
|
||||||
|
window.quill = new Quill('#quill', {
|
||||||
|
modules: {
|
||||||
|
formula: true,
|
||||||
|
syntax: true,
|
||||||
|
toolbar: [
|
||||||
|
[{ size: ['small', false, 'large', 'huge'] }],
|
||||||
|
['bold', 'italic', 'underline'],
|
||||||
|
[{ color: [] }, { background: [] }], // Snow theme fills in values
|
||||||
|
[{ script: 'sub' }, { script: 'super' }],
|
||||||
|
['link', 'image'],
|
||||||
|
['link', 'code-block'],
|
||||||
|
[{list: 'ordered' }]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
theme: 'snow'
|
||||||
|
})
|
||||||
|
// bind quill to richtext type
|
||||||
|
y.share.richtext.bind(window.quill)
|
||||||
|
})
|
||||||
16
README.md
16
README.md
@@ -41,6 +41,12 @@ Connectors, Databases, and Types are available as modules that extend Yjs. Here
|
|||||||
|[text](https://github.com/y-js/y-text) | Collaborate on text. Supports two way binding to the [Ace Editor](https://ace.c9.io), textareas, input elements, and HTML elements (e.g. <*h1*>, or <*p*>) |
|
|[text](https://github.com/y-js/y-text) | Collaborate on text. Supports two way binding to the [Ace Editor](https://ace.c9.io), textareas, input elements, and HTML elements (e.g. <*h1*>, or <*p*>) |
|
||||||
|[richtext](https://github.com/y-js/y-richtext) | Collaborate on rich text. Supports two way binding to the [Quill Rich Text Editor](http://quilljs.com/)|
|
|[richtext](https://github.com/y-js/y-richtext) | Collaborate on rich text. Supports two way binding to the [Quill Rich Text Editor](http://quilljs.com/)|
|
||||||
|
|
||||||
|
##### Other
|
||||||
|
|
||||||
|
| Name | Description |
|
||||||
|
|-----------|-------------------|
|
||||||
|
|[y-element](http://y-js.org/y-element/) | Yjs Polymer Element |
|
||||||
|
|
||||||
## Use it!
|
## Use it!
|
||||||
Install Yjs, and its modules with [bower](http://bower.io/), or [npm](https://www.npmjs.org/package/yjs).
|
Install Yjs, and its modules with [bower](http://bower.io/), or [npm](https://www.npmjs.org/package/yjs).
|
||||||
|
|
||||||
@@ -145,6 +151,7 @@ Report _any_ issues to the [Github issue page](https://github.com/y-js/yjs/issue
|
|||||||
* All our connectors implement a `room` property. Clients that specify the same room share the same data.
|
* All our connectors implement a `room` property. Clients that specify the same room share the same data.
|
||||||
* All of our connectors specify an `url` property that defines the connection endpoint of the used connector.
|
* All of our connectors specify an `url` property that defines the connection endpoint of the used connector.
|
||||||
* All of our connectors also have a default connection endpoint that you can use for development.
|
* All of our connectors also have a default connection endpoint that you can use for development.
|
||||||
|
* Set `options.connector.generateUserId = true` in order to genenerate a userid, instead of receiving one from the server. This way the `Y(..)` is immediately going to be resolved, without waiting for any confirmation from the server. Use with caution.
|
||||||
* Have a look at the used connector repository to see all available options.
|
* Have a look at the used connector repository to see all available options.
|
||||||
* options.sourceDir (browser only)
|
* options.sourceDir (browser only)
|
||||||
* Path where all y-* modules are stored
|
* Path where all y-* modules are stored
|
||||||
@@ -199,13 +206,19 @@ The promise returns an instance of Y. We denote it with a lower case `y`.
|
|||||||
* y.connector.reconnect()
|
* y.connector.reconnect()
|
||||||
* Try to reconnect to the other instances (needs to be supported by the connector)
|
* Try to reconnect to the other instances (needs to be supported by the connector)
|
||||||
* Not supported by y-xmpp
|
* Not supported by y-xmpp
|
||||||
* y.destroy()
|
* y.close()
|
||||||
* Destroy this object.
|
* Destroy this object.
|
||||||
* Destroys all types (they will throw weird errors if you still use them)
|
* Destroys all types (they will throw weird errors if you still use them)
|
||||||
* Disconnects from the other instances (via connector)
|
* Disconnects from the other instances (via connector)
|
||||||
|
* Returns a promise
|
||||||
|
* y.destroy()
|
||||||
|
* calls y.close()
|
||||||
* Removes all data from the database
|
* Removes all data from the database
|
||||||
|
* Returns a promise
|
||||||
* y.db.stopGarbageCollector()
|
* y.db.stopGarbageCollector()
|
||||||
* Stop the garbage collector. Call y.db.garbageCollect() to continue garbage collection
|
* Stop the garbage collector. Call y.db.garbageCollect() to continue garbage collection
|
||||||
|
* y.db.gc :: Boolean
|
||||||
|
* Whether gc is turned on
|
||||||
* y.db.gcTimeout :: Number (defaults to 50000 ms)
|
* y.db.gcTimeout :: Number (defaults to 50000 ms)
|
||||||
* Time interval between two garbage collect cycles
|
* Time interval between two garbage collect cycles
|
||||||
* It is required that all instances exchanged all messages after two garbage collect cycles (after 100000 ms per default)
|
* It is required that all instances exchanged all messages after two garbage collect cycles (after 100000 ms per default)
|
||||||
@@ -261,4 +274,3 @@ I created this framework during my bachelor thesis at the chair of computer scie
|
|||||||
Yjs is licensed under the [MIT License](./LICENSE).
|
Yjs is licensed under the [MIT License](./LICENSE).
|
||||||
|
|
||||||
<yjs@dbis.rwth-aachen.de>
|
<yjs@dbis.rwth-aachen.de>
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "12.1.0",
|
"version": "12.1.5",
|
||||||
"homepage": "y-js.org",
|
"homepage": "y-js.org",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
||||||
|
|||||||
180
y.es6
180
y.es6
@@ -1,4 +1,10 @@
|
|||||||
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
/**
|
||||||
|
* yjs - A framework for real-time p2p shared editing on any data
|
||||||
|
* @version v12.1.4
|
||||||
|
* @link http://y-js.org
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Y = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||||
/* @flow */
|
/* @flow */
|
||||||
'use strict'
|
'use strict'
|
||||||
|
|
||||||
@@ -60,6 +66,18 @@ module.exports = function (Y/* :any */) {
|
|||||||
this.protocolVersion = 11
|
this.protocolVersion = 11
|
||||||
this.authInfo = opts.auth || null
|
this.authInfo = opts.auth || null
|
||||||
this.checkAuth = opts.checkAuth || function () { return Promise.resolve('write') } // default is everyone has write access
|
this.checkAuth = opts.checkAuth || function () { return Promise.resolve('write') } // default is everyone has write access
|
||||||
|
if (opts.generateUserId === true) {
|
||||||
|
this.setUserId(Y.utils.generateGuid())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
resetAuth (auth) {
|
||||||
|
if (this.authInfo !== auth) {
|
||||||
|
this.authInfo = auth
|
||||||
|
this.broadcast({
|
||||||
|
type: 'auth',
|
||||||
|
auth: this.authInfo
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reconnect () {
|
reconnect () {
|
||||||
}
|
}
|
||||||
@@ -145,13 +163,8 @@ module.exports = function (Y/* :any */) {
|
|||||||
this.whenSyncedListeners.push(f)
|
this.whenSyncedListeners.push(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
|
|
||||||
returns false, if there is no sync target
|
|
||||||
true otherwise
|
|
||||||
*/
|
|
||||||
findNextSyncTarget () {
|
findNextSyncTarget () {
|
||||||
if (this.currentSyncTarget != null || this.isSynced) {
|
if (this.currentSyncTarget != null) {
|
||||||
return // "The current sync has not finished!"
|
return // "The current sync has not finished!"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,16 +190,20 @@ module.exports = function (Y/* :any */) {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.y.db.requestTransaction(function *() {
|
if (!conn.isSynced) {
|
||||||
// it is crucial that isSynced is set at the time garbageCollectAfterSync is called
|
this.y.db.requestTransaction(function *() {
|
||||||
conn.isSynced = true
|
if (!conn.isSynced) {
|
||||||
yield* this.garbageCollectAfterSync()
|
// it is crucial that isSynced is set at the time garbageCollectAfterSync is called
|
||||||
// call whensynced listeners
|
conn.isSynced = true
|
||||||
for (var f of conn.whenSyncedListeners) {
|
yield* this.garbageCollectAfterSync()
|
||||||
f()
|
// call whensynced listeners
|
||||||
}
|
for (var f of conn.whenSyncedListeners) {
|
||||||
conn.whenSyncedListeners = []
|
f()
|
||||||
})
|
}
|
||||||
|
conn.whenSyncedListeners = []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
send (uid, message) {
|
send (uid, message) {
|
||||||
@@ -298,7 +315,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
type: 'sync done'
|
type: 'sync done'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
conn._setSyncedWith(sender)
|
|
||||||
})
|
})
|
||||||
} else if (message.type === 'sync step 2' && canWrite(auth)) {
|
} else if (message.type === 'sync step 2' && canWrite(auth)) {
|
||||||
let conn = this
|
let conn = this
|
||||||
@@ -714,12 +730,18 @@ module.exports = function (Y /* :any */) {
|
|||||||
}
|
}
|
||||||
this.gc1 = [] // first stage
|
this.gc1 = [] // first stage
|
||||||
this.gc2 = [] // second stage -> after that, remove the op
|
this.gc2 = [] // second stage -> after that, remove the op
|
||||||
this.gcTimeout = !opts.gcTimeout ? 50000 : opts.gcTimeouts
|
this.gc = opts.gc == null || opts.gc
|
||||||
|
if (this.gc) {
|
||||||
|
this.gcTimeout = !opts.gcTimeout ? 50000 : opts.gcTimeout
|
||||||
|
} else {
|
||||||
|
this.gcTimeout = -1
|
||||||
|
}
|
||||||
|
|
||||||
function garbageCollect () {
|
function garbageCollect () {
|
||||||
return os.whenTransactionsFinished().then(function () {
|
return os.whenTransactionsFinished().then(function () {
|
||||||
if (os.gc1.length > 0 || os.gc2.length > 0) {
|
if (os.gc1.length > 0 || os.gc2.length > 0) {
|
||||||
if (!os.y.isConnected()) {
|
if (!os.y.connector.isSynced) {
|
||||||
console.warn('gc should be empty when disconnected!')
|
console.warn('gc should be empty when not synced!')
|
||||||
}
|
}
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
os.requestTransaction(function * () {
|
os.requestTransaction(function * () {
|
||||||
@@ -788,7 +810,7 @@ module.exports = function (Y /* :any */) {
|
|||||||
clearInterval(this.repairCheckIntervalHandler)
|
clearInterval(this.repairCheckIntervalHandler)
|
||||||
}
|
}
|
||||||
queueGarbageCollector (id) {
|
queueGarbageCollector (id) {
|
||||||
if (this.y.isConnected()) {
|
if (this.y.connector.isSynced && this.gc) {
|
||||||
this.gc1.push(id)
|
this.gc1.push(id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -821,6 +843,8 @@ module.exports = function (Y /* :any */) {
|
|||||||
}
|
}
|
||||||
stopGarbageCollector () {
|
stopGarbageCollector () {
|
||||||
var self = this
|
var self = this
|
||||||
|
this.gc = false
|
||||||
|
this.gcTimeout = -1
|
||||||
return new Promise(function (resolve) {
|
return new Promise(function (resolve) {
|
||||||
self.requestTransaction(function * () {
|
self.requestTransaction(function * () {
|
||||||
var ungc /* :Array<Struct> */ = self.gc1.concat(self.gc2)
|
var ungc /* :Array<Struct> */ = self.gc1.concat(self.gc2)
|
||||||
@@ -843,7 +867,7 @@ module.exports = function (Y /* :any */) {
|
|||||||
TODO: rename this function
|
TODO: rename this function
|
||||||
|
|
||||||
Rulez:
|
Rulez:
|
||||||
* Only gc if this user is online
|
* Only gc if this user is online & gc turned on
|
||||||
* The most left element in a list must not be gc'd.
|
* The most left element in a list must not be gc'd.
|
||||||
=> There is at least one element in the list
|
=> There is at least one element in the list
|
||||||
|
|
||||||
@@ -852,7 +876,9 @@ module.exports = function (Y /* :any */) {
|
|||||||
* addToGarbageCollector (op, left) {
|
* addToGarbageCollector (op, left) {
|
||||||
if (
|
if (
|
||||||
op.gc == null &&
|
op.gc == null &&
|
||||||
op.deleted === true
|
op.deleted === true &&
|
||||||
|
this.store.gc &&
|
||||||
|
this.store.y.connector.isSynced
|
||||||
) {
|
) {
|
||||||
var gc = false
|
var gc = false
|
||||||
if (left != null && left.deleted === true) {
|
if (left != null && left.deleted === true) {
|
||||||
@@ -878,10 +904,7 @@ module.exports = function (Y /* :any */) {
|
|||||||
this.gc2 = this.gc2.filter(filter)
|
this.gc2 = this.gc2.filter(filter)
|
||||||
delete op.gc
|
delete op.gc
|
||||||
}
|
}
|
||||||
* destroy () {
|
destroyTypes () {
|
||||||
clearInterval(this.gcInterval)
|
|
||||||
this.gcInterval = null
|
|
||||||
this.stopRepairCheck()
|
|
||||||
for (var key in this.initializedTypes) {
|
for (var key in this.initializedTypes) {
|
||||||
var type = this.initializedTypes[key]
|
var type = this.initializedTypes[key]
|
||||||
if (type._destroy != null) {
|
if (type._destroy != null) {
|
||||||
@@ -891,6 +914,11 @@ module.exports = function (Y /* :any */) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
* destroy () {
|
||||||
|
clearInterval(this.gcInterval)
|
||||||
|
this.gcInterval = null
|
||||||
|
this.stopRepairCheck()
|
||||||
|
}
|
||||||
setUserId (userId) {
|
setUserId (userId) {
|
||||||
if (!this.userIdPromise.inProgress) {
|
if (!this.userIdPromise.inProgress) {
|
||||||
this.userIdPromise.inProgress = true
|
this.userIdPromise.inProgress = true
|
||||||
@@ -1073,8 +1101,7 @@ module.exports = function (Y /* :any */) {
|
|||||||
*/
|
*/
|
||||||
* operationAdded (transaction, op) {
|
* operationAdded (transaction, op) {
|
||||||
if (op.struct === 'Delete') {
|
if (op.struct === 'Delete') {
|
||||||
var target = yield* transaction.getInsertion(op.target)
|
var type = this.initializedTypes[JSON.stringify(op.targetParent)]
|
||||||
var type = this.initializedTypes[JSON.stringify(target.parent)]
|
|
||||||
if (type != null) {
|
if (type != null) {
|
||||||
yield* type._changed(transaction, op)
|
yield* type._changed(transaction, op)
|
||||||
}
|
}
|
||||||
@@ -1142,10 +1169,8 @@ module.exports = function (Y /* :any */) {
|
|||||||
resolve: resolve,
|
resolve: resolve,
|
||||||
promise: promise
|
promise: promise
|
||||||
}
|
}
|
||||||
return promise
|
|
||||||
} else {
|
|
||||||
return this.transactionsFinished.promise
|
|
||||||
}
|
}
|
||||||
|
return this.transactionsFinished.promise
|
||||||
} else {
|
} else {
|
||||||
return Promise.resolve()
|
return Promise.resolve()
|
||||||
}
|
}
|
||||||
@@ -1261,7 +1286,11 @@ module.exports = function (Y/* :any */) {
|
|||||||
*/
|
*/
|
||||||
Delete: {
|
Delete: {
|
||||||
encode: function (op) {
|
encode: function (op) {
|
||||||
return op
|
return {
|
||||||
|
target: op.target,
|
||||||
|
length: op.length || 0,
|
||||||
|
struct: 'Delete'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
requiredOps: function (op) {
|
requiredOps: function (op) {
|
||||||
return [] // [op.target]
|
return [] // [op.target]
|
||||||
@@ -1496,7 +1525,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try to merge original op.left and op.origin
|
// try to merge original op.left and op.origin
|
||||||
for (let i = 0; i < tryToRemergeLater.length; i++) {
|
for (i = 0; i < tryToRemergeLater.length; i++) {
|
||||||
var m = yield* this.getOperation(tryToRemergeLater[i])
|
var m = yield* this.getOperation(tryToRemergeLater[i])
|
||||||
yield* this.tryCombineWithLeft(m)
|
yield* this.tryCombineWithLeft(m)
|
||||||
}
|
}
|
||||||
@@ -1739,7 +1768,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
send.push(Y.Struct[op.struct].encode(op))
|
send.push(Y.Struct[op.struct].encode(op))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!this.store.y.connector.isDisconnected() && send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)
|
if (this.store.y.connector.isSynced && send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)
|
||||||
// is connected, and this is not going to be send in addOperation
|
// is connected, and this is not going to be send in addOperation
|
||||||
this.store.y.connector.broadcastOps(send)
|
this.store.y.connector.broadcastOps(send)
|
||||||
}
|
}
|
||||||
@@ -1849,7 +1878,8 @@ module.exports = function (Y/* :any */) {
|
|||||||
yield* this.store.operationAdded(this, {
|
yield* this.store.operationAdded(this, {
|
||||||
struct: 'Delete',
|
struct: 'Delete',
|
||||||
target: target.id,
|
target: target.id,
|
||||||
length: targetLength
|
length: targetLength,
|
||||||
|
targetParent: target.parent
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// need to gc in the end!
|
// need to gc in the end!
|
||||||
@@ -2011,6 +2041,9 @@ module.exports = function (Y/* :any */) {
|
|||||||
if (this.store.gc1.length > 0 || this.store.gc2.length > 0) {
|
if (this.store.gc1.length > 0 || this.store.gc2.length > 0) {
|
||||||
console.warn('gc should be empty after sync')
|
console.warn('gc should be empty after sync')
|
||||||
}
|
}
|
||||||
|
if (!this.store.gc) {
|
||||||
|
return
|
||||||
|
}
|
||||||
yield* this.os.iterate(this, null, null, function * (op) {
|
yield* this.os.iterate(this, null, null, function * (op) {
|
||||||
if (op.gc) {
|
if (op.gc) {
|
||||||
delete op.gc
|
delete op.gc
|
||||||
@@ -2356,7 +2389,7 @@ module.exports = function (Y/* :any */) {
|
|||||||
}
|
}
|
||||||
* addOperation (op) {
|
* addOperation (op) {
|
||||||
yield* this.os.put(op)
|
yield* this.os.put(op)
|
||||||
if (!this.store.y.connector.isDisconnected() && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
|
if (this.store.y.connector.isSynced && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
|
||||||
// is connected, and this is not going to be send in addOperation
|
// is connected, and this is not going to be send in addOperation
|
||||||
this.store.y.connector.broadcastOps([op])
|
this.store.y.connector.broadcastOps([op])
|
||||||
}
|
}
|
||||||
@@ -2771,7 +2804,6 @@ module.exports = function (Y /* : any*/) {
|
|||||||
destroy () {
|
destroy () {
|
||||||
super.destroy()
|
super.destroy()
|
||||||
this.waiting = null
|
this.waiting = null
|
||||||
this.awaiting = null
|
|
||||||
this.onevent = null
|
this.onevent = null
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -3442,6 +3474,11 @@ module.exports = function (Y /* : any*/) {
|
|||||||
return SmallLookupBuffer
|
return SmallLookupBuffer
|
||||||
}
|
}
|
||||||
Y.utils.createSmallLookupBuffer = createSmallLookupBuffer
|
Y.utils.createSmallLookupBuffer = createSmallLookupBuffer
|
||||||
|
|
||||||
|
// Generates a unique id, for use as a user id.
|
||||||
|
// Thx to @jed for this script https://gist.github.com/jed/982883
|
||||||
|
function generateGuid(a){return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,generateGuid)} // eslint-disable-line
|
||||||
|
Y.utils.generateGuid = generateGuid
|
||||||
}
|
}
|
||||||
|
|
||||||
},{}],7:[function(require,module,exports){
|
},{}],7:[function(require,module,exports){
|
||||||
@@ -3485,7 +3522,12 @@ Y.extend = function (name, value) {
|
|||||||
|
|
||||||
Y.requestModules = requestModules
|
Y.requestModules = requestModules
|
||||||
function requestModules (modules) {
|
function requestModules (modules) {
|
||||||
var sourceDir = Y.sourceDir || '/bower_components'
|
var sourceDir
|
||||||
|
if (Y.sourceDir === null) {
|
||||||
|
sourceDir = null
|
||||||
|
} else {
|
||||||
|
sourceDir = Y.sourceDir || '/bower_components'
|
||||||
|
}
|
||||||
// determine if this module was compiled for es5 or es6 (y.js vs. y.es6)
|
// determine if this module was compiled for es5 or es6 (y.js vs. y.es6)
|
||||||
// if Insert.execute is a Function, then it isnt a generator..
|
// if Insert.execute is a Function, then it isnt a generator..
|
||||||
// then load the es5(.js) files..
|
// then load the es5(.js) files..
|
||||||
@@ -3498,10 +3540,11 @@ function requestModules (modules) {
|
|||||||
if (requiringModules[module] == null) {
|
if (requiringModules[module] == null) {
|
||||||
// module does not exist
|
// module does not exist
|
||||||
if (typeof window !== 'undefined' && window.Y !== 'undefined') {
|
if (typeof window !== 'undefined' && window.Y !== 'undefined') {
|
||||||
var imported = document.createElement('script')
|
if (sourceDir != null) {
|
||||||
imported.src = sourceDir + '/' + modulename + '/' + modulename + extention
|
var imported = document.createElement('script')
|
||||||
document.head.appendChild(imported)
|
imported.src = sourceDir + '/' + modulename + '/' + modulename + extention
|
||||||
|
document.head.appendChild(imported)
|
||||||
|
}
|
||||||
let requireModule = {}
|
let requireModule = {}
|
||||||
requiringModules[module] = requireModule
|
requiringModules[module] = requireModule
|
||||||
requireModule.promise = new Promise(function (resolve) {
|
requireModule.promise = new Promise(function (resolve) {
|
||||||
@@ -3550,7 +3593,7 @@ type YOptions = {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
|
function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
|
||||||
if (opts.sourceDir != null) {
|
if (opts.hasOwnProperty('sourceDir')) {
|
||||||
Y.sourceDir = opts.sourceDir
|
Y.sourceDir = opts.sourceDir
|
||||||
}
|
}
|
||||||
opts.types = opts.types != null ? opts.types : []
|
opts.types = opts.types != null ? opts.types : []
|
||||||
@@ -3564,7 +3607,6 @@ function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
|
|||||||
else if (opts.connector.name == null) reject('You must specify connector name! (missing connector.name property)')
|
else if (opts.connector.name == null) reject('You must specify connector name! (missing connector.name property)')
|
||||||
else if (opts.db == null) reject('You must specify a database! (missing db property)')
|
else if (opts.db == null) reject('You must specify a database! (missing db property)')
|
||||||
else if (opts.connector.name == null) reject('You must specify db name! (missing db.name property)')
|
else if (opts.connector.name == null) reject('You must specify db name! (missing db.name property)')
|
||||||
else if (opts.share == null) reject('You must specify a set of shared types!')
|
|
||||||
else {
|
else {
|
||||||
opts = Y.utils.copyObject(opts)
|
opts = Y.utils.copyObject(opts)
|
||||||
opts.connector = Y.utils.copyObject(opts.connector)
|
opts.connector = Y.utils.copyObject(opts.connector)
|
||||||
@@ -3595,6 +3637,7 @@ class YConfig {
|
|||||||
this.options = opts
|
this.options = opts
|
||||||
this.db = new Y[opts.db.name](this, opts.db)
|
this.db = new Y[opts.db.name](this, opts.db)
|
||||||
this.connector = new Y[opts.connector.name](this, opts.connector)
|
this.connector = new Y[opts.connector.name](this, opts.connector)
|
||||||
|
this.connected = true
|
||||||
}
|
}
|
||||||
init (callback) {
|
init (callback) {
|
||||||
var opts = this.options
|
var opts = this.options
|
||||||
@@ -3631,29 +3674,50 @@ class YConfig {
|
|||||||
return this.connector.isSynced
|
return this.connector.isSynced
|
||||||
}
|
}
|
||||||
disconnect () {
|
disconnect () {
|
||||||
return this.connector.disconnect()
|
if (this.connected) {
|
||||||
|
this.connected = false
|
||||||
|
return this.connector.disconnect()
|
||||||
|
} else {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
reconnect () {
|
reconnect () {
|
||||||
return this.connector.reconnect()
|
if (!this.connected) {
|
||||||
|
this.connected = true
|
||||||
|
return this.connector.reconnect()
|
||||||
|
} else {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
destroy () {
|
destroy () {
|
||||||
|
var self = this
|
||||||
|
return this.close().then(function () {
|
||||||
|
if (self.db.deleteDB != null) {
|
||||||
|
return self.db.deleteDB()
|
||||||
|
} else {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
close () {
|
||||||
|
var self = this
|
||||||
|
this.share = null
|
||||||
if (this.connector.destroy != null) {
|
if (this.connector.destroy != null) {
|
||||||
this.connector.destroy()
|
this.connector.destroy()
|
||||||
} else {
|
} else {
|
||||||
this.connector.disconnect()
|
this.connector.disconnect()
|
||||||
}
|
}
|
||||||
var self = this
|
return this.db.whenTransactionsFinished(function () {
|
||||||
this.db.requestTransaction(function * () {
|
this.db.destroyTypes()
|
||||||
yield* self.db.destroy()
|
// make sure to wait for all transactions before destroying the db
|
||||||
self.connector = null
|
this.db.requestTransaction(function * () {
|
||||||
self.db = null
|
yield* self.db.destroy()
|
||||||
|
})
|
||||||
|
return this.db.whenTransactionsFinished()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof window !== 'undefined') {
|
},{"./Connector.js":1,"./Connectors/Test.js":2,"./Database.js":3,"./Struct.js":4,"./Transaction.js":5,"./Utils.js":6}]},{},[7])(7)
|
||||||
window.Y = Y
|
});
|
||||||
}
|
|
||||||
|
|
||||||
},{"./Connector.js":1,"./Connectors/Test.js":2,"./Database.js":3,"./Struct.js":4,"./Transaction.js":5,"./Utils.js":6}]},{},[7])
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user