Skip to content

kristianmandrup/gun-edge

Repository files navigation

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 (see timed-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 the path (no meta)
  • .valAt(path, cb, opt) : get value at the path
  • .setAt(path, cb, opt) : set value at the path
  • .putAt(path, cb, opt) : put value at the path
  • .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 set Gun.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 the path (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) or link - 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

About

API helpers for Gun.js

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published