git ssb

4+

Dominic / scuttlebot



Tree: 9f9cf35ed08ffd67846989f488fffb1faea6395f

Files: 9f9cf35ed08ffd67846989f488fffb1faea6395f / index.js

7147 bytesRaw
1var SecretStack = require('secret-stack')
2var create = require('secure-scuttlebutt/create')
3var ssbKeys = require('ssb-keys')
4var path = require('path')
5var osenv = require('osenv')
6var mkdirp = require('mkdirp')
7var rimraf = require('rimraf')
8var mdm = require('mdmanifest')
9var cmdAliases = require('./lib/cli-cmd-aliases')
10var valid = require('./lib/validators')
11var apidocs = require('./lib/apidocs.js')
12var pkg = require('./package.json')
13
14function isString(s) { return 'string' === typeof s }
15function isObject(o) { return 'object' === typeof o }
16function isFunction (f) { return 'function' === typeof f }
17// create SecretStack definition
18var manifest = mdm.manifest(apidocs._)
19manifest.seq = 'async'
20manifest.usage = 'sync'
21manifest.clock = 'async'
22manifest.version = 'sync'
23
24var SSB = {
25 manifest: manifest,
26 permissions: {
27 master: {allow: null, deny: null},
28 anonymous: {allow: ['createHistoryStream'], deny: null}
29 },
30 init: function (api, opts) {
31
32 // .temp: use a /tmp data directory
33 // (useful for testing)
34 if(opts.temp) {
35 var name = isString(opts.temp) ? opts.temp : ''+Date.now()
36 opts.path = path.join(osenv.tmpdir(), name)
37 rimraf.sync(opts.path)
38 }
39
40 // load/create secure scuttlebutt data directory
41 var dbPath = path.join(opts.path, 'db')
42 mkdirp.sync(dbPath)
43
44 if(!opts.keys)
45 opts.keys = ssbKeys.generate('ed25519', opts.seed && new Buffer(opts.seed, 'base64'))
46
47 if(!opts.path)
48 throw new Error('opts.path *must* be provided, or use opts.temp=name to create a test instance')
49
50 // main interface
51 var ssb = create(path.join(opts.path, 'db'), opts, opts.keys)
52 //treat the main feed as remote, because it's likely handled like that by others.
53 var feed = ssb.createFeed(opts.keys, {remote: true})
54 var _close = api.close
55 var close = function (arg, cb) {
56 if('function' === typeof arg) cb = arg
57 // override to close the SSB database
58 ssb.close(function (err) {
59 if (err) throw err
60 _close()
61 cb && cb() //multiserver doesn't take a callback on close.
62 })
63 }
64
65 function since () {
66 var plugs = {}
67 var sync = true
68 for(var k in ssb) {
69 if(ssb[k] && isObject(ssb[k]) && isFunction(ssb[k].since)) {
70 plugs[k] = ssb[k].since.value
71 sync = sync && (plugs[k] === ssb.since.value)
72 }
73 }
74 return {
75 since: ssb.since.value,
76 plugins: plugs,
77 sync: sync,
78 }
79 }
80 var self
81 return self = {
82 id : feed.id,
83 keys : opts.keys,
84
85 ready : function () {
86 return ssb.ready.value
87 },
88
89 progress : function () {
90 return ssb.progress
91 },
92
93 status : function () {
94 return {progress: self.progress(), db: ssb.status, sync: since() }
95 },
96
97 version : function () {
98 return pkg.version
99 },
100
101 //temporary!
102 _flumeUse :
103 function (name, flumeview) {
104 ssb.use(name, flumeview)
105 return ssb[name]
106 },
107
108 usage : valid.sync(usage, 'string?|boolean?'),
109 close : valid.async(close),
110
111 publish : valid.async(feed.add, 'string|msgContent'),
112 add : valid.async(ssb.add, 'msg'),
113 queue : valid.async(ssb.queue, 'msg'),
114 get : valid.async(ssb.get, 'msgId|number|object'),
115
116 post : ssb.post,
117
118 since : since,
119
120 getPublicKey : ssb.getPublicKey,
121 latest : ssb.latest,
122 getLatest : valid.async(ssb.getLatest, 'feedId'),
123 latestSequence : valid.async(ssb.latestSequence, 'feedId'),
124 createFeed : ssb.createFeed,
125 whoami : function () { return { id: feed.id } },
126 query : ssb.query,
127 createFeedStream : valid.source(ssb.createFeedStream, 'readStreamOpts?'),
128 createHistoryStream : valid.source(ssb.createHistoryStream, ['createHistoryStreamOpts'], ['feedId', 'number?', 'boolean?']),
129 createLogStream : valid.source(ssb.createLogStream, 'readStreamOpts?'),
130 createUserStream : valid.source(ssb.createUserStream, 'createUserStreamOpts'),
131 links : valid.source(ssb.links, 'linksOpts'),
132 sublevel : ssb.sublevel,
133 messagesByType : valid.source(ssb.messagesByType, 'string|messagesByTypeOpts'),
134 createWriteStream : ssb.createWriteStream,
135 getVectorClock : ssb.getVectorClock,
136 getAtSequence : ssb.getAtSequence,
137 }
138 }
139}
140
141// live help RPC method
142function usage (cmd) {
143 var path = (cmd||'').split('.')
144 if ((path[0] && apidocs[path[0]]) || (cmd && apidocs[cmd])) {
145 // return usage for the plugin
146 cmd = path.slice(1).join('.')
147 return mdm.usage(apidocs[path[0]], cmd, { prefix: path[0] })
148 }
149 if (!cmd) {
150 // return usage for all docs
151 return Object.keys(apidocs).map(function (name) {
152 if (name == '_')
153 return mdm.usage(apidocs[name], null, { nameWidth: 20 })
154
155 var text = mdm.usage(apidocs[name], null, { prefix: name, nameWidth: 20 })
156 return text.slice(text.indexOf('Commands:') + 10) // skip past the toplevel summary, straight to the cmd list
157 }).join('\n\n')
158 }
159 // toplevel cmd usage
160 cmd = cmdAliases[cmd] || cmd
161 return mdm.usage(apidocs._, cmd)
162}
163
164function createSbot() {
165 return SecretStack({
166 //this is just the default app key.
167 //it can be overridden by passing a appKey as option
168 //when creating a Sbot instance.
169 appKey: require('./lib/ssb-cap')
170 })
171 .use(SSB)
172 .use(function (ssk, config) {
173 var Onion = require('multiserver/plugins/onion')
174
175 ssk.multiserver.transport({
176 name: 'onion',
177 create: function (conf) {
178 return Onion(conf)
179 }
180 })
181 })
182 .use(function (ssk, config) {
183 var WS = require('multiserver/plugins/ws')
184
185 ssk.multiserver.transport({
186 name: 'ws',
187 create: function (conf) {
188 if (!conf.port)
189 conf.port = 1024+(~~(Math.random()*(65536-1024)))
190
191 return WS(conf)
192 }
193 })
194 })
195 .use(function (ssk, config) {
196 var us = require('multiserver/plugins/unix-socket')
197
198 ssk.multiserver.transport({
199 name: 'unix',
200 create: function () {
201 return us({ path: config.path })
202 }
203 })
204 })
205 .use(function (ssk, config) {
206 var Noauth = require('multiserver/plugins/noauth')
207
208 ssk.multiserver.transform({
209 name: 'noauth',
210 create: function () {
211 return Noauth({
212 keys: {
213 publicKey: Buffer.from(config.keys.public, 'base64')
214 }
215 })
216 }
217 })
218 })
219}
220module.exports = createSbot()
221module.exports.createSbot = createSbot
222
223
224

Built with git-ssb-web