git ssb

2+

cel / scuttlebot.io



Commit a738ecf91d844ee886e94857a82177ab446113f1

add all module apis

Paul Frazee committed on 3/15/2016, 11:45:32 PM
Parent: 335022b47a65f2cc954c1ad739f3061a37f8bcd3

Files changed

markdown.jschanged
tmpl/apis/common/ssb-client.html.jsdeleted
tmpl/apis/common/ssb-client.mddeleted
tmpl/apis/common/ssb-feed.html.jsdeleted
tmpl/apis/common/ssb-feed.mddeleted
tmpl/apis/common/ssb-keys.html.jsdeleted
tmpl/apis/common/ssb-keys.mddeleted
tmpl/apis/common/ssb-msg-schemas.html.jsdeleted
tmpl/apis/common/ssb-msg-schemas.mddeleted
tmpl/apis/common/ssb-msgs.html.jsdeleted
tmpl/apis/common/ssb-msgs.mddeleted
tmpl/apis/common/ssb-ref.html.jsdeleted
tmpl/apis/common/ssb-ref.mddeleted
tmpl/apis/modules/graphmitter.html.jsadded
tmpl/apis/modules/graphmitter.mdadded
tmpl/apis/modules/mdmanifest.html.jsadded
tmpl/apis/modules/mdmanifest.mdadded
tmpl/apis/modules/muxrpc.html.jsadded
tmpl/apis/modules/muxrpc.mdadded
tmpl/apis/modules/muxrpcli.html.jsadded
tmpl/apis/modules/muxrpcli.mdadded
tmpl/apis/modules/secret-stack.html.jsadded
tmpl/apis/modules/secret-stack.mdadded
tmpl/apis/modules/ssb-client.html.jsadded
tmpl/apis/modules/ssb-client.mdadded
tmpl/apis/modules/ssb-config.html.jsadded
tmpl/apis/modules/ssb-config.mdadded
tmpl/apis/modules/ssb-feed.html.jsadded
tmpl/apis/modules/ssb-feed.mdadded
tmpl/apis/modules/ssb-keys.html.jsadded
tmpl/apis/modules/ssb-keys.mdadded
tmpl/apis/modules/ssb-msg-schemas.html.jsadded
tmpl/apis/modules/ssb-msg-schemas.mdadded
tmpl/apis/modules/ssb-msgs.html.jsadded
tmpl/apis/modules/ssb-msgs.mdadded
tmpl/apis/modules/ssb-ref.html.jsadded
tmpl/apis/modules/ssb-ref.mdadded
tmpl/leftnav.part.jschanged
tmpl/tabs.part.jschanged
markdown.jsView
@@ -37,8 +37,10 @@
3737 groupStart = i
3838 }
3939 }
4040 })
41+ if (groupStart)
42+ groups.push([groupStart, groupStart+1])
4143 return groups
4244 }
4345
4446 // replace <code> groupings with code-example nodes
tmpl/apis/common/ssb-client.html.jsView
@@ -1,8 +1,0 @@
1-var md = require('../../../markdown')
2-var page = require('../../page.part')
3-module.exports = () => page({
4- section: 'apis',
5- tab: 'apis-common',
6- path: '/apis/common/ssb-client.html',
7- content: md.doc(__dirname+'/ssb-client.md')
8-})
tmpl/apis/common/ssb-client.mdView
@@ -1,29 +1,0 @@
1-# ssb-client
2-
3-Scuttlebot client.
4-
5-```js
6-var ssbClient = require('ssb-client')
7-
8-// simplest usage, connect to localhost sbot
9-ssbClient(function (err, sbot) {
10- // ...
11-})
12-
13-// configuration:
14-var keys = ssbKeys.loadOrCreateSync('./app-private.key')
15-ssbClient(
16- keys, // optional, defaults to ~/.ssb/secret
17- {
18- host: 'localhost', // optional, defaults to localhost
19- port: 8008, // optional, defaults to 8008
20- key: keys.id // optional, defaults to keys.id
21- },
22- function (err, sbot) {
23- // ...
24- }
25-)
26-
27-```
28-
29-[View on Github](https://github.com/ssbc/ssb-client)
tmpl/apis/common/ssb-feed.html.jsView
@@ -1,8 +1,0 @@
1-var md = require('../../../markdown')
2-var page = require('../../page.part')
3-module.exports = () => page({
4- section: 'apis',
5- tab: 'apis-common',
6- path: '/apis/common/ssb-feed.html',
7- content: md.doc(__dirname+'/ssb-feed.md')
8-})
tmpl/apis/common/ssb-feed.mdView
@@ -1,34 +1,0 @@
1-# ssb-feed
2-
3-A publishing interface for scuttlebutt feeds.
4-
5-By default, Scuttlebot uses a "master" identity/feed, which `sbot.publish()` will append new messages to. If you want to manipulate additional feeds, you can load the keypair and then use this library to do so.
6-
7-## Example
8-
9-``` js
10-
11-var ssbFeed = require('ssb-feed')
12-var ssbClient = require('ssb-client')
13-var ssbKeys = require('ssb-keys')
14-
15-var alice = ssbKeys.generate()
16-ssbClient(function (err, sbot) {
17- var feed = ssbFeed(sbot, alice)
18-
19- // Post to alice's feed
20- feed.publish({
21- type: 'post',
22- text: 'hello world, I am alice.'
23- }, function (err) { ... })
24-
25- // Also available:
26- console.log(feed.id)
27- console.log(feed.keys)
28-})
29-```
30-
31-This example uses `ssb-client`, but, if you're embedding `scuttlebot` or the `secure-scuttlebutt` library into your process, you can use them locally.
32-
33-[View on Github](https://github.com/ssbc/ssb-feed)
34-
tmpl/apis/common/ssb-keys.html.jsView
@@ -1,8 +1,0 @@
1-var md = require('../../../markdown')
2-var page = require('../../page.part')
3-module.exports = () => page({
4- section: 'apis',
5- tab: 'apis-common',
6- path: '/apis/common/ssb-keys.html',
7- content: md.doc(__dirname+'/ssb-keys.md')
8-})
tmpl/apis/common/ssb-keys.mdView
@@ -1,78 +1,0 @@
1-# ssb-keys
2-
3-A common module for secure-scuttlebutt projects, provides an API to create or load elliptic-curve keypairs and to execute related crypto operations.
4-
5-```js
6-var ssbkeys = require('ssb-keys')
7-
8-ssbkeys.create(path, function(err, k) {
9- console.log(k) /* => {
10- id: String,
11- public: String,
12- private: String
13- }*/
14-})
15-
16-ssbkeys.load(path, function(err, k) {
17- console.log(k) /* => {
18- id: String,
19- public: String,
20- private: String
21- }*/
22-})
23-
24-var k = ssbkeys.createSync(path)
25-console.log(k) /* => {
26- id: String,
27- public: String,
28- private: String
29-}*/
30-
31-var k = ssbkeys.loadSync(path)
32-console.log(k) /* => {
33- id: String,
34- public: String,
35- private: String
36-}*/
37-
38-var k = ssbkeys.generate()
39-console.log(k) /* => {
40- id: String,
41- public: String,
42- private: String
43-}*/
44-
45-var hash = ssbkeys.hash(new Buffer('deadbeef', 'hex'))
46-ssbkeys.isHash(hash) // => true
47-
48-var sig = ssbkeys.sign(k, hash)
49-ssbkeys.verify(k.public, sig, hash) // => true
50-
51-var secret = new Buffer('deadbeef', 'hex')
52-ssbkeys.hmac(secret, k.private) // => String
53-
54-var obj = ssbkeys.signObj(k, { foo: 'bar' })
55-console.log(obj) /* => {
56- foo: 'bar',
57- signature: ...
58-} */
59-ssbkeys.verifyObj(k, obj) // => true
60-
61-var secret = new Buffer('deadbeef', 'hex')
62-var obj = ssbkeys.signObjHmac(secret, { foo: 'bar' })
63-console.log(obj) /* => {
64- foo: 'bar',
65- hmac: ...
66-} */
67-ssbkeys.verifyObjHmac(secret, obj) // => true
68-
69-var authRequest = ssbkeys.createAuth(k, 'client')
70-console.log(authRequest) /* => {
71- role: 'client',
72- ts: Number,
73- public: String,
74- signature: ...
75-} */
76-```
77-
78-[View on Github](https://github.com/ssbc/ssb-keys)
tmpl/apis/common/ssb-msg-schemas.html.jsView
@@ -1,8 +1,0 @@
1-var md = require('../../../markdown')
2-var page = require('../../page.part')
3-module.exports = () => page({
4- section: 'apis',
5- tab: 'apis-common',
6- path: '/apis/common/ssb-msg-schemas.html',
7- content: md.doc(__dirname+'/ssb-msg-schemas.md')
8-})
tmpl/apis/common/ssb-msg-schemas.mdView
@@ -1,34 +1,0 @@
1-# ssb-msg-schemas
2-
3-Functions to create common SSB messages.
4-
5-```js
6-var schemas = require('ssb-msg-schemas')
7-
8-schemas.post(
9- text,
10- root /*optional*/,
11- branch /*optional*/,
12- mentions /*optional*/,
13- recps /*optional*/,
14- channel /*optional*/
15-)
16-schemas.name(id, name)
17-schemas.image(id, imgLink)
18-schemas.follow(userId)
19-schemas.unfollow(userId)
20-schemas.block(userId)
21-schemas.unblock(userId)
22-schemas.vote(id, vote, reason /*optional*/)
23-schemas.pub(id, host, port)
24-```
25-
26-Related docs:
27- - [Message schemas](/docs/advanced/message-schemas.html)
28- - [Type: post](/docs/message-types/post.html)
29- - [Type: about](/docs/message-types/about.html)
30- - [Type: contact](/docs/message-types/contact.html)
31- - [Type: vote](/docs/message-types/vote.html)
32- - [Type: pub](/docs/message-types/pub.html)
33-
34-[View on Github](https://github.com/ssbc/ssb-msg-schemas)
tmpl/apis/common/ssb-msgs.html.jsView
@@ -1,8 +1,0 @@
1-var md = require('../../../markdown')
2-var page = require('../../page.part')
3-module.exports = () => page({
4- section: 'apis',
5- tab: 'apis-common',
6- path: '/apis/common/ssb-msgs.html',
7- content: md.doc(__dirname+'/ssb-msgs.md')
8-})
tmpl/apis/common/ssb-msgs.mdView
@@ -1,132 +1,0 @@
1-# ssb-msgs
2-
3-Message-processing tools for secure-scuttlebutt
4-
5-```js
6-var mlib = require('ssb-msgs')
7-```
8-
9-### indexLinks
10-
11-```js
12-mlib.indexLinks(
13- msg: Object,
14- {
15- rel: optional String
16- msg: optional Bool|String
17- feed: optional Bool|String
18- ext: optional Bool|String
19- },
20- each: Function(link: Object, rel: String)
21-)
22-```
23-
24-Traverses a message and runs the `each` function on all found links. All `opts` fields are optional. `Opts` may also be a string, in which case it is the rel attribute.
25-
26-```js
27-// assume %msgid and @feedid a well-formed
28-var msg = {
29- foo: { link: '%msgid' },
30- bar: [{ link: '@feedid' }]
31-}
32-function print (obj, rel) {
33- console.log(rel, obj.link)
34-}
35-mlib.indexLinks(msg, print)
36-// => foo %msgid
37-// => bar @feedid
38-mlib.indexLinks(msg, 'foo', print)
39-// => foo %msgid
40-mlib.indexLinks(msg, { rel: 'foo' }, print)
41-// => foo %msgid
42-mlib.indexLinks(msg, { feed: true }, print)
43-// => bar @feedid
44-mlib.indexLinks(msg, { feed: '@feedid' }, print)
45-// => bar @feedid
46-```
47-
48-### links
49-
50-```js
51-links(obj: Any, [requiredAttr: String])
52-```
53-
54-Helper to get links from a message in a regular array form.
55-
56-```js
57-var msg = {
58- foo: { link: '%msgid' },
59- bar: [{ link: '@feedid' }]
60-}
61-mlib.links(msg.foo) // => [{ link: '%msgid' }]
62-mlib.links(msg.bar) // => [{ link: '@feedid' }]
63-mlib.links(msg.bar, 'feed') // => [{ link: '@feedid' }]
64-mlib.links(msg.bar, 'msg') // => []
65-mlib.links(msg.baz) // => []
66-```
67-
68-### link
69-
70-```js
71-link(obj: Any, [requiredAttr: String])
72-```
73-
74-Helper to get a link from a message in a regular object form. If an array is found, will use the first element.
75-
76-```js
77-var msg = {
78- foo: { link: '%msgid' },
79- bar: [{ link: '@feedid' }]
80-}
81-mlib.link(msg.foo) // => { link: '%msgid' }
82-mlib.link(msg.bar) // => { link: '@feedid' }
83-mlib.link(msg.bar, 'feed') // => { link: '@feedid' }
84-mlib.link(msg.bar, 'msg') // => null
85-mlib.link(msg.baz) // => null
86-```
87-
88-### isLink
89-
90-```js
91-isLink(obj: Any, [requiredAttr: String])
92-```
93-
94-Predicate to test whether an object is a well-formed link. Returns false if given an array.
95-
96-```js
97-var msg = {
98- foo: { link: '%msgid' },
99- bar: [{ link: '@feedid' }]
100-}
101-mlib.isLink(msg.foo) // => true
102-mlib.isLink(msg.bar) // => true
103-mlib.isLink(msg.bar, 'feed') // => true
104-mlib.isLink(msg.bar, 'msg') // => false
105-mlib.isLink(msg.baz) // => false
106-```
107-
108-### linksTo
109-
110-```js
111-linksTo(a: Message, b: Message)
112-```
113-
114-Get link objects pointing from `a` to `b`.
115-
116-```js
117-mlib.linksTo(msgA, msgB) // => [{ link: '%msgB-id' }]
118-```
119-
120-### relationsTo
121-
122-```js
123-relationsTo(a: Message, b: Message)
124-```
125-
126-Get relations of links pointing from `a` to `b`.
127-
128-```js
129-mlib.relationsTo(msgA, msgB) // => ['fooRelation']
130-```
131-
132-[View on Github](https://github.com/ssbc/ssb-msgs)
tmpl/apis/common/ssb-ref.html.jsView
@@ -1,8 +1,0 @@
1-var md = require('../../../markdown')
2-var page = require('../../page.part')
3-module.exports = () => page({
4- section: 'apis',
5- tab: 'apis-common',
6- path: '/apis/common/ssb-ref.html',
7- content: md.doc(__dirname+'/ssb-ref.md')
8-})
tmpl/apis/common/ssb-ref.mdView
@@ -1,32 +1,0 @@
1-# ssb-ref
2-
3-Check if a string is a valid ssb-reference.
4-
5-``` js
6-var ref = require('ssb-ref')
7-
8-// Check if a string is a valid ref
9-ref.isLink(str)
10-
11-// Check if a string is a feed id
12-ref.isFeedId(str)
13-
14-// Check if a string is a message id
15-ref.isMsgId(str)
16-
17-// Check if a string is a blob id
18-ref.isBlobId(str)
19-
20-// Get the type of the reference
21-ref.type(str) == 'feed'
22-ref.type(str) == 'msg'
23-ref.type(str) == 'blob'
24-ref.type('not-a-link') == false
25-
26-// Extract a ref out of a url
27-// (Url-encoding is supported)
28-ref.extract(url)
29- == '%pGzeEydYdHjKW1iIchR0Yumydsr3QSp8+FuYcwVwi8Q=.sha256'
30-```
31-
32-[View on Github](https://github.com/ssbc/ssb-ref)
tmpl/apis/modules/graphmitter.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/graphmitter.html',
7+ content: md.doc(__dirname+'/graphmitter.md')
8+})
tmpl/apis/modules/graphmitter.mdView
@@ -1,0 +1,54 @@
1+# graphmitter
2+
3+```js
4+var Graphmitter = require('graphmitter')
5+var g = Graphmitter()
6+
7+// create edges
8+g.edge(1, 2).edge(2, 3).edge(3, 4)
9+
10+// delete an edge
11+g.del(3, 4)
12+
13+// iterate each node
14+g.each(console.log)
15+// => 1 { edges: { '2': true } }
16+// => 2 { edges: { '3': true } }
17+// => 3 { edges: { '2': true } }
18+// => 4 { edges: {} }
19+
20+// get full structure
21+g.toJSON() /* =>
22+{ '1': { '2': true },
23+ '2': { '3': true },
24+ '3': {},
25+ '4': {} }
26+*/
27+
28+// see connected nodes from a start node, including # of hops
29+g.traverse({ start: 1 }) // => { '1': 0, '2': 1, '3': 2 }
30+g.traverse({ start: 2 }) // => { '2': 0, '3': 1 }
31+g.traverse({ start: 1, hops: 1 }) // => { '1': 0, '2': 1 }
32+g.traverse({ start: 1, max: 2 }) // => { '1': 0, '2': 1 }
33+
34+// rank the connectedness of nodes using a pagerank derivative
35+g.rank() /* =>
36+{ '1': 0.037500000000000006,
37+ '2': 0.25,
38+ '3': 0.25,
39+ '4': 0.037500000000000006 }
40+*/
41+g.edge(3, 2)
42+g.rank() /* =>
43+{ '1': 0.037500000000000006,
44+ '2': 0.4625,
45+ '3': 0.25,
46+ '4': 0.037500000000000006 }
47+*/
48+
49+// helper to generate a random graph
50+Graphmitter.random(100, 100) // 100 nodes, 100 edges
51+```
52+
53+
54+[View on Github](https://github.com/ssbc/graphmitter)
tmpl/apis/modules/mdmanifest.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/mdmanifest.html',
7+ content: md.doc(__dirname+'/mdmanifest.md')
8+})
tmpl/apis/modules/mdmanifest.mdView
@@ -1,0 +1,181 @@
1+# mdmanifest
2+
3+Uses a regular markdown form to produce muxrpc manifests and cli usage descriptions.
4+
5+The form:
6+
7+```markdown
8+# api-name
9+
10+Api short description.
11+
12+Api long, multiline description (optional).
13+Api long, multiline description (optional).
14+Api long, multiline description (optional).
15+
16+## method-name: type
17+
18+Method short description.
19+
20+```bash
21+bash usage (optional)
22+``` --
23+
24+```js
25+js usage (optional)
26+``` --
27+
28+Method long, multiline description (optional).
29+Method long, multiline description (optional).
30+Method long, multiline description (optional).
31+```
32+
33+Example:
34+
35+```markdown
36+# example-api
37+
38+Example API, v1.0.0.
39+
40+This is an example API, written by Paul Frazee.
41+It's not a real API, but it would work with muxrpc.
42+
43+## ping: async
44+
45+Pings a target machine.
46+
47+```bash
48+ping {target string} [-n number]
49+``` --
50+
51+```js
52+ping(target, { n: })
53+``` --
54+
55+ - target: string, an IPv4/IPv6 address
56+ - opts:
57+ - n: optional number, how many times to ping
58+
59+Sends ICMP ping messages to the given target.
60+Will wait 1 second between pings.
61+
62+## listen: source
63+
64+Listens for pings.
65+
66+```bash
67+listen
68+``` --
69+
70+```js
71+listen()
72+``` --
73+
74+Will emit a string describing incoming pings, as they occur.
75+```
76+
77+The api:
78+
79+```js
80+var mdm = require('mdmanifest')
81+
82+mdm.muxrpcManifest(exampleMd)
83+/* => {
84+ ping: 'async',
85+ listen: 'source'
86+}*/
87+
88+mdm.usage(exampleMd)
89+/* =>
90+Example API, v1.0.0.
91+
92+This is an example API, written by Paul Frazee.
93+It's not a real API, but it would work with muxrpc.
94+
95+Commands:
96+
97+ - ping Pings a target machine.
98+ - listen Listens for pings.
99+*/
100+
101+mdm.usage(exampleMd, { prefix: 'foo' })
102+/* =>
103+Example API, v1.0.0.
104+
105+This is an example API, written by Paul Frazee.
106+It's not a real API, but it would work with muxrpc.
107+
108+Commands:
109+
110+ - foo.ping Pings a target machine.
111+ - foo.listen Listens for pings.
112+*/
113+
114+mdm.usage(exampleMd, { nameWidth: 20 })
115+/* =>
116+Example API, v1.0.0.
117+
118+This is an example API, written by Paul Frazee.
119+It's not a real API, but it would work with muxrpc.
120+
121+Commands:
122+
123+ - ping Pings a target machine.
124+ - listen Listens for pings.
125+*/
126+
127+mdm.usage(exampleMd, 'ping')
128+/* =>
129+Pings a target machine.
130+
131+ping {target string} [-n number]
132+
133+- target: string, an IPv4/IPv6 address
134+- opts:
135+ - n: optional number, how many times to ping
136+
137+Sends ICMP ping messages to the given target.
138+Will wait 1 second between pings.
139+*/
140+
141+mdm.html(exampleMd) // standard HTML output
142+```
143+
144+Command-line usage:
145+
146+```bash
147+$ ./mdm.js manifest ./test/valid-example.md
148+{
149+ "ping": "async",
150+ "listen": "source"
151+}
152+
153+$ ./mdm.js html ./test/valid-example.md
154+<h1>example-api</h1>
155+<p>Example API, v1.0.0.</p>
156+...
157+
158+$ ./mdm.js usage ./test/valid-example.md
159+Example API, v1.0.0.
160+
161+This is an example API, written by Paul Frazee.
162+It's not a real API, but it would work with muxrpc.
163+
164+Commands:
165+ ping Pings a target machine.
166+ listen Listens for pings.
167+
168+$ ./mdm.js usage ./test/valid-example.md ping
169+Pings a target machine.
170+
171+ping {target string} [-n number]
172+
173+- target: string, an IPv4/IPv6 address
174+- opts:
175+ - n: optional number, how many times to ping
176+
177+Sends ICMP ping messages to the given target.
178+Will wait 1 second between pings.
179+```
180+
181+[View on Github](https://github.com/ssbc/mdmanifest)
tmpl/apis/modules/muxrpc.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/muxrpc.html',
7+ content: md.doc(__dirname+'/muxrpc.md')
8+})
tmpl/apis/modules/muxrpc.mdView
@@ -1,0 +1,149 @@
1+# muxrpc
2+
3+Combined rpc and multiplexing, with pull-streams.
4+
5+
6+## example
7+
8+``` js
9+
10+var MRPC = require('muxrpc')
11+var pull = require('pull-stream')
12+
13+//we need a manifest of methods we wish to expose.
14+var api = {
15+ //async is a normal async function
16+ hello: 'async',
17+
18+ //source is a pull-stream (readable)
19+ stuff: 'source'
20+
21+ //TODO: sink and duplex pull-streams
22+}
23+
24+//pass the api into the constructor,
25+//and then pass the object you are wrapping
26+//(if there is a local api)
27+var client = MRPC(api, null) () //remoteApi, localApi
28+var server = MRPC(null, api) ({
29+ hello: function (name, cb) {
30+ cb(null, 'hello, ' + name + '!')
31+ },
32+ stuff: function () {
33+ return pull.values([1, 2, 3, 4, 5])
34+ }
35+})
36+
37+var a = client.createStream()
38+var b = server.createStream()
39+
40+pull(a, b, a) //pipe together
41+
42+client.hello('world', function (err, value) {
43+ if(err) throw err
44+ console.log(value)
45+ // hello, world!
46+})
47+
48+pull(client.stuff(), pull.drain(console.log))
49+// 1
50+// 2
51+// 3
52+// 4
53+// 5
54+```
55+
56+## Manifest
57+
58+like multilevel, a [manifest is required](https://github.com/juliangruber/multilevel#plugins)
59+except it works a little differently, and since muxrpc works with any api,
60+not assuming leveldb then you must write the manifest yourself.
61+
62+The manifest is simply an object mapping to strings, or nested objects.
63+
64+``` js
65+{
66+ //a function with a callback.
67+ foo: 'async',
68+
69+ //a function that returns a value
70+ //(note this is converted to
71+ // an async function for the client)
72+ bar: 'sync',
73+
74+ //a source pull-stream (aka, readable)
75+ allTheFoos: 'source',
76+
77+ //a sink pull-stream (aka, writable)
78+ writeFoos: 'sink',
79+
80+ //a duplex pull-stream
81+ fooPhone: 'duplex',
82+
83+ //create nested objects like this:
84+ bar: {
85+ ...
86+ }
87+}
88+
89+```
90+
91+## Permissions
92+
93+If you are exposing an api over a network connection,
94+then you probably want some sort of authorization system.
95+`muxrpc@4` and earlier had a `rpc.permissions()` method on
96+the rpc object, but this has been removed. Now you must
97+provide a permissions object, which has methods `{pre, post}`.
98+`pre` is called with the path and arguments before the api
99+method is actually called, and if it returns false, then the
100+user gets an error and the method is not called.
101+
102+This is much more flexible than attaching a standard permissions
103+method--now all methods on the rpc object act the same (call remote
104+methods) and it's possible to have a method named "permissions"
105+
106+A helper module for providing permissions is provided,
107+this enables you to update permissions on the fly
108+``` js
109+
110+var Permissions = require('muxrpc/permissions')
111+
112+var api = {
113+ foo: 'async',
114+ bar: 'async',
115+ auth: 'async'
116+}
117+
118+//set initial settings
119+var perms = Perms({allow: ['auth']})
120+
121+var rpc = muxrpc(null, api, serializer)({
122+ foo: function (val, cb) {
123+ cb(null, {okay: 'foo'})
124+ },
125+ bar: function (val, cb) {
126+ cb(null, {okay: 'bar'})
127+ },
128+ auth: function (pass) {
129+ //implement an auth function that sets the permissions,
130+ //using allow or deny lists.
131+
132+ if(pass === 'whatever')
133+ perms({deny: ['bar']}) //allow everything except "bar"
134+ else if(pass === 's3cr3tz')
135+ perms({}) //allow everything!!!
136+ else return cb(new Error('ACCESS DENIED'))
137+
138+ //else we ARE authorized.
139+ cb(null, 'ACCESS GRANTED')
140+ }
141+})
142+
143+//Get a stream to connect to the remote.
144+//As in the above example!
145+var ss = rpc.createStream()
146+
147+```
148+
149+[View on Github](https://github.com/ssbc/muxrpc)
tmpl/apis/modules/muxrpcli.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/muxrpcli.html',
7+ content: md.doc(__dirname+'/muxrpcli.md')
8+})
tmpl/apis/modules/muxrpcli.mdView
@@ -1,0 +1,144 @@
1+# muxrpcli
2+
3+Command-line interface to [muxrpc](https://github.com/ssbc/muxrpc) servers.
4+Works by converting the command-line parameters into args for the RPC calls.
5+Also adds some standard behaviors for usage calls.
6+
7+**Standard Switches**:
8+
9+ - `--oneline` put json output on one line.
10+ - `-h / --help` usage.
11+
12+## CLI Parameters
13+
14+Parameters are parsed with [minimist](https://www.npmjs.com/package/minimist).
15+The first positional param is mapped to the rpc command.
16+Any subsequent positional params are passed as arguments.
17+Then, the object constructed by the named parameters (if there are any) is passed as the last argument.
18+
19+Examples:
20+
21+```bash
22+$ program command arg1 arg2
23+invokes server.command("arg1", "arg2")
24+
25+$ program command -a beep -b boop
26+invokes server.command({ a: "beep", b: "boob" })
27+
28+$ program command arg1 arg2 -a beep -b boop
29+invokes server.command("arg1", "arg2", {
30+ a: "beep",
31+ b: "boob"
32+})
33+
34+$ program command -a beep -b boop arg1 arg2
35+invokes server.command("arg1", "arg2", {
36+ a: "beep",
37+ b: "boob"
38+})
39+```
40+
41+If a stream is supplied to stdin, it will be parsed as JSON and used instead of the CLI parameters.
42+
43+```bash
44+$ echo '{"a":"beep","b":"boop"}' | program command
45+invokes `server.command({ a: "beep", b: "boob" })'
46+```
47+
48+
49+## Usage calls
50+
51+Usage-calls are the help which is output when a command fails, or when help is requested.
52+They are used in the following situations:
53+
54+ - If the command does not exist in the RPC server's manifest, does a top-level usage call.
55+ - If the command responses with a `TypeError`, `UsageError`, `BadParamError`, or `BadArgError`, does a usage call for that command.
56+ - If the `-h` or `--help` switches are given, does a toplevel or command usage call.
57+
58+A usage-call is a call to the `usage(cmd)` function on the RPC server.
59+A 'top-level' usage call will leave `cmd` falsey.
60+The `usage` method should return a string to display.
61+
62+
63+## Example rpc server
64+
65+```js
66+var zerr = require('zerr')
67+var MissingArgError = zerr('BadArg', '"%" is required')
68+var BadTypeError = zerr('BadArg', '"%" must be a valid %')
69+
70+var manifest = {
71+ usage: 'sync',
72+ whoami: 'sync',
73+ ping: 'async'
74+}
75+var api = {}
76+// muxrpc(null, manifest)(api) is called
77+
78+api.usage = function (cmd) {
79+ switch (cmd) {
80+ case 'whoami':
81+ return 'whoami. get your profile info.'
82+ case 'ping':
83+ return 'ping {target} [-n times]. '+
84+ 'send `n` pings to `target`, defaults to 1'
85+ }
86+ return [
87+ 'myexample usage:'
88+ ' - ' + api.usage('whoami'),
89+ ' - ' + api.usage('ping')
90+ ].join('\n')
91+}
92+
93+api.whoami = function() { return 'bob, obviously' }
94+
95+api.ping = function(target, opts, cb) {
96+ if (!target) return cb(MissingArgError('target'))
97+ if (!isAddress(target))
98+ return cb(BadTypeError('target', 'address'))
99+
100+ var n = 1
101+ if (opts && opts.n) {
102+ n = +opts.n
103+ if (isNaN(n)) return cb(BadTypeError('n', 'number'))
104+ }
105+
106+ // ...
107+}
108+```
109+
110+Here's how a session would behave with this server:
111+
112+```bash
113+$ myexample
114+myexample usage:
115+ - whoami. get your profile info.
116+ - ping {target} [-n times]. send `n` pings to `target`.
117+defaults to 1
118+
119+$ myexample whoami -h
120+whoami. get your profile info.
121+
122+$ myexample ping -h
123+ping {target} [-n times]. send `n` pings to `target`.
124+defaults to 1
125+
126+$ myexample whoami
127+bob, obviously
128+
129+$ myexample ping 127.0.0.1
130+...
131+
132+$ myexample ping 1123123123
133+[BadArgError: "target" must be a valid address]
134+ping {target} [-n times]. send `n` pings to `target`.
135+defaults to 1
136+
137+
138+$ myexample ping 127.0.0.1 -n foobar
139+[BadArgError: "n" must be a valid number]
140+ping {target} [-n times]. send `n` pings to `target`.
141+defaults to 1
142+```
143+
144+[View on Github](https://github.com/ssbc/muxrpcli)
tmpl/apis/modules/secret-stack.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/secret-stack.html',
7+ content: md.doc(__dirname+'/secret-stack.md')
8+})
tmpl/apis/modules/secret-stack.mdView
@@ -1,0 +1,124 @@
1+# secret-stack
2+
3+Create secure peer to peer networks using secret-handshakes.
4+
5+SecretStack is built on [secret-handshake](https://github.com/dominictarr/secret-handshake)
6+and [muxrpc](https://github.com/ssbc/muxrpc). This provides a framework
7+to make building secure, decentralized systems easier.
8+(such as [scuttlebot](https://github.com/ssbc/scuttlebot) which this was refactored out of ;)
9+
10+## Example
11+
12+``` js
13+var SecretStack = require('secret-stack')
14+
15+var createApp = SecretStack({
16+ appKey: appKey //32 random bytes
17+})
18+.use({
19+ //plugin
20+ //name of the plugin, this is where it will be "mounted"
21+ name: 'foo',
22+ //muxrpc manifest
23+ manifest: {
24+ bar: 'async'
25+ },
26+ //permissions will be merged into the main permissions,
27+ //prefixed with the plugin name.
28+ //so theirfore this becomes 'foo.bar'.
29+ permissions: {
30+ anonymous: [
31+ 'bar'
32+ ]
33+ }
34+ init: function (api, opts) {
35+ //set up and return some methods...
36+ return {
37+ bar: function (arg, cb) {
38+ //do something async
39+ cb(null, result)
40+ })
41+ }
42+ }
43+})
44+```
45+
46+## create = SecretStack(opts)
47+
48+initialize a new app factory.
49+opts must have a property `appKey` which should
50+be a high entropy (i.e. random) 32 byte value.
51+It is fixed for your app. Actors who do not know this value
52+will not be able to connect to instances of your app.
53+
54+### create.use(plugin)
55+
56+set up the factory by adding plugins. see the example above.
57+
58+### plugin.init (api, opts)
59+
60+each plugin init function is called in the order they where
61+added and it may return an object which is combined into the api.
62+if `plugin.name` is a string, then it's added as `api[plugin.name]=plugin.init(api, opts)`
63+else, it's merged with the api object.
64+
65+Note, each method on the api gets wrapped with [hoox](https://github.com/dominictarr/hoox)
66+so that plugins may intercept that function.
67+So far, the ways i have used this is to manage permissions,
68+for example, to extend the auth method (see below) or to filter
69+the output of a stream.
70+
71+### connect = create.createClient(opts)
72+
73+sometimes you need to create a connection using a different key pair,
74+and/or to connect without providing access for the remote to your local api.
75+`opts` must have a sodium ed25519 key pair, or a `seed` (32 byte random)
76+value, from which a private key will be generated.
77+
78+`connect` then takes the same arguments as `node.connect`
79+
80+### node = create (opts)
81+
82+create an actual instance! opts must have a `keys` property
83+which is a sodium ed25519 key pair.
84+
85+### node.getAddress()
86+
87+get a string representing the address of this node.
88+it will be `ip:port:<base64:pubkey>`.
89+
90+### node.connect(address, cb)
91+
92+create a rpc connection to another instance.
93+Address should be the form returned by `getAddress`
94+
95+### node.auth(publicKey, cb)
96+
97+Query what permissions a given public key is assigned.
98+it's not intended for this to be exposed over the network,
99+but rather to extend this method to create plugable permissions systems.
100+
101+``` js
102+node.auth.hook(function (auth, args) {
103+ var pub = args[0]
104+ var cb = args[1]
105+ //call the first auth fn, and then hook the callback.
106+ auth(pub, function (err, perms) {
107+ if(err) cb(err)
108+ //optionally set your own perms for this pubkey.
109+ else if(accepted)
110+ cb(null, permissions)
111+
112+ //or if you wish to reject them
113+ else if(rejected)
114+ cb(new Error('reject'))
115+
116+ //fallback to default
117+ //(the next hook, or the anonymous config, if defined)
118+ else
119+ cb()
120+ })
121+})
122+```
123+
124+[View on Github](https://github.com/ssbc/secret-stack)
tmpl/apis/modules/ssb-client.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/ssb-client.html',
7+ content: md.doc(__dirname+'/ssb-client.md')
8+})
tmpl/apis/modules/ssb-client.mdView
@@ -1,0 +1,29 @@
1+# ssb-client
2+
3+Scuttlebot client.
4+
5+```js
6+var ssbClient = require('ssb-client')
7+
8+// simplest usage, connect to localhost sbot
9+ssbClient(function (err, sbot) {
10+ // ...
11+})
12+
13+// configuration:
14+var keys = ssbKeys.loadOrCreateSync('./app-private.key')
15+ssbClient(
16+ keys, // optional, defaults to ~/.ssb/secret
17+ {
18+ host: 'localhost', // optional, defaults to localhost
19+ port: 8008, // optional, defaults to 8008
20+ key: keys.id // optional, defaults to keys.id
21+ },
22+ function (err, sbot) {
23+ // ...
24+ }
25+)
26+
27+```
28+
29+[View on Github](https://github.com/ssbc/ssb-client)
tmpl/apis/modules/ssb-config.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/ssb-config.html',
7+ content: md.doc(__dirname+'/ssb-config.md')
8+})
tmpl/apis/modules/ssb-config.mdView
@@ -1,0 +1,36 @@
1+# ssb-config
2+
3+Configuration module used by [`scuttlebot`](https://github.com/ssbc/scuttlebot).
4+
5+## example
6+
7+``` js
8+var config = require('ssb-config')
9+
10+// if you want to set up a test network, that
11+// doesn't collide with main ssb network,
12+// pass the name of that network in.
13+
14+var test_config = require('ssb-config/inject')(
15+ 'testnet', // name
16+ { port: 9999 } // opts
17+)
18+// you can also pass a second argument,
19+// which overrides the default opts.
20+```
21+
22+## Configuration
23+
24+* `host` *(string)* The domain or ip address for `sbot`. Defaults to your public ip address.
25+* `port` *(string|number)* The port for `sbot`. Defaults to `8008`.
26+* `timeout`: *(number)* Number of milliseconds a replication stream can idle before it's automatically disconnected. Defaults to `30000`.
27+* `pub` *(boolean)* Replicate with pub servers. Defaults to `true`.
28+* `local` *(boolean)* Replicate with local servers found on the same network via `udp`. Defaults to `true`.
29+* `friends.dunbar` *(number)* [`Dunbar's number`](https://en.wikipedia.org/wiki/Dunbar%27s_number). Number of nodes your instance will replicate. Defaults to `150`.
30+* `friends.hops` *(number)* How many friend of friend hops to replicate. Defaults to `3`.
31+* `gossip.connections` *(number)* How many other nodes to connect with at one time. Defaults to `2`.
32+* `path` *(string)* Path to the application data folder, which contains the private key, message attachment data (blobs) and the leveldb backend. Defaults to `$HOME/.ssb`.
33+
34+There are some configuration options for the sysadmins out there. All configuration is loaded via [`rc`](https://github.com/dominictarr/rc). You can pass any configuration value in as cli arg, env var, or in a file.
35+
36+[View on Github](https://github.com/ssbc/ssb-config)
tmpl/apis/modules/ssb-feed.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/ssb-feed.html',
7+ content: md.doc(__dirname+'/ssb-feed.md')
8+})
tmpl/apis/modules/ssb-feed.mdView
@@ -1,0 +1,34 @@
1+# ssb-feed
2+
3+A publishing interface for scuttlebutt feeds.
4+
5+By default, Scuttlebot uses a "master" identity/feed, which `sbot.publish()` will append new messages to. If you want to manipulate additional feeds, you can load the keypair and then use this library to do so.
6+
7+## Example
8+
9+``` js
10+
11+var ssbFeed = require('ssb-feed')
12+var ssbClient = require('ssb-client')
13+var ssbKeys = require('ssb-keys')
14+
15+var alice = ssbKeys.generate()
16+ssbClient(function (err, sbot) {
17+ var feed = ssbFeed(sbot, alice)
18+
19+ // Post to alice's feed
20+ feed.publish({
21+ type: 'post',
22+ text: 'hello world, I am alice.'
23+ }, function (err) { ... })
24+
25+ // Also available:
26+ console.log(feed.id)
27+ console.log(feed.keys)
28+})
29+```
30+
31+This example uses `ssb-client`, but, if you're embedding `scuttlebot` or the `secure-scuttlebutt` library into your process, you can use them locally.
32+
33+[View on Github](https://github.com/ssbc/ssb-feed)
34+
tmpl/apis/modules/ssb-keys.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/ssb-keys.html',
7+ content: md.doc(__dirname+'/ssb-keys.md')
8+})
tmpl/apis/modules/ssb-keys.mdView
@@ -1,0 +1,78 @@
1+# ssb-keys
2+
3+A common module for secure-scuttlebutt projects, provides an API to create or load elliptic-curve keypairs and to execute related crypto operations.
4+
5+```js
6+var ssbkeys = require('ssb-keys')
7+
8+ssbkeys.create(path, function(err, k) {
9+ console.log(k) /* => {
10+ id: String,
11+ public: String,
12+ private: String
13+ }*/
14+})
15+
16+ssbkeys.load(path, function(err, k) {
17+ console.log(k) /* => {
18+ id: String,
19+ public: String,
20+ private: String
21+ }*/
22+})
23+
24+var k = ssbkeys.createSync(path)
25+console.log(k) /* => {
26+ id: String,
27+ public: String,
28+ private: String
29+}*/
30+
31+var k = ssbkeys.loadSync(path)
32+console.log(k) /* => {
33+ id: String,
34+ public: String,
35+ private: String
36+}*/
37+
38+var k = ssbkeys.generate()
39+console.log(k) /* => {
40+ id: String,
41+ public: String,
42+ private: String
43+}*/
44+
45+var hash = ssbkeys.hash(new Buffer('deadbeef', 'hex'))
46+ssbkeys.isHash(hash) // => true
47+
48+var sig = ssbkeys.sign(k, hash)
49+ssbkeys.verify(k.public, sig, hash) // => true
50+
51+var secret = new Buffer('deadbeef', 'hex')
52+ssbkeys.hmac(secret, k.private) // => String
53+
54+var obj = ssbkeys.signObj(k, { foo: 'bar' })
55+console.log(obj) /* => {
56+ foo: 'bar',
57+ signature: ...
58+} */
59+ssbkeys.verifyObj(k, obj) // => true
60+
61+var secret = new Buffer('deadbeef', 'hex')
62+var obj = ssbkeys.signObjHmac(secret, { foo: 'bar' })
63+console.log(obj) /* => {
64+ foo: 'bar',
65+ hmac: ...
66+} */
67+ssbkeys.verifyObjHmac(secret, obj) // => true
68+
69+var authRequest = ssbkeys.createAuth(k, 'client')
70+console.log(authRequest) /* => {
71+ role: 'client',
72+ ts: Number,
73+ public: String,
74+ signature: ...
75+} */
76+```
77+
78+[View on Github](https://github.com/ssbc/ssb-keys)
tmpl/apis/modules/ssb-msg-schemas.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/ssb-msg-schemas.html',
7+ content: md.doc(__dirname+'/ssb-msg-schemas.md')
8+})
tmpl/apis/modules/ssb-msg-schemas.mdView
@@ -1,0 +1,34 @@
1+# ssb-msg-schemas
2+
3+Functions to create common SSB messages.
4+
5+```js
6+var schemas = require('ssb-msg-schemas')
7+
8+schemas.post(
9+ text,
10+ root /*optional*/,
11+ branch /*optional*/,
12+ mentions /*optional*/,
13+ recps /*optional*/,
14+ channel /*optional*/
15+)
16+schemas.name(id, name)
17+schemas.image(id, imgLink)
18+schemas.follow(userId)
19+schemas.unfollow(userId)
20+schemas.block(userId)
21+schemas.unblock(userId)
22+schemas.vote(id, vote, reason /*optional*/)
23+schemas.pub(id, host, port)
24+```
25+
26+Related docs:
27+ - [Message schemas](/docs/advanced/message-schemas.html)
28+ - [Type: post](/docs/message-types/post.html)
29+ - [Type: about](/docs/message-types/about.html)
30+ - [Type: contact](/docs/message-types/contact.html)
31+ - [Type: vote](/docs/message-types/vote.html)
32+ - [Type: pub](/docs/message-types/pub.html)
33+
34+[View on Github](https://github.com/ssbc/ssb-msg-schemas)
tmpl/apis/modules/ssb-msgs.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/ssb-msgs.html',
7+ content: md.doc(__dirname+'/ssb-msgs.md')
8+})
tmpl/apis/modules/ssb-msgs.mdView
@@ -1,0 +1,132 @@
1+# ssb-msgs
2+
3+Message-processing tools for secure-scuttlebutt
4+
5+```js
6+var mlib = require('ssb-msgs')
7+```
8+
9+### indexLinks
10+
11+```js
12+mlib.indexLinks(
13+ msg: Object,
14+ {
15+ rel: optional String
16+ msg: optional Bool|String
17+ feed: optional Bool|String
18+ ext: optional Bool|String
19+ },
20+ each: Function(link: Object, rel: String)
21+)
22+```
23+
24+Traverses a message and runs the `each` function on all found links. All `opts` fields are optional. `Opts` may also be a string, in which case it is the rel attribute.
25+
26+```js
27+// assume %msgid and @feedid a well-formed
28+var msg = {
29+ foo: { link: '%msgid' },
30+ bar: [{ link: '@feedid' }]
31+}
32+function print (obj, rel) {
33+ console.log(rel, obj.link)
34+}
35+mlib.indexLinks(msg, print)
36+// => foo %msgid
37+// => bar @feedid
38+mlib.indexLinks(msg, 'foo', print)
39+// => foo %msgid
40+mlib.indexLinks(msg, { rel: 'foo' }, print)
41+// => foo %msgid
42+mlib.indexLinks(msg, { feed: true }, print)
43+// => bar @feedid
44+mlib.indexLinks(msg, { feed: '@feedid' }, print)
45+// => bar @feedid
46+```
47+
48+### links
49+
50+```js
51+links(obj: Any, [requiredAttr: String])
52+```
53+
54+Helper to get links from a message in a regular array form.
55+
56+```js
57+var msg = {
58+ foo: { link: '%msgid' },
59+ bar: [{ link: '@feedid' }]
60+}
61+mlib.links(msg.foo) // => [{ link: '%msgid' }]
62+mlib.links(msg.bar) // => [{ link: '@feedid' }]
63+mlib.links(msg.bar, 'feed') // => [{ link: '@feedid' }]
64+mlib.links(msg.bar, 'msg') // => []
65+mlib.links(msg.baz) // => []
66+```
67+
68+### link
69+
70+```js
71+link(obj: Any, [requiredAttr: String])
72+```
73+
74+Helper to get a link from a message in a regular object form. If an array is found, will use the first element.
75+
76+```js
77+var msg = {
78+ foo: { link: '%msgid' },
79+ bar: [{ link: '@feedid' }]
80+}
81+mlib.link(msg.foo) // => { link: '%msgid' }
82+mlib.link(msg.bar) // => { link: '@feedid' }
83+mlib.link(msg.bar, 'feed') // => { link: '@feedid' }
84+mlib.link(msg.bar, 'msg') // => null
85+mlib.link(msg.baz) // => null
86+```
87+
88+### isLink
89+
90+```js
91+isLink(obj: Any, [requiredAttr: String])
92+```
93+
94+Predicate to test whether an object is a well-formed link. Returns false if given an array.
95+
96+```js
97+var msg = {
98+ foo: { link: '%msgid' },
99+ bar: [{ link: '@feedid' }]
100+}
101+mlib.isLink(msg.foo) // => true
102+mlib.isLink(msg.bar) // => true
103+mlib.isLink(msg.bar, 'feed') // => true
104+mlib.isLink(msg.bar, 'msg') // => false
105+mlib.isLink(msg.baz) // => false
106+```
107+
108+### linksTo
109+
110+```js
111+linksTo(a: Message, b: Message)
112+```
113+
114+Get link objects pointing from `a` to `b`.
115+
116+```js
117+mlib.linksTo(msgA, msgB) // => [{ link: '%msgB-id' }]
118+```
119+
120+### relationsTo
121+
122+```js
123+relationsTo(a: Message, b: Message)
124+```
125+
126+Get relations of links pointing from `a` to `b`.
127+
128+```js
129+mlib.relationsTo(msgA, msgB) // => ['fooRelation']
130+```
131+
132+[View on Github](https://github.com/ssbc/ssb-msgs)
tmpl/apis/modules/ssb-ref.html.jsView
@@ -1,0 +1,8 @@
1+var md = require('../../../markdown')
2+var page = require('../../page.part')
3+module.exports = () => page({
4+ section: 'apis',
5+ tab: 'apis-modules',
6+ path: '/apis/modules/ssb-ref.html',
7+ content: md.doc(__dirname+'/ssb-ref.md')
8+})
tmpl/apis/modules/ssb-ref.mdView
@@ -1,0 +1,32 @@
1+# ssb-ref
2+
3+Check if a string is a valid ssb-reference.
4+
5+``` js
6+var ref = require('ssb-ref')
7+
8+// Check if a string is a valid ref
9+ref.isLink(str)
10+
11+// Check if a string is a feed id
12+ref.isFeedId(str)
13+
14+// Check if a string is a message id
15+ref.isMsgId(str)
16+
17+// Check if a string is a blob id
18+ref.isBlobId(str)
19+
20+// Get the type of the reference
21+ref.type(str) == 'feed'
22+ref.type(str) == 'msg'
23+ref.type(str) == 'blob'
24+ref.type('not-a-link') == false
25+
26+// Extract a ref out of a url
27+// (Url-encoding is supported)
28+ref.extract(url)
29+ == '%pGzeEydYdHjKW1iIchR0Yumydsr3QSp8+FuYcwVwi8Q=.sha256'
30+```
31+
32+[View on Github](https://github.com/ssbc/ssb-ref)
tmpl/leftnav.part.jsView
@@ -55,17 +55,28 @@
5555 ${item(c, '/apis/scuttlebot/private.html', 'Private')}
5656 ${item(c, '/apis/scuttlebot/replicate.html', 'Replicate')}
5757 </ul>`
5858
59-module.exports['apis-common'] = (c) => `<ul class="nav">
60- ${item(c, '/apis/common/ssb-client.html', 'SSB-Client')}
61- ${item(c, '/apis/common/ssb-feed.html', 'SSB-Feed')}
62- ${item(c, '/apis/common/ssb-keys.html', 'SSB-Keys')}
63- ${item(c, '/apis/common/ssb-ref.html', 'SSB-Ref')}
64- ${item(c, '/apis/common/ssb-msgs.html', 'SSB-Msgs')}
65- ${item(c, '/apis/common/ssb-msg-schemas.html', 'SSB-Msg-Schemas')}
59+module.exports['apis-modules'] = (c) => `<ul class="nav">
60+ ${item(c, '/apis/modules/ssb-client.html', 'SSB-Client')}
61+ ${item(c, '/apis/modules/ssb-feed.html', 'SSB-Feed')}
62+ ${item(c, '/apis/modules/ssb-keys.html', 'SSB-Keys')}
63+ ${item(c, '/apis/modules/ssb-ref.html', 'SSB-Ref')}
64+ ${item(c, '/apis/modules/ssb-msgs.html', 'SSB-Msgs')}
65+ ${item(c, '/apis/modules/ssb-msg-schemas.html', 'SSB-Msg-Schemas')}
66+ ${item(c, '/apis/modules/ssb-config.html', 'SSB-Config')}
67+ ${item(c, '/apis/modules/secret-stack.html', 'Secret-Stack')}
68+ ${item(c, '/apis/modules/muxrpc.html', 'MuxRPC')}
69+ ${item(c, '/apis/modules/muxrpcli.html', 'MuxRPCCli')}
70+ ${item(c, '/apis/modules/mdmanifest.html', 'MDManifest')}
71+ ${item(c, '/apis/modules/graphmitter.html', 'Graphmitter')}
6672 </ul>`
6773
74+module.exports['apis-pull-stream'] = (c) => `<ul class="nav">
75+ ${item(c, '/apis/pull-stream/pull-stream.html', 'Pull-Stream')}
76+ ${item(c, '/apis/pull-stream/pull-ws-server.html', 'Pull-WS-Server')}
77+`
78+
6879 module.exports['guides-concepts'] = (c) => `<ul class="nav">
6980 ${item(c, '/guides/concepts/intro.html', 'Intro')}
7081 </ul>`
7182
tmpl/tabs.part.jsView
@@ -21,11 +21,11 @@
2121 </div>`
2222
2323 module.exports.apis = (c) => `<div class="tabs small">
2424 ${item(c, 'apis-scuttlebot', '/apis/scuttlebot/ssb.html', 'Scuttlebot')}
25- ${item(c, 'apis-common', '/apis/common/ssb-client.html', 'Common Modules')}
26- ${item(c, 'apis-internal', '/apis/internal/muxrpc.html', 'Internal Modules')}
27- ${item(c, 'apis-community', '/apis/community/ssbify.html', 'Community Modules')}
25+ ${item(c, 'apis-modules', '/apis/modules/ssb-client.html', 'Modules')}
26+ ${item(c, 'apis-pull-stream', '/apis/pull-stream/ssb-client.html', 'Pull Stream')}
27+ ${item(c, 'apis-community', '/apis/community/ssbify.html', 'Community')}
2828 </div>`
2929
3030 module.exports.apps = (c) => `<div class="tabs small">
3131 ${item(c, 'basics', '/basics/install-the-database.html', 'Basics')}

Built with git-ssb-web