-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathindex.js
141 lines (104 loc) · 3.79 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* jshint node: true */
'use strict';
var debug = require('cog/logger')('rtc-mesh');
var dcstream = require('rtc-dcstream');
var Model = require('scuttlebutt/model');
/**
# rtc-mesh
__NOTE:__ From version `0.5` onwards `rtc-mesh` is now an
[rtc-quickconnect](https://github.com/rtc-io/rtc-quickconnect) plugin
(which is heaps better and cleaner).
The `rtc-mesh` module provides a way of sharing data between clients using
[scuttlebutt](https://github.com/dominictarr/scuttlebutt).
## Simple Example
<<< examples/simple.js
## Using Scuttlebutt Subclasses
In the case that you would like to use one of the
[Scuttlebutt subclasses](https://github.com/dominictarr/scuttlebutt#subclasses),
this can be done quite easily be providing a model instance in the `model`
option in the `opts` argument. Here's an example using
[CRDT](https://github.com/dominictarr/crdt):
<<< examples/crdt.js
## Synchronizing Multiple Datasets
It's also possible to create invoke multiple meshes on a single data
channel using custom channel names (by default the a channel is created with
the name of `mesh`).
<<< examples/multichannel.js
## Reference
**/
/**
### mesh
```
mesh(qc, opts?) => Model
```
As displayed in the examples, the `mesh` function expects to be passed a
[quickconnect](https://github.com/rtc-io/rtc-quickconnect) created signaller. Using
this object, it will create a data channel that will be responsible for sharing
[scuttlebutt](https://github.com/dominictarr/scuttlebutt) model information with peers.
In addition to the functions exposed by a scuttlebutt Model, the following helpers
have also been added:
**/
module.exports = function(qc, opts) {
// create the model
var model = (opts || {}).model || new Model();
var name = (opts || {}).channelName || 'mesh';
var channels = {};
function joinMesh(id, dc) {
// create a new stream
var stream = dcstream(dc);
var reader = model.createReadStream();
var writer = model.createWriteStream();
debug('connecting mesh with peer: ' + id);
// register the channel
channels[id] = dc;
stream.on('error', function(err) {
console.warn('captured stream error: ', err.message)
});
reader.on('error', function(err) {
console.warn('captured reader stream error: ', err.message);
});
writer.on('error', function(err) {
console.warn('captured writer stream error: ', err.message);
});
// connect the stream to the data
reader.pipe(stream).pipe(writer);
// bubble sync events
writer.on('sync', model.emit.bind(model, 'sync'));
}
function joinMeshDeprecated(dc, id) {
joinMesh(id, dc);
}
function leaveMesh(id) {
// remove the channel reference
channels[id] = null;
}
/**
#### retrieve
```
retrieve(key, callback)
```
Get the value of the specified key and pass the result back through the
provided `callback` (node error first style). If the value is already
available in the local Model, then the callback will be triggered immediately.
If not, the callback will be triggered once the value has been set in the
local Model.
**/
function retrieve(key, callback) {
var value = model.get(key);
// if we have the value, then trigger the callback immediately
if (typeof value != 'undefined') {
return callback(null, value);
}
// otherwise, wait for the value
model.once('change:' + key, callback.bind(model, null));
}
// patch in the retrieveValue function
model.retrieve = retrieve;
// create the data channel
qc.createDataChannel(name, (opts || {}).channelOpts)
.on(name + ':open', joinMeshDeprecated)
.on('channel:opened:' + name, joinMesh)
.on(name + ':close', leaveMesh)
.on('channel:closed:' + name, leaveMesh);
return model;
};