A framework for real-time p2p shared editing on any data
npm install ys-yjs
sh
bower install --save yjs y-array % add all y-* modules you want to use
`
You only need to include the y.js file. Yjs is able to automatically require
missing modules.
`html
`
$3
`sh
npm install --save yjs % add all y-* modules you want to use
`
If you don't include via script tag, you have to explicitly include all modules!
(Same goes for other module systems)
`js
var Y = require('yjs')
require('y-array')(Y) // add the y-array type to Yjs
require('y-websockets-client')(Y)
require('y-memory')(Y)
require('y-array')(Y)
require('y-map')(Y)
require('y-text')(Y)
// ..
// do the same for all modules you want to use
`
$3
`js
import Y from 'yjs'
import yArray from 'y-array'
import yWebsocketsClient from 'y-webrtc'
import yMemory from 'y-memory'
import yArray from 'y-array'
import yMap from 'y-map'
import yText from 'y-text'
// ..
Y.extend(yArray, yWebsocketsClient, yMemory, yArray, yMap, yText /, .. /)
`
Text editing example
Install dependencies
`sh
bower i yjs y-memory y-webrtc y-array y-text
`
Here is a simple example of a shared textarea
`HTML
`
Get Help & Give Help
There are some friendly people on  who are eager to help, and answer questions. Please join!
Report _any_ issues to the
Github issue page! I try to fix them very
soon, if possible.
API
$3
* Y.extend(module1, module2, ..)
* Add extensions to Y
* Y.extend(require('y-webrtc')) has the same semantics as
require('y-webrtc')(Y)
* options.db
* Will be forwarded to the database adapter. Specify the database adaper on
options.db.name.
* Have a look at the used database adapter repository to see all available
options.
* options.connector
* Will be forwarded to the connector adapter. Specify the connector adaper on
options.connector.name.
* 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 also have a default connection endpoint that you can
use for development.
* We provide basic authentification for all connectors. The value of
options.connector.auth (this can be a passphase) is sent to all connected
Yjs instances. options.connector.checkAuth may grant read or write access
depending on the auth information.
Example: A client specifies options.connector.auth = 'superSecretPassword.
A server specifies
`js
options.connector.checkAuth = function (auth, yjsInstance, sender) {
return new Promise(function (resolve, reject){
if (auth === 'superSecretPassword') {
resolve('write') // grant read-write access
} else if (auth === 'different password') {
resolve('read') // grant read-only access
} else {
reject('wrong password!') // reject connection
}
})
}
`
* 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.
Only if you know what you are doing:* Set
options.connector.preferUntransformed = true in order receive the shared
data untransformed. This is very efficient as the database content is simply
copied to this client. This does only work if this client receives content
from only one client.
* options.sourceDir (browser only)
Path where all y- modules are stored
* Defaults to /bower_components
* Not required when running on nodejs / iojs
* When using nodejs you need to manually extend Yjs:
`js
var Y = require('yjs')
// you have to require a db, connector, and all types you use!
require('y-memory')(Y)
require('y-webrtc')(Y)
require('y-map')(Y)
// ..
`
* options.share
* Specify on options.share[arbitraryName] types that are shared among all
users.
* E.g. Specify options.share[arbitraryName] = 'Array' to require y-array and
create an y-array type on y.share[arbitraryName].
* If userA doesn't specify options.share[arbitraryName], it won't be
available for userA.
* If userB specifies options.share[arbitraryName], it still won't be
available for userA. But all the updates are send from userB to userA.
In contrast to y-map, types on y.share. cannot be overwritten or deleted.
Instead, they are merged among all users. This feature is only available on
y.share.*
* Weird behavior: It is supported that two users specify different types with
the same property name.
E.g. userA specifies options.share.x = 'Array', and userB specifies
options.share.x = 'Text'. But they only share data if they specified the
same type with the same property name
* options.type (browser only)
* Array of modules that Yjs needs to require, before instantiating a shared
type.
* By default Yjs requires the specified database adapter, the specified
connector, and all modules that are used in options.share.*
Put all types here that you intend to use, but are not used in y.share.
$3
Y(options) returns a promise that is fulfilled when..
* All modules are loaded
* The specified database adapter is loaded
* The specified connector is loaded
* All types are included
* The connector is initialized, and a unique user id is set (received from the
server)
* Note: When using y-indexeddb, a retrieved user id is stored on localStorage
The promise returns an instance of Y. We denote it with a lower case y.
y.share.
Instances of the types you specified on options.share.
y.share. can only be defined once when you instantiate Y!
* y.connector is an instance of Y.AbstractConnector
* y.connector.onUserEvent(function (event) {..})
* Observe user events (event.action is either 'userLeft' or 'userJoined')
* y.connector.whenSynced(listener)
* listener is executed when y synced with at least one user.
* listener is not called when no other user is in the same room.
* y-websockets-client aways waits to sync with the server
* y.connector.disconnect()
* Force to disconnect this instance from the other instances
* y.connector.reconnect()
* Try to reconnect to the other instances (needs to be supported by the
connector)
* Not supported by y-xmpp
* y.close()
* Destroy this object.
* Destroys all types (they will throw weird errors if you still use them)
* Disconnects from the other instances (via connector)
* Returns a promise
* y.destroy()
* calls y.close()
* Removes all data from the database
* Returns a promise
* y.db.stopGarbageCollector()
* 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)
* 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)
* y.db.userId :: String
* The used user id for this client. Never overwrite this
$3
Yjs uses debug for logging. The flag
y enables logging for all y- components. You can selectively remove
will not log the long y:connector-message messages.
##### Enable logging in Node.js
`sh
DEBUG=y* node app.js
`
Remove the colors in order to log to a file:
`sh
DEBUG_COLORS=0 DEBUG=y* node app.js > log
`
##### Enable logging in the browser
`js
localStorage.debug = 'y*'
``