Skip to content

Commit

Permalink
1.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
okdistribute committed May 16, 2018
0 parents commit 47d307b
Show file tree
Hide file tree
Showing 8 changed files with 1,062 additions and 0 deletions.
61 changes: 61 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage

# nyc test coverage
.nyc_output

# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env

# next.js build output
.next
9 changes: 9 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
language: node_js

node_js:
- '6'
- '8'
sudo: false

script:
- npm test
661 changes: 661 additions & 0 deletions LICENSE

Large diffs are not rendered by default.

82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# cabal-node

Node.js library for p2p functions for chat.

## Usage

npm install cabal-node

## API

<!-- Generated by documentation.js. Update this documentation by updating the source code. -->

#### Table of Contents

- [Cabal](#cabal)
- [onconnection](#onconnection)
- [joinChannel](#joinchannel)
- [leaveChannel](#leavechannel)
- [createReadStream](#createreadstream)
- [message](#message)
- [replicate](#replicate)

### Cabal

Create a new Cabal. This is the object handling all
local nickname -> cabal interactions for a single user.

**Parameters**

- `storage` **([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) \| [function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function))** A hyperdb compatible storage function, or a string representing the local data path.
- `href` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The dat link
- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Options include: username

#### onconnection

When a connection is made. Auto-authorizes new peers to
write to the local database. Maintains the local view
of visible users.

**Parameters**

- `peer` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** The discovery-swarm peer emitted from the 'connection' or 'disconnection' event

#### joinChannel

Join a channel.

**Parameters**

- `channel` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The channel to join.

#### leaveChannel

Leave a channel.

**Parameters**

- `channel` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The channel to leave.

#### createReadStream

Create a readable stream for the cabal channel.

**Parameters**

- `channel` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The channel you want to read from.

#### message

Create a message.

**Parameters**

- `channel` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The channel to create the message.
- `message` **[String](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** The message to write.
- `opts` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Options: date, username
- `done` **[function](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/function)** When message has been successfully added.

#### replicate

Replication stream for the cabal. Shares the username with the
other peers it is connecting with.
164 changes: 164 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
var hyperdb = require('hyperdb')
var strftime = require('strftime')
var events = require('events')
var encoding = require('dat-encoding')
var inherits = require('inherits')

module.exports = Cabal

/**
* Create a new cabal. This is the object handling all
* local nickname -> mesh interactions for a single user.
* @constructor
* @param {string|function} storage - A hyperdb compatible storage function, or a string representing the local data path.
* @param {string} href - The dat link
* @param {Object} opts - Options include: username
*/
function Cabal (storage, href, opts) {
if (!(this instanceof Cabal)) return new Cabal(storage, href, opts)
if (!opts) opts = {}
events.EventEmitter.call(this)
var self = this

var json = {
encode: function (obj) {
return Buffer.from(JSON.stringify(obj))
},
decode: function (buf) {
var str = buf.toString('utf8')
try { var obj = JSON.parse(str) }
catch (err) { return {} }
return obj
}
}

self.username = opts.username || 'anonymous'

try {
var key = encoding.decode(href)
self.addr = encoding.encode(key)
} catch (e) {
self.addr = null
}
self.db = self.addr
? hyperdb(storage, self.addr, {valueEncoding: json})
: hyperdb(storage, {valueEncoding: json})

self.channels = {}
self.users = {}
self.users[opts.username] = new Date()
}

inherits(Cabal, events.EventEmitter)

/**
* When a connection is made. Auto-authorizes new peers to
* write to the local database. Maintains the local view
* of visible users.
* @param {Object} peer - The discovery-swarm peer emitted from the 'connection' or 'disconnection' event
*/
Cabal.prototype.onconnection = function (peer) {
var self = this
if (!peer.remoteUserData) return
try { var data = JSON.parse(peer.remoteUserData) }
catch (err) { return }
var key = Buffer.from(data.key)
var username = data.username

self.db.authorized(key, function (err, auth) {
if (err) return console.log(err)
if (!auth) self.db.authorize(key, function (err) {
if (err) return console.log(err)
})
})

if (!self.users[username]) {
self.users[username] = new Date()
self.emit('join', username)
peer.on('close', function () {
if (!self.users[username]) return
delete self.users[username]
self.emit('leave', username)
})
}
}

/**
* Join a channel.
* @param {String} channel - The channel to join.
*/
Cabal.prototype.joinChannel = function (channel) {
this.channels[channel] = true
}

/**
* Leave a channel.
* @param {String} channel - The channel to leave.
*/
Cabal.prototype.leaveChannel = function (channel) {
delete this.channels[channel]
}

/**
* Create a readable stream for the mesh.
* @param {String} channel - The channel you want to read from.
*/
Cabal.prototype.createReadStream = function (channel, opts) {
if (!opts) opts = {}
return this.db.createReadStream(`${channel}/messages`, Object.assign({recursive: true}, opts))
}

/**
* Get the metadata of channel.
* @param {String} channel Channel name
* @param {Function} done Callback
*/
Cabal.prototype.metadata = function (channel, done) {
this.db.get(`${channel}/metadata`, function (err, data) {
if (err) return done(err)
var node = (data.length ? data[0].value : {latest: 0})
done(null, node)
})
}

/**
* Create a message.
* @param {String} channel - The channel to create the message.
* @param {String} message - The message to write.
* @param {Object} opts - Options: date, username
* @param {function} done - When message has been successfully added.
*/
Cabal.prototype.message = function (channel, message, opts, done) {
if (typeof opts === 'function') return this.message(channel, message, null, opts)
if (!opts) opts = {}
var self = this
if (!message) return done()
var username = opts.username || self.username
self.metadata(channel, function (err, metadata) {
if (err) return done(err)
var latest = parseInt(metadata.latest)
var newLatest = latest + 1
var key = `${channel}/messages/${newLatest}`
var d = opts.date || new Date()
var date = new Date(d.valueOf() + d.getTimezoneOffset()*60*1000)
self.db.put(key, {username, date, message}, function () {
metadata.latest = newLatest
self.db.put(`${channel}/metadata`, metadata, done)
})
})
}

/**
* Replication stream for the mesh. Shares the username with the
* other peers it is connecting with.
*/
Cabal.prototype.replicate = function () {
var self = this
return this.db.replicate({
live: true,
userData: JSON.stringify({
key: self.db.local.key,
username: self.username
})
})
}
41 changes: 41 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"name": "cabal-node",
"version": "1.0.0",
"description": " p2p db functions for chat ",
"main": "index.js",
"scripts": {
"test": "node test.js",
"docs": "documentation readme index.js --section=API"
},
"repository": {
"type": "git",
"url": "git+https://github.com/cabal-club/cabal-node.git"
},
"keywords": [
"cabal",
"decentralized",
"swarm",
"chat",
"p2p",
"hyperdb"
],
"author": "Karissa McKelvey",
"license": "AGPL-3.0",
"bugs": {
"url": "https://github.com/cabal-club/cabal-node/issues"
},
"homepage": "https://github.com/cabal-club/cabal-node#readme",
"dependencies": {
"crypto": "^1.0.1",
"dat-swarm-defaults": "^1.0.1",
"discovery-swarm": "^5.1.1",
"hyperdb": "^3.0.0-3",
"strftime": "^0.10.0"
},
"devDependencies": {
"collect-stream": "^1.2.1",
"documentation": "^6.3.2",
"random-access-memory": "^3.0.0",
"tape": "^4.9.0"
}
}
15 changes: 15 additions & 0 deletions swarm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
var discovery = require('discovery-swarm')
var swarmDefaults = require('dat-swarm-defaults')

module.exports = function (cabal) {
var swarm = discovery(swarmDefaults({
id: cabal.db.local.key,
stream: function (peer) {
return cabal.replicate()
}
}))
var key = cabal.addr || cabal.db.key
swarm.join(key.toString('hex'))
swarm.on('connection', cabal.onconnection.bind(cabal))
return swarm
}
Loading

0 comments on commit 47d307b

Please sign in to comment.