git ssb

1+

Dominic / secure-scuttlebutt



Commit ce0193e6fd7e6dfc8a6db20584bc72fa4886e719

stuff needed for working as a secret-stack plugin

Dominic Tarr committed on 1/10/2019, 9:49:04 PM
Parent: 9a17c94760002374e7b724537d1ea63dcd1b84e0

Files changed

api.mdadded
lib/validators.jsadded
plugin.jsadded
api.mdView
@@ -1,0 +1,341 @@
1+# ssb-server
2+
3+Secure-scuttlebutt API server
4+
5+
6+
7+## get: async
8+
9+Get a message by its hash-id.
10+
11+```bash
12+get {msgid}
13+```
14+
15+```js
16+get(msgid, cb)
17+```
18+
19+
20+
21+## createFeedStream: source
22+
23+(feed) Fetch messages ordered by their claimed timestamps.
24+
25+```bash
26+feed [--live] [--gt index] [--gte index] [--lt index] [--lte index] [--reverse] [--keys] [--values] [--limit n]
27+```
28+
29+```js
30+createFeedStream({ live:, gt:, gte:, lt:, lte:, reverse:, keys:, values:, limit:, fillCache:, keyEncoding:, valueEncoding: })
31+```
32+
33+Create a stream of the data in the database, ordered by the timestamp claimed by the author.
34+NOTE - the timestamp is not verified, and may be incorrect.
35+The range queries (gt, gte, lt, lte) filter against this claimed timestap.
36+
37+ - `live` (boolean, default: `false`): Keep the stream open and emit new messages as they are received.
38+ - `gt` (greater than), `gte` (greater than or equal) define the lower bound of the range to be streamed. Only records where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.
39+ - `lt` (less than), `lte` (less than or equal) define the higher bound of the range to be streamed. Only key/value pairs where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.
40+ - `reverse` (boolean, default: `false`): a boolean, set true and the stream output will be reversed. Beware that due to the way LevelDB works, a reverse seek will be slower than a forward seek.
41+ - `keys` (boolean, default: `true`): whether the `data` event should contain keys. If set to `true` and `values` set to `false` then `data` events will simply be keys, rather than objects with a `key` property.
42+ - `values` (boolean, default: `true`): whether the `data` event should contain values. If set to `true` and `keys` set to `false` then `data` events will simply be values, rather than objects with a `value` property.
43+ - `limit` (number, default: `-1`): limit the number of results collected by this stream. This number represents a *maximum* number of results and may not be reached if you get to the end of the data first. A value of `-1` means there is no limit. When `reverse=true` the highest keys will be returned instead of the lowest keys.
44+ - `fillCache` (boolean, default: `false`): wheather LevelDB's LRU-cache should be filled with data read.
45+ - `keyEncoding` / `valueEncoding` (string): the encoding applied to each read piece of data.
46+
47+
48+
49+## createLogStream: source
50+
51+(log) Fetch messages ordered by the time received.
52+
53+```bash
54+log [--live] [--gt index] [--gte index] [--lt index] [--lte index] [--reverse] [--keys] [--values] [--limit n]
55+```
56+
57+```js
58+createLogStream({ live:, gt:, gte:, lt:, lte:, reverse:, keys:, values:, limit:, fillCache:, keyEncoding:, valueEncoding: })
59+```
60+
61+Creates a stream of the messages that have been written to this instance, in the order they arrived.
62+The objects in this stream will be of the form:
63+
64+```
65+{ key: Hash, value: Message, timestamp: timestamp }
66+```
67+
68+`timestamp` is the time which the message was received.
69+It is generated by [monotonic-timestamp](https://github.com/dominictarr/monotonic-timestamp).
70+The range queries (gt, gte, lt, lte) filter against this receive timestap.
71+
72+
73+ - `live` (boolean, default: `false`): Keep the stream open and emit new messages as they are received.
74+ - `gt` (greater than), `gte` (greater than or equal) define the lower bound of the range to be streamed. Only records where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.
75+ - `lt` (less than), `lte` (less than or equal) define the higher bound of the range to be streamed. Only key/value pairs where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.
76+ - `reverse` (boolean, default: `false`): a boolean, set true and the stream output will be reversed. Beware that due to the way LevelDB works, a reverse seek will be slower than a forward seek.
77+ - `keys` (boolean, default: `true`): whether the `data` event should contain keys. If set to `true` and `values` set to `false` then `data` events will simply be keys, rather than objects with a `key` property.
78+ - `values` (boolean, default: `false`): whether the `data` event should contain values. If set to `true` and `keys` set to `false` then `data` events will simply be values, rather than objects with a `value` property.
79+ - `limit` (number, default: `-1`): limit the number of results collected by this stream. This number represents a *maximum* number of results and may not be reached if you get to the end of the data first. A value of `-1` means there is no limit. When `reverse=true` the highest keys will be returned instead of the lowest keys.
80+ - `fillCache` (boolean, default: `false`): wheather LevelDB's LRU-cache should be filled with data read.
81+ - `keyEncoding` / `valueEncoding` (string): the encoding applied to each read piece of data.
82+
83+
84+
85+## messagesByType: source
86+
87+(logt) Retrieve messages with a given type, ordered by receive-time.
88+
89+
90+```bash
91+logt --type {type} [--live] [--gt index] [--gte index] [--lt index] [--lte index] [--reverse] [--keys] [--values] [--limit n]
92+```
93+
94+```js
95+messagesByType({ type:, live:, gt:, gte:, lt:, lte:, reverse:, keys:, values:, limit:, fillCache:, keyEncoding:, valueEncoding: })
96+```
97+
98+All messages must have a type, so this is a good way to select messages that an application might use.
99+Like in createLogStream, the range queries (gt, gte, lt, lte) filter against the receive timestap.
100+
101+ - `type` (string): The type of the messages to emit.
102+ - `live` (boolean, default: `false`): Keep the stream open and emit new messages as they are received.
103+ - `gt` (greater than), `gte` (greater than or equal) define the lower bound of the range to be streamed. Only records where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.
104+ - `lt` (less than), `lte` (less than or equal) define the higher bound of the range to be streamed. Only key/value pairs where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.
105+ - `reverse` (boolean, default: `false`): a boolean, set true and the stream output will be reversed. Beware that due to the way LevelDB works, a reverse seek will be slower than a forward seek.
106+ - `keys` (boolean, default: `true`): whether the `data` event should contain keys. If set to `true` and `values` set to `false` then `data` events will simply be keys, rather than objects with a `key` property.
107+ - `values` (boolean, default: `true`): whether the `data` event should contain values. If set to `true` and `keys` set to `false` then `data` events will simply be values, rather than objects with a `value` property.
108+ - `limit` (number, default: `-1`): limit the number of results collected by this stream. This number represents a *maximum* number of results and may not be reached if you get to the end of the data first. A value of `-1` means there is no limit. When `reverse=true` the highest keys will be returned instead of the lowest keys.
109+ - `fillCache` (boolean, default: `false`): wheather LevelDB's LRU-cache should be filled with data read.
110+ - `keyEncoding` / `valueEncoding` (string): the encoding applied to each read piece of data.
111+
112+
113+
114+## createHistoryStream: source
115+
116+(hist) Fetch messages from a specific user, ordered by sequence numbers.
117+
118+```bash
119+hist {feedid} [seq] [live]
120+hist --id {feedid} [--seq n] [--live] [--limit n] [--keys] [--values]
121+```
122+
123+```js
124+createHistoryStream(id, seq, live)
125+createHistoryStream({ id:, seq:, live:, limit:, keys:, values: })
126+```
127+
128+`createHistoryStream` and `createUserStream` serve the same purpose.
129+`createHistoryStream` exists as a separate call because it provides fewer range parameters, which makes it safer for RPC between untrusted peers.
130+
131+ - `id` (FeedID, required): The id of the feed to fetch.
132+ - `seq` (number, default: `0`): If `seq > 0`, then only stream messages with sequence numbers greater than `seq`.
133+ - `live` (boolean, default: `false`): Keep the stream open and emit new messages as they are received.
134+ - `keys` (boolean, default: `true`): whether the `data` event should contain keys. If set to `true` and `values` set to `false` then `data` events will simply be keys, rather than objects with a `key` property.
135+ - `values` (boolean, default: `true`): whether the `data` event should contain values. If set to `true` and `keys` set to `false` then `data` events will simply be values, rather than objects with a `value` property.
136+ - `limit` (number, default: `-1`): limit the number of results collected by this stream. This number represents a *maximum* number of results and may not be reached if you get to the end of the data first. A value of `-1` means there is no limit. When `reverse=true` the highest keys will be returned instead of the lowest keys.
137+
138+
139+## createUserStream: source
140+
141+Fetch messages from a specific user, ordered by sequence numbers.
142+
143+```bash
144+createUserStream --id {feedid} [--live] [--gt index] [--gte index] [--lt index] [--lte index] [--reverse] [--keys] [--values] [--limit n]
145+```
146+
147+```js
148+createUserStream({ id:, live:, gt:, gte:, lt:, lte:, reverse:, keys:, values:, limit:, fillCache:, keyEncoding:, valueEncoding: })
149+```
150+
151+`createHistoryStream` and `createUserStream` serve the same purpose.
152+`createHistoryStream` exists as a separate call because it provides fewer range parameters, which makes it safer for RPC between untrusted peers.
153+
154+The range queries (gt, gte, lt, lte) filter against the sequence number.
155+
156+ - `id` (FeedID, required): The id of the feed to fetch.
157+ - `live` (boolean, default: `false`): Keep the stream open and emit new messages as they are received.
158+ - `gt` (greater than), `gte` (greater than or equal) define the lower bound of the range to be streamed. Only records where the key is greater than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.
159+ - `lt` (less than), `lte` (less than or equal) define the higher bound of the range to be streamed. Only key/value pairs where the key is less than (or equal to) this option will be included in the range. When `reverse=true` the order will be reversed, but the records streamed will be the same.
160+ - `reverse` (boolean, default: `false`): a boolean, set true and the stream output will be reversed. Beware that due to the way LevelDB works, a reverse seek will be slower than a forward seek.
161+ - `keys` (boolean, default: `true`): whether the `data` event should contain keys. If set to `true` and `values` set to `false` then `data` events will simply be keys, rather than objects with a `key` property.
162+ - `values` (boolean, default: `true`): whether the `data` event should contain values. If set to `true` and `keys` set to `false` then `data` events will simply be values, rather than objects with a `value` property.
163+ - `limit` (number, default: `-1`): limit the number of results collected by this stream. This number represents a *maximum* number of results and may not be reached if you get to the end of the data first. A value of `-1` means there is no limit. When `reverse=true` the highest keys will be returned instead of the lowest keys.
164+ - `fillCache` (boolean, default: `false`): wheather LevelDB's LRU-cache should be filled with data read.
165+ - `keyEncoding` / `valueEncoding` (string): the encoding applied to each read piece of data.
166+
167+
168+## createWriteStream: sink
169+
170+write a number of messages to the local store.
171+will error if messages are not valid, but will accept
172+messages that the ssb-server doesn't replicate.
173+
174+
175+## links: source
176+
177+Get a stream of messages, feeds, or blobs that are linked to/from an id.
178+
179+```bash
180+links [--source id|filter] [--dest id|filter] [--rel value] [--keys] [--values] [--live] [--reverse]
181+```
182+
183+```js
184+links({ source:, dest:, rel:, keys:, values:, live:, reverse: })
185+```
186+
187+The objects in this stream will be of the form:
188+
189+```
190+{ source: ID, rel: String, dest: ID, key: MsgID }
191+```
192+
193+ - `source` (string, optional): An id or filter, specifying where the link should originate from. To filter, just use the sigil of the type you want: `@` for feeds, `%` for messages, and `&` for blobs.
194+ - `dest` (string, optional): An id or filter, specifying where the link should point to. To filter, just use the sigil of the type you want: `@` for feeds, `%` for messages, and `&` for blobs.
195+ - `rel` (string, optional): Filters the links by the relation string.
196+ - `live` (boolean, default: `false`): Keep the stream open and emit new messages as they are received.
197+ - `reverse` (boolean, default: `false`): a boolean, set true and the stream output will be reversed. Beware that due to the way LevelDB works, a reverse seek will be slower than a forward seek.
198+ - `keys` (boolean, default: `true`): whether the `data` event should contain keys. If set to `true` and `values` set to `false` then `data` events will simply be keys, rather than objects with a `key` property.
199+ - `values` (boolean, default: `true`): whether the `data` event should contain values. If set to `true` and `keys` set to `false` then `data` events will simply be values, rather than objects with a `value` property.
200+
201+
202+## add: async
203+
204+Add a well-formed message to the database.
205+
206+```bash
207+cat ./message.json | add
208+add --author {feedid} --sequence {number} --previous {msgid} --timestamp {number} --hash sha256 --signature {sig} --content.type {type} --content.{...}
209+```
210+
211+```js
212+add({ author:, sequence:, previous: timestamp:, hash: 'sha256', signature:, content: { type:, ... } }, cb)
213+```
214+
215+ - `author` (FeedID): Public key of the author of the message.
216+ - `sequence` (number): Sequence number of the message. (Starts from 1.)
217+ - `previous` (MsgID): Hash-id of the previous message in the feed (null for seq=1).
218+ - `timestamp` (number): Unix timestamp for the publish time.
219+ - `hash` (string): The hash algorithm used in the message, should always be `sha256`.
220+ - `signature` (string): A signature computed using the author pubkey and the content of the message (less the `signature` attribute).
221+ - `content` (object): The content of the message.
222+ - `.type` (string): The object's type.
223+
224+
225+## publish: async
226+
227+Construct a message using ssb-server's current user, and add it to the DB.
228+
229+```bash
230+cat ./message-content.json | publish
231+publish --type {string} [--other-attributes...]
232+```
233+
234+```js
235+publish({ type:, ... }, cb)
236+```
237+
238+This is the recommended method for publishing new messages, as it handles the tasks of correctly setting the message's timestamp, sequence number, previous-hash, and signature.
239+
240+ - `content` (object): The content of the message.
241+ - `.type` (string): The object's type.
242+
243+
244+
245+
246+## getAddress: sync
247+
248+Get the address of the server. Default scope is public.
249+
250+```bash
251+getAddress {scope}
252+```
253+
254+```js
255+getAddress(scope, cb)
256+```
257+
258+
259+
260+## getLatest: async
261+
262+Get the latest message in the database by the given feedid.
263+
264+```bash
265+getLatest {feedid}
266+```
267+
268+```js
269+getLatest(id, cb)
270+```
271+
272+
273+
274+## latest: source
275+
276+Get the seq numbers of the latest messages of all users in the database.
277+
278+```bash
279+latest
280+```
281+
282+```js
283+latest()
284+```
285+
286+
287+
288+## latestSequence: async
289+
290+Get the sequence and local timestamp of the last received message from
291+a given `feedId`.
292+
293+```bash
294+latestSequence {feedId}
295+```
296+
297+```js
298+latest({feedId})
299+```
300+
301+
302+
303+## whoami: sync
304+
305+Get information about the current ssb-server user.
306+
307+```bash
308+whoami
309+```
310+
311+```js
312+whoami(cb)
313+```
314+
315+Outputs information in the following form:
316+
317+```
318+{ id: FeedID }
319+```
320+
321+
322+
323+## progress: sync
324+
325+returns an object reflecting the progress state of various plugins.
326+the return value is a `{}` with subobjects showing `{start,current,target}`
327+to represent progress. Currently implemented are `migration` (legacy->flume)
328+migration progress and `indexes` (index regeneration).
329+
330+
331+## status: sync
332+
333+returns an object reflecting the status of various ssb operations,
334+such as db read activity, connection statuses, etc, etc. The purpose is to provide
335+an overview of how ssb is working.
336+
337+## getVectorClock: async
338+
339+## version: sync
340+
341+return the current version number of the running server
lib/validators.jsView
@@ -1,0 +1,239 @@
1+var valid = require('muxrpc-validation')
2+var zerr = require('zerr')
3+var ref = require('ssb-ref')
4+
5+// errors
6+var MissingAttr = zerr('Usage', 'Param % must have a .% of type "%"')
7+var AttrType = zerr('Usage', '.% of param % must be of type "%"')
8+
9+function isFilter (v) {
10+ return (v == '@' || v == '%' || v == '&')
11+}
12+
13+module.exports = valid({
14+ msgId: function (v) {
15+ if (!ref.isMsg(v))
16+ return 'type'
17+ },
18+ msgLink: function (v) {
19+ if (!ref.isMsgLink(v))
20+ return 'type'
21+ },
22+ feedId: function (v) {
23+ if (!ref.isFeed(v))
24+ return 'type'
25+ },
26+ blobId: function (v) {
27+ if (!ref.isBlob(v))
28+ return 'type'
29+ },
30+
31+ msgContent: function (v, n) {
32+ var err = this.get('object')(v, n)
33+ if (err) return err
34+ if (!v.type || typeof v.type != 'string')
35+ return MissingAttr(n, 'type', 'string')
36+ },
37+
38+ msg: function (v, n) {
39+ var err = this.get('object')(v, n)
40+ if (err)
41+ return err
42+
43+ //allow content to be string. (i.e. for encrypted messages)
44+ //or object with type string
45+ if(!v.content)
46+ return MissingAttr(n, 'content', 'object|string')
47+ else if(typeof v.content === 'string')
48+ ; //check if it's base64?
49+ else if('object' === typeof v.content) {
50+ if(!v.content.type || typeof v.content.type != 'string')
51+ return MissingAttr(n, 'content.type', 'string')
52+ }
53+ else
54+ return MissingAttr(n, 'content', 'object|string')
55+
56+ // .author
57+ if (!ref.isFeed(v.author))
58+ return MissingAttr(n, 'author', 'feedId')
59+
60+ // .sequence
61+ if (typeof v.sequence != 'number')
62+ return MissingAttr(n, 'sequence', 'number')
63+
64+ // .previous
65+ if (v.sequence > 1 && !ref.isMsg(v.previous))
66+ return MissingAttr(n, 'previous', 'msgId')
67+ else if(v.sequence == 1 && v.previous != null)
68+ return MissingAttr(n, 'previous', 'null')
69+
70+ // .timestamp
71+ if (typeof v.timestamp != 'number')
72+ return MissingAttr(n, 'timestamp', 'number')
73+
74+ // .hash
75+ if (v.hash != 'sha256')
76+ return zerr('Usage', 'Param % must have .hash set to "sha256"')(n)
77+
78+ // .signature
79+ if (typeof v.signature != 'string')
80+ return MissingAttr(n, 'signature', 'string')
81+ },
82+
83+ readStreamOpts: function (v, n) {
84+ var err = this.get('object')(v, n)
85+ if (err)
86+ return err
87+
88+ // .live
89+ if (v.live && typeof v.live != 'boolean' && typeof v.live != 'number')
90+ return AttrType(n, 'live', 'boolean')
91+
92+ // .reverse
93+ if (v.reverse && typeof v.reverse != 'boolean' && typeof v.reverse != 'number')
94+ return AttrType(n, 'reverse', 'boolean')
95+
96+ // .keys
97+ if (v.keys && typeof v.keys != 'boolean' && typeof v.keys != 'number')
98+ return AttrType(n, 'keys', 'boolean')
99+
100+ // .values
101+ if (v.values && typeof v.values != 'boolean' && typeof v.values != 'number')
102+ return AttrType(n, 'values', 'boolean')
103+
104+ // .limit
105+ if (v.limit && typeof v.limit != 'number')
106+ return AttrType(n, 'limit', 'number')
107+
108+ // .fillCache
109+ if (v.fillCache && typeof v.fillCache != 'boolean' && typeof v.fillCache != 'number')
110+ return AttrType(n, 'fillCache', 'boolean')
111+ },
112+
113+ createHistoryStreamOpts: function (v, n) {
114+ // .id
115+ if (!ref.isFeed(v.id))
116+ return MissingAttr(n, 'id', 'feedId')
117+
118+ // .seq
119+ if (v.seq && typeof v.seq != 'number')
120+ return AttrType(n, 'seq', 'number')
121+
122+ // .live
123+ if (v.live && typeof v.live != 'boolean' && typeof v.live != 'number')
124+ return AttrType(n, 'live', 'boolean')
125+
126+ // .limit
127+ if (v.limit && typeof v.limit != 'number')
128+ return AttrType(n, 'limit', 'number')
129+
130+ // .keys
131+ if (v.keys && typeof v.keys != 'boolean' && typeof v.keys != 'number')
132+ return AttrType(n, 'keys', 'boolean')
133+
134+ // .values
135+ if (v.values && typeof v.values != 'boolean' && typeof v.values != 'number')
136+ return AttrType(n, 'values', 'boolean')
137+ },
138+
139+ createUserStreamOpts: function (v, n) {
140+ var err = this.get('readStreamOpts')(v, n)
141+ if (err)
142+ return err
143+
144+ // .id
145+ if (!ref.isFeed(v.id))
146+ return MissingAttr(n, 'id', 'feedId')
147+ },
148+
149+ messagesByTypeOpts: function (v, n) {
150+ var err = this.get('readStreamOpts')(v, n)
151+ if (err)
152+ return err
153+
154+ // .type
155+ if (typeof v.type != 'string')
156+ return MissingAttr(n, 'type', 'string')
157+ },
158+
159+ linksOpts: function (v, n) {
160+ var err = this.get('object')(v, n)
161+ if (err)
162+ return err
163+
164+ // .source
165+ if (v.source && !ref.isLink(v.source) && !isFilter(v.source))
166+ return AttrType(n, 'source', 'id|filter')
167+
168+ // .dest
169+ if (v.dest && !ref.isLink(v.dest) && !isFilter(v.dest))
170+ return AttrType(n, 'dest', 'id|filter')
171+
172+ // .rel
173+ if (v.rel && typeof v.rel != 'string')
174+ return AttrType(n, 'rel', 'string')
175+
176+ // .live
177+ if (v.live && typeof v.live != 'boolean' && typeof v.live != 'number')
178+ return AttrType(n, 'live', 'boolean')
179+
180+ // .reverse
181+ if (v.reverse && typeof v.reverse != 'boolean' && typeof v.reverse != 'number')
182+ return AttrType(n, 'reverse', 'boolean')
183+
184+ // .keys
185+ if (v.keys && typeof v.keys != 'boolean' && typeof v.keys != 'number')
186+ return AttrType(n, 'keys', 'boolean')
187+
188+ // .values
189+ if (v.values && typeof v.values != 'boolean' && typeof v.values != 'number')
190+ return AttrType(n, 'values', 'boolean')
191+ },
192+
193+ isBlockedOpts: function (v, n) {
194+ var err = this.get('object')(v, n)
195+ if (err)
196+ return err
197+
198+ // .source
199+ if (v.source && !ref.isFeed(v.source))
200+ return AttrType(n, 'source', 'feedId')
201+
202+ // .dest
203+ if (v.dest && !ref.isFeed(v.dest))
204+ return AttrType(n, 'dest', 'feedId')
205+ },
206+
207+ createFriendStreamOpts: function (v, n) {
208+ var err = this.get('object')(v, n)
209+ if (err)
210+ return err
211+
212+ // .start
213+ if (v.start && !ref.isFeed(v.start))
214+ return AttrType(n, 'start', 'feedId')
215+
216+ // .graph
217+ if (v.graph && typeof v.graph != 'string')
218+ return AttrType(n, 'graph', 'string')
219+
220+ // .dunbar
221+ if (v.dunbar && typeof v.dunbar != 'number')
222+ return AttrType(n, 'dunbar', 'number')
223+
224+ // .hops
225+ if (v.hops && typeof v.hops != 'number')
226+ return AttrType(n, 'hops', 'number')
227+ }
228+})
229+
230+
231+
232+
233+
234+
235+
236+
237+
238+
239+
plugin.jsView
@@ -1,0 +1,186 @@
1+var SecretStack = require('secret-stack')
2+var create = require('./create')
3+var ssbKeys = require('ssb-keys')
4+var path = require('path')
5+var osenv = require('osenv')
6+var mkdirp = require('mkdirp')
7+var rimraf = require('rimraf')
8+var mdm = require('mdmanifest')
9+//var cmdAliases = require('./lib/cli-cmd-aliases')
10+var valid = require('./lib/validators')
11+//var apidocs = require('./lib/apidocs.js')
12+var pkg = require('./package.json')
13+
14+function isString(s) { return 'string' === typeof s }
15+function isObject(o) { return 'object' === typeof o }
16+function isFunction (f) { return 'function' === typeof f }
17+// create SecretStack definition
18+var fs = require('fs')
19+var manifest = mdm.manifest(fs.readFileSync(path.join(__dirname, 'api.md'), 'utf-8'))
20+
21+manifest.seq = 'async'
22+manifest.usage = 'sync'
23+manifest.clock = 'async'
24+manifest.version = 'sync'
25+
26+console.log('manifest', manifest)
27+
28+module.exports = {
29+ manifest: manifest,
30+ permissions: {
31+ master: {allow: null, deny: null},
32+ anonymous: {allow: ['createHistoryStream'], deny: null}
33+ },
34+ init: function (api, opts) {
35+
36+ // .temp: use a /tmp data directory
37+ // (useful for testing)
38+ if(opts.temp) {
39+ var name = isString(opts.temp) ? opts.temp : ''+Date.now()
40+ opts.path = path.join(osenv.tmpdir(), name)
41+ rimraf.sync(opts.path)
42+ }
43+
44+ // load/create secure scuttlebutt data directory
45+ mkdirp.sync(opts.path)
46+
47+ if(!opts.keys)
48+ opts.keys = ssbKeys.generate('ed25519', opts.seed && Buffer.from(opts.seed, 'base64'))
49+
50+ if(!opts.path)
51+ throw new Error('opts.path *must* be provided, or use opts.temp=name to create a test instance')
52+
53+ // main interface
54+ var ssb = create(opts.path, opts, opts.keys)
55+ //treat the main feed as remote, because it's likely handled like that by others.
56+ var feed = ssb.createFeed(opts.keys, {remote: true})
57+ var _close = api.close
58+ var close = function (arg, cb) {
59+ if('function' === typeof arg) cb = arg
60+ // override to close the SSB database
61+ ssb.close(function (err) {
62+ if (err) throw err
63+ console.log("fallback to close")
64+ _close(cb) //multiserver doesn't take a callback on close.
65+ })
66+ }
67+
68+ function since () {
69+ var plugs = {}
70+ var sync = true
71+ for(var k in ssb) {
72+ if(ssb[k] && isObject(ssb[k]) && isFunction(ssb[k].since)) {
73+ plugs[k] = ssb[k].since.value
74+ sync = sync && (plugs[k] === ssb.since.value)
75+ }
76+ }
77+ return {
78+ since: ssb.since.value,
79+ plugins: plugs,
80+ sync: sync,
81+ }
82+ }
83+ var self
84+ return self = {
85+ id : feed.id,
86+ keys : opts.keys,
87+
88+ ready : function () {
89+ return ssb.ready.value
90+ },
91+
92+ progress : function () {
93+ return ssb.progress
94+ },
95+
96+ status : function () {
97+ return {progress: self.progress(), db: ssb.status, sync: since() }
98+ },
99+
100+ version : function () {
101+ return pkg.version
102+ },
103+
104+ //temporary!
105+ _flumeUse :
106+ function (name, flumeview) {
107+ ssb.use(name, flumeview)
108+ return ssb[name]
109+ },
110+
111+ // usage : valid.sync(usage, 'string?|boolean?'),
112+ close : valid.async(close),
113+
114+ publish : valid.async(feed.add, 'string|msgContent'),
115+ add : valid.async(ssb.add, 'msg'),
116+ queue : valid.async(ssb.queue, 'msg'),
117+ get : valid.async(ssb.get, 'msgLink|number|object'),
118+
119+ post : ssb.post,
120+ addMap : ssb.addMap,
121+
122+ since : since,
123+
124+ getPublicKey : ssb.getPublicKey,
125+ latest : ssb.latest,
126+ getLatest : valid.async(ssb.getLatest, 'feedId'),
127+ latestSequence : valid.async(ssb.latestSequence, 'feedId'),
128+ createFeed : ssb.createFeed,
129+ whoami : function () { return { id: feed.id } },
130+ query : ssb.query,
131+ createFeedStream : valid.source(ssb.createFeedStream, 'readStreamOpts?'),
132+ createHistoryStream : valid.source(ssb.createHistoryStream, ['createHistoryStreamOpts'], ['feedId', 'number?', 'boolean?']),
133+ createLogStream : valid.source(ssb.createLogStream, 'readStreamOpts?'),
134+ createUserStream : valid.source(ssb.createUserStream, 'createUserStreamOpts'),
135+ links : valid.source(ssb.links, 'linksOpts'),
136+ sublevel : ssb.sublevel,
137+ messagesByType : valid.source(ssb.messagesByType, 'string|messagesByTypeOpts'),
138+ createWriteStream : ssb.createWriteStream,
139+ getVectorClock : ssb.getVectorClock,
140+ getAtSequence : ssb.getAtSequence,
141+ addUnboxer : ssb.addUnboxer,
142+ box : ssb.box,
143+ }
144+ }
145+}
146+
147+/*
148+// live help RPC method
149+function usage (cmd) {
150+ var path = (cmd||'').split('.')
151+ if ((path[0] && apidocs[path[0]]) || (cmd && apidocs[cmd])) {
152+ // return usage for the plugin
153+ cmd = path.slice(1).join('.')
154+ return mdm.usage(apidocs[path[0]], cmd, { prefix: path[0] })
155+ }
156+ if (!cmd) {
157+ // return usage for all docs
158+ return Object.keys(apidocs).map(function (name) {
159+ if (name == '_')
160+ return mdm.usage(apidocs[name], null, { nameWidth: 20 })
161+
162+ var text = mdm.usage(apidocs[name], null, { prefix: name, nameWidth: 20 })
163+ return text.slice(text.indexOf('Commands:') + 10) // skip past the toplevel summary, straight to the cmd list
164+ }).join('\n\n')
165+ }
166+ // toplevel cmd usage
167+ cmd = cmdAliases[cmd] || cmd
168+ return mdm.usage(apidocs._, cmd)
169+}
170+*/
171+
172+//function createSsbServer() {
173+// return SecretStack({
174+// //this is just the default app key.
175+// //it can be overridden by passing a appKey as option
176+// //when creating a SsbServer instance.
177+// appKey: require('./lib/ssb-cap')
178+// })
179+// .use(SSB)
180+//}
181+//module.exports = createSsbServer()
182+//module.exports.createSsbServer = createSsbServer
183+
184+
185+
186+

Built with git-ssb-web