git ssb

0+

mixmix / scuttle-inject



Commit f0668f9a8e9bd4c90739103f1c6582a4a483d2ae

initial release

mix irving committed on 6/18/2018, 2:26:26 AM

Files changed

.gitignoreadded
README.mdadded
index.jsadded
package-lock.jsonadded
package.jsonadded
.gitignoreView
@@ -1,0 +1,1 @@
1 +node_modules
README.mdView
@@ -1,0 +1,61 @@
1 +# Scuttle-inject
2 +
3 +Takes a particular sort of nested tree of methods and returns a version of that tree which has a scuttlebutt server injected into each method.
4 +
5 +This pattern means you only need to inject a scuttlebot once, makes it easier to test your methods, and handles being able to inject different sorts of server for you.
6 +
7 +## Example usage
8 +
9 +```js
10 +// methods.js
11 +module.exports = {
12 + async: {
13 + publishPoll: function (server) {
14 + return function (opts, cb) {
15 + // check the opts before publishing
16 + const cleanOpts = clean(opts)
17 +
18 + server.publish(cleanOpts, cb)
19 + }
20 + },
21 + // getPoll: (key, cb) => {}
22 + },
23 + pull: {
24 + myPolls: function (server) {
25 + return function (opts) {
26 + const defaultQuery = { ... }
27 + const query = Object.assign({}, defaultQuery, opts)
28 +
29 + return server.query.read(opts)
30 + }
31 + }
32 + // openPolls: (opts) => {},
33 + // closedPolls: (opts) => {}
34 + }
35 +}
36 +```
37 +
38 +Injecting server once (somehwhere high-level):
39 +```js
40 +const inject = require('scuttle-inject')
41 +cosnt methods = require('./methods')
42 +
43 +const scuttle = inject(methods, server)
44 +// assume you're in a context where you have a server
45 +```
46 +
47 +Using the scuttle helper:
48 +```
49 +const opts = { ... }
50 +scuttle.async.publishPoll(opts, cb)
51 +```
52 +
53 +## API
54 +
55 +`inject(server, methods, pluginDeps)`
56 +
57 +- `server` - a `scuttlebot` server, an `ssb-client` connection to a server, or an observeable which will resolve into a server connection (such as Patchcore's `sbot.obs.connection`)
58 +
59 +- `methods` - an Object nested at least 2 levels deep, where there must be one layer which specifies the `type` of method. Valid types are : `sync`, `async`, `pull`, `obs`
60 +
61 +- `pluginDeps` (optional) - an Array of plugins apis the scuttlebot must have for your methods to work. e.g. `['query']` will check that `sbot.query` has methods which are accessible.
index.jsView
@@ -1,0 +1,81 @@
1 +const { each, map } = require('libnested')
2 +const onceTrue = require('mutant/once-true')
3 +const watch = require('mutant/watch')
4 +const Value = require('mutant/value')
5 +const assert = require('assert')
6 +const Defer = require('pull-defer').source
7 +
8 +// auto-inject the ssb-server to all methods to reduce repitition
9 +module.exports = function inject (server, methods, pluginDeps = []) {
10 + checkMethods(methods)
11 +
12 + switch (typeof server) {
13 + case 'object': // just a classic ssb server
14 + checkPlugins(server, pluginDeps)
15 + return map(methods, (fn, path) => fn(server))
16 +
17 + case 'function': // hopefully an observeable which will contain an ssb server
18 + return injectObsServer(server, methods)
19 +
20 + default:
21 + throw new Error('scuttle-poll expects an ssb server (or obs that contains one)')
22 + }
23 +}
24 +
25 +function injectObsServer (server, methods, pluginDeps = []) {
26 + onceTrue(server, server => checkPlugins(server, pluginDeps))
27 +
28 + return map(methods, (fn, path) => {
29 + if (path.includes('async')) {
30 + return function () {
31 + onceTrue(
32 + server,
33 + server => fn(server).apply(null, arguments)
34 + )
35 + }
36 + }
37 +
38 + if (path.includes('pull')) {
39 + return function () {
40 + const source = Defer()
41 + onceTrue(
42 + server,
43 + server => {
44 + var _source = fn(server).apply(null, arguments)
45 + source.resolve(_source)
46 + }
47 + )
48 + return source
49 + }
50 + }
51 +
52 + // NOTE - both `obs` and `sync` methods will return observeables
53 + return function () {
54 + var result = Value({})
55 + // var result = Struct({}) // WARNING - this shouldn't be copied for other apps, only works with obs.get method here. Probably breaks sync.isBlog
56 + onceTrue(
57 + server,
58 + server => {
59 + var res = fn(server).apply(null, arguments)
60 + watch(res, res => result.set(res))
61 + }
62 + )
63 + return result
64 + }
65 + })
66 +}
67 +
68 +function checkMethods (methods) {
69 + const server = { backlinks: 'fake' }
70 + each(methods, (fn, path) => {
71 + assert(typeof fn === 'function', `${path.join('.')}: expect each method to be a function`)
72 + const injectedMethod = fn(server)
73 + assert(typeof injectedMethod === 'function', `${path.join('.')}: expect each method to be a closure which accepts a server and returns a function`)
74 + })
75 +}
76 +
77 +function checkPlugins (server, pluginDeps) {
78 + pluginDeps.forEach(p => {
79 + if (!server[p]) throw new Error(`scuttle-blog needs a scuttlebot server with the ${p} plugin installed`)
80 + })
81 +}
package-lock.jsonView
@@ -1,0 +1,37 @@
1 +{
2 + "name": "scuttle-inject",
3 + "version": "0.0.1",
4 + "lockfileVersion": 1,
5 + "requires": true,
6 + "dependencies": {
7 + "browser-split": {
8 + "version": "0.0.1",
9 + "resolved": "https://registry.npmjs.org/browser-split/-/browser-split-0.0.1.tgz",
10 + "integrity": "sha1-ewl1dPjj6tYG+0Zk5krf3aKYGpM="
11 + },
12 + "libnested": {
13 + "version": "1.3.2",
14 + "resolved": "https://registry.npmjs.org/libnested/-/libnested-1.3.2.tgz",
15 + "integrity": "sha512-YvMQglpk/DyB8vFL5usJe6IZTqOU/fRopoUpoOt9TavYh5CaGdTp6zYqrA7DW8tHmZAr8fj+pDXbHBwlVrcVXQ=="
16 + },
17 + "mutant": {
18 + "version": "3.22.1",
19 + "resolved": "https://registry.npmjs.org/mutant/-/mutant-3.22.1.tgz",
20 + "integrity": "sha1-kEh1RvcAs8KKqApD0c99M48wdYE=",
21 + "requires": {
22 + "browser-split": "0.0.1",
23 + "xtend": "^4.0.1"
24 + }
25 + },
26 + "pull-defer": {
27 + "version": "0.2.2",
28 + "resolved": "https://registry.npmjs.org/pull-defer/-/pull-defer-0.2.2.tgz",
29 + "integrity": "sha1-CIew/7MK8ypW2+z6csFnInHwexM="
30 + },
31 + "xtend": {
32 + "version": "4.0.1",
33 + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz",
34 + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68="
35 + }
36 + }
37 +}
package.jsonView
@@ -1,0 +1,29 @@
1 +{
2 + "name": "scuttle-inject",
3 + "version": "0.0.1",
4 + "description": "an helper for injecting a scuttlebot server into all your scuttle-methods",
5 + "main": "index.js",
6 + "scripts": {
7 + "test": "echo \"Error: no test specified\" && exit 1"
8 + },
9 + "repository": {
10 + "type": "git",
11 + "url": "git+https://github.com/ssbc/scuttle-inject.git"
12 + },
13 + "keywords": [
14 + "scuttlebutt",
15 + "scuttle",
16 + "helper"
17 + ],
18 + "author": "mixmix",
19 + "license": "AGPL-3.0",
20 + "bugs": {
21 + "url": "https://github.com/ssbc/scuttle-inject/issues"
22 + },
23 + "homepage": "https://github.com/ssbc/scuttle-inject#readme",
24 + "dependencies": {
25 + "libnested": "^1.3.2",
26 + "mutant": "^3.22.1",
27 + "pull-defer": "^0.2.2"
28 + }
29 +}

Built with git-ssb-web