gun-edge v0.8.8
Gun edge
Extra DSL extensions for Gun.js
Many of the snippets were extracted from Gun Snippets 0.3.x and upgraded to work with Gun +0.6
Some extra chain methods have been added, such as mapReduce and iterator.
Most async methods now come with a ES6 Promises or async/await (ES7) variant.
The Promise methods are prefixed with $.
Maturity
As of version 0.8.x, not all of the chain methods have been fully tested yet. Please help test them out and/or add more tests. Thanks.
Install
npm i -S gun-edge
Use
Assuming Babel or similar transpiler setup (2017)
To add all chain methods:
import Gun from 'gun/gun'
import chain from 'gun-edge'
chain(Gun)To control which chain methods to add:
import {
add
} from 'gun-edge'
add(Gun, 'date', 'fields')Import individual chain modules
import {
inspect,
addInspect
} from 'gun-edge/edge/inspect'
addInspect(Gun.chain)Require (Node.js)
Using require
const Gun = require('gun/gun')
require('gun-edge')(Gun)API extensions
Chain methods available:
Iteration
.each()- see each.timed(opts)- interval based recursive iteration on node (seetimed-iterator.test.js).mapReduce(options, cb, putCb, opt)- mapReduce on a bucket (see below).recurse(cb, filter)- recursively navigate bucket graph/tree structure
Operations
.count(numFun)- create a CRDT counter, see counter.copy(val)- make a copy/clone of a value.date(dateValue)- date field, see date.local(data, cb, opt)- store locally only, no peer sync.no(cb)- see no.value(cb, opt)- get the node value (no meta).valueAt(path, cb, opt): get value at thepath(no meta).valAt(path, cb, opt): get value at thepath.setAt(path, cb, opt): set value at thepath.putAt(path, cb, opt): put value at thepath.localFields()- get list of local field names (keys) in the bucket.fields(cb)- return fields to cb.soul()- return the soul (id) of the node.print(label)- print value to console (no meta). Note: You can setGun.log, by default:console.log
Promise enabled methods
ES6 Promise or ES7 async/await), always prefixed with $
.$fields(opt)- get fields (ie. property names).$iterate(opts)- iterate.$mapReduce(options, putCb, opt)- map/reduce.$no(opt)- blocks if no data, see no.$val(opt)- full value (with meta).$value(opt)- get value (no meta).$valueAt(path, opt)- get value at thepath(no meta).$recurse(filter)- recursive filter.$timed(opts)- timed recursion
Observable streams for superior Async flow control
Observable methods are also (currently) prefixed with $
Observable stream support is included for:
Example: Rx.js
// optional
let options = {
log: true,
op: 'live'
}
// or simply $rx(node) or even node.$rx()
let obs = $rx(node, options)
let subscription = obs
.subscribe(x => {
console.log({received: x})
})Useful internal Gun functions
Gun.obj.copy(val) - copy a value
Gun.obj.map(data, function(val, field){ ... } - map over a node
Gun.fn.is - check if something is a function
Gun.text.random() - generate random text
Gun.is.node.soul(data) - test if data has a soul (ie. is a Gun node)
Gun.node.soul(data) - return id of Gun node
Please add more internal Gun functions to this list for reference ;)
Useful chain methods
node.back() - go one level back/up in the graph
WIP
.out(navOpts, cb)- traverse edge (WIP).edge(navOpts/data)orlink- for linking nodes and traversing links/edges.filter(filterFun, cb)- filter fields
CSP Channels: WIP
CSP channel also included :)
The main idea is outlined here
CSP learning resources:
To start a process just pass a generator as a parameter to the go function.
By using the yield keyword, you can pause a process, freeing the main thread
Channels are queues. Whenever a process calls take on a channel, it pauses until a value is put into that channel.
Processes that put a value on a channel also pause until some other process uses take. Because channels are queues, when a process takes from a channel, the value will not be available for other processes to take. One process puts, one process takes. A channel can be buffered, which means that, for a given number of puts, a put will not make the process pause.
If the channel has a buffer of size 2, the third put will block the process, until someone takes from it.
See the test/channel/ folder for some test examples:
let size = 2
let buffer = csp.buffers.fixed(size)
// let buffer = csp.buffers.sliding(size)
// let buffer = csp.buffers.dropping(size)
// const promiseCh = csp.promiseChan();
// NOTE: optionally customize channel and buffer used
// let promiseCh = csp.chan(buffer)
promiseCh = $csp(node, {
// channel: promiseCh, // will use fixed(2) buffer by default
// log: true,
op: 'live',
// only put on channel when node value has a num field
condition: (val) => val.num
})
node.timed({
maxNum,
logging: true,
cb: resolve
})
let num = 0
let condition = () => num < 5
// Please help improved this!!!
csp.go(function* () {
while (condition()) {
const value = yield csp.take(promiseCh)
console.log('value', value)
}
})mapReduce
See full mapReduce guide
Contributing
Compile/Build
The project includes a gulpfile configured to use Babel 6.
All /src files are compiled to /dist including source maps.
Scripts:
- start:
npm start - build:
npm run build(ie. compile) - watch and start:
npm run watch - watch and build:
npm run watch:b
Run Tests
npm test or simply ava test
Examples
The /examples folder will at some point include some example projects, including a web page (with live reload)
Sandbox
For playing around...
Docs
Various ideas sketched out in /docs
License
MIT Kristian Mandrup