Skip to content

Commit

Permalink
refactor: Simplify code and use es2015 features.
Browse files Browse the repository at this point in the history
  • Loading branch information
dignifiedquire committed Nov 13, 2015
1 parent 3d5c6a6 commit 99b16d5
Show file tree
Hide file tree
Showing 3 changed files with 211 additions and 221 deletions.
261 changes: 125 additions & 136 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,51 @@
var run = require('subcomandante')
var _ = require('lodash')
var Q = require('kew')
var ipfs = require('ipfs-api')
var multiaddr = require('multiaddr')
var waterfall = require('promise-waterfall')
var rimraf = require('rimraf')
var fs = require('fs')
var shutdown = require('shutdown')

var IPFS_EXEC = require('go-ipfs')
var GRACE_PERIOD = 7500 // amount of ms to wait before sigkill

function configureNode (node, conf, cb) {
if (Object.keys(conf).length) {
waterfall(_.map(conf, function (value, key) {
return function () {
var def = Q.defer()
run(IPFS_EXEC, ['config', key, '--json', JSON.stringify(value)],
{env: node.env})
.on('error', cb)
.on('end', function () { def.resolve() })
return def.promise
}
})).then(function () {
cb(null)
})
'use strict'

const fs = require('fs')
const os = require('os')
const join = require('path').join
const run = require('subcomandante')
const async = require('async')
const ipfs = require('ipfs-api')
const multiaddr = require('multiaddr')
const rimraf = require('rimraf')
const shutdown = require('shutdown')

const IPFS_EXEC = require('go-ipfs')
const GRACE_PERIOD = 7500 // amount of ms to wait before sigkill

function configureNode (node, conf, done) {
if (Object.keys(conf).length > 0) {
async.forEachOfSeries(conf, (value, key, cb) => {
const env = {env: node.env}

run(IPFS_EXEC, ['config', key, '--json', JSON.stringify(value)], env)
.on('error', cb)
.on('end', cb)
}, done)
} else {
cb(null)
done()
}
}

function tempDir () {
return '/tmp/ipfs_' + (Math.random() + '').substr(2)
return join(os.tmpdir(), `ipfs_${(Math.random() + '').substr(2)}`)
}

var Node = function (path, opts, disposable) {
var env = _.clone(process.env)
// Consistent error handling
function parseConfig (path, done) {
try {
const file = fs.readFileSync(join(path, 'config'))
const parsed = JSON.parse(file)
done(null, parsed)
} catch (err) {
done(err)
}
}

function Node (path, opts, disposable) {
const env = Object.assign({}, process.env, {IPFS_PATH: path})

env.IPFS_PATH = path
if (opts.env) _.assign(env, opts.env)
if (opts.env) Object.assign(env, opts.env)

return {
subprocess: null,
Expand All @@ -47,181 +54,163 @@ var Node = function (path, opts, disposable) {
path: path,
opts: opts,
env: env,
init: function (initOpts, cb) {
var t = this
if (!cb) {
cb = initOpts
init (initOpts, done) {
if (!done) {
done = initOpts
initOpts = {}
}
var buf = ''
let buf = ''

var keySize = initOpts.keysize || 2048
const keySize = initOpts.keysize || 2048

if (initOpts.directory && initOpts.directory !== path) {
path = initOpts.directory
t.env.IPFS_PATH = path
this.env.IPFS_PATH = path
}

run(IPFS_EXEC, ['init', '-b', keySize], {env: t.env})
.on('error', cb)
.on('data', function (data) { buf += data })
.on('end', function () {
configureNode(t, t.opts, function (err) {
if (err) return cb(err)
t.clean = false
t.initialized = true
cb(null, t)
run(IPFS_EXEC, ['init', '-b', keySize], {env: this.env})
.on('error', done)
.on('data', data => buf += data)
.on('end', () => {
configureNode(this, this.opts, err => {
if (err) return done(err)
this.clean = false
this.initialized = true
done(null, this)
})
})

if (disposable) {
shutdown.addHandler('disposable', 1, t.shutdown.bind(t))
shutdown.addHandler('disposable', 1, this.shutdown.bind(this))
}
},
// cleanup tmp files
shutdown: function (done) {
var t = this
if (!t.clean && disposable) {
rimraf(t.path, function (err) {
shutdown (done) {
if (!this.clean && disposable) {
rimraf(this.path, err => {
if (err) throw err
done()
})
}
},
startDaemon: function (cb) {
var t = this
parseConfig(t.path, function (err, conf) {
if (err) return cb(err)
startDaemon (done) {
parseConfig(this.path, (err, conf) => {
if (err) return done(err)

t.subprocess = run(IPFS_EXEC, ['daemon'], {env: t.env})
.on('error', function (err) {
this.subprocess = run(IPFS_EXEC, ['daemon'], {env: this.env})
.on('error', err => {
if ((err + '').match('daemon is running')) {
// we're good
cb(null, ipfs(conf.Addresses.API))
done(null, ipfs(conf.Addresses.API))
} else if ((err + '').match('non-zero exit code')) {
// ignore when kill -9'd
} else {
cb(err)
done(err)
}
})
.on('data', function (data) {
var match = (data + '').trim().match(/API server listening on (.*)/)
.on('data', data => {
const match = (data + '').trim().match(/API server listening on (.*)/)
if (match) {
t.apiAddr = match[1]
var addr = multiaddr(t.apiAddr).nodeAddress()
var api = ipfs(t.apiAddr)
this.apiAddr = match[1]
const addr = multiaddr(this.apiAddr).nodeAddress()
const api = ipfs(this.apiAddr)
api.apiHost = addr.address
api.apiPort = addr.port
cb(null, api)
done(null, api)
}
})
})
},
stopDaemon: function (cb) {
var sp = this.subprocess
if (!sp) return
stopDaemon (done) {
if (!done) done = () => {}
if (!this.subprocess) return done(null)

sp.kill('SIGTERM')
this.subprocess.kill('SIGTERM')

var timeout = setTimeout(function () {
sp.kill('SIGKILL')
cb && cb(null)
const timeout = setTimeout(() => {
this.subprocess.kill('SIGKILL')
done(null)
}, GRACE_PERIOD)

sp.on('close', function () {
this.subprocess.on('close', () => {
clearTimeout(timeout)
cb && cb(null)
done(null)
})

this.subprocess = null
},
daemonPid: function () {
daemonPid () {
return this.subprocess && this.subprocess.pid
},
getConfig: function (key, cb) {
getConfig (key, done) {
if (typeof key === 'function') {
cb = key
done = key
key = ''
}
var t = this
var result = ''
run(IPFS_EXEC, ['config', key], {env: t.env})
.on('error', cb)
.on('data', function (data) { result += data })
.on('end', function () {
cb(null, result.trim())
})
let result = ''
run(IPFS_EXEC, ['config', key], {env: this.env})
.on('error', done)
.on('data', data => result += data)
.on('end', () => done(null, result.trim()))
},
setConfig: function (key, value, cb) {
var t = this
run(IPFS_EXEC, ['config', key, value, '--json'], {env: t.env})
.on('error', cb)
.on('data', function (data) {})
.on('end', function () { cb() })
setConfig (key, value, done) {
run(IPFS_EXEC, ['config', key, value, '--json'], {env: this.env})
.on('error', done)
.on('data', data => {})
.on('end', () => done())
},
replaceConf: function (file, cb) {
var t = this
var result = ''
run(IPFS_EXEC, ['config', 'replace', file], {env: t.env})
.on('error', cb)
.on('data', function (data) { result += data })
.on('end', function () { cb(null, result.trim()) })
replaceConf (file, done) {
let result = ''
run(IPFS_EXEC, ['config', 'replace', file], {env: this.env})
.on('error', done)
.on('data', data => result += data)
.on('end', () => done(null, result.trim()))
}
}
}

// cb for consistent error handling
var parseConfig = function (path, cb) {
try {
var file = fs.readFileSync(path + '/config')
var parsed = JSON.parse(file)
cb(null, parsed)
} catch (e) {
cb(e)
}
}

module.exports = {
version: function (cb) {
var buf = ''
version (done) {
let buf = ''
run(IPFS_EXEC, ['version'])
.on('error', cb)
.on('data', function (data) { buf += data })
.on('end', function () { cb(null, buf) })
.on('error', done)
.on('data', data => buf += data)
.on('end', () => done(null, buf))
},
local: function (path, cb) {
if (!cb) {
cb = path
local (path, done) {
if (!done) {
done = path
path = process.env.IPFS_PATH ||
(process.env.HOME ||
process.env.USERPROFILE) + '/.ipfs'
join(process.env.HOME ||
process.env.USERPROFILE, '.ipfs')
}
cb(null, new Node(path, {}))
done(null, new Node(path, {}))
},
disposableApi: function (opts, cb) {
disposableApi (opts, done) {
if (typeof opts === 'function') {
cb = opts
done = opts
opts = {}
}
this.disposable(opts, function (err, node) {
if (err) return cb(err)
node.startDaemon(function (err, api) {
if (err) return cb(err)
cb(null, api)
this.disposable(opts, (err, node) => {
if (err) return done(err)
node.startDaemon((err, api) => {
if (err) return done(err)
done(null, api)
})
})
},
disposable: function (opts, cb) {
disposable (opts, done) {
if (typeof opts === 'function') {
cb = opts
done = opts
opts = {}
}
opts['Addresses.Swarm'] = ['/ip4/0.0.0.0/tcp/0']
opts['Addresses.Gateway'] = ''
opts['Addresses.API'] = '/ip4/127.0.0.1/tcp/0'
var node = new Node(tempDir(), opts, true)
node.init(function (err) {
if (err) return cb(err)
cb(null, node)
const node = new Node(tempDir(), opts, true)
node.init(err => {
if (err) return done(err)
done(null, node)
})
}
}
7 changes: 3 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"main": "index.js",
"scripts": {
"test": "node_modules/.bin/mocha test",
"lint": "node_modules/.bin/standard"
"lint": "standard"
},
"engines": {
"node": ">=4.0.0"
Expand All @@ -28,15 +28,14 @@
"dependencies": {
"go-ipfs": "0.3.9",
"ipfs-api": "^2.2.1",
"kew": "0.7.0",
"lodash": "^3.6.0",
"multiaddr": "^1.0.0",
"promise-waterfall": "0.1.0",
"rimraf": "^2.3.4",
"shutdown": "^0.2.4",
"subcomandante": "^1.0.3"
},
"devDependencies": {
"async": "^1.5.0",
"estraverse": "^4.1.1",
"mocha": "^2.3.3",
"pre-commit": "^1.1.2",
"standard": "^5.3.1"
Expand Down
Loading

0 comments on commit 99b16d5

Please sign in to comment.