-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add a factory to start/stop nodes from node and browser
- Loading branch information
Showing
12 changed files
with
394 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
'use strict' | ||
|
||
const tasks = require('./src/remote-factory/tasks') | ||
|
||
module.exports = { | ||
hooks: { | ||
browser: { | ||
pre: tasks.start, | ||
post: tasks.stop | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,3 +36,5 @@ node_modules | |
|
||
dist | ||
docs | ||
|
||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
'use strict' | ||
|
||
const isNode = require('detect-node') | ||
const Local = require('./local-factory') | ||
const Remote = require('./remote-factory') | ||
|
||
class Factory { | ||
constructor (opts) { | ||
this.factory = isNode ? new Local() : new Remote(opts) | ||
} | ||
|
||
spawnNode (repoPath, opts, callback) { | ||
this.factory.spawnNode(repoPath, opts, callback) | ||
} | ||
|
||
dismantle (callback) { | ||
this.factory.dismantle(callback) | ||
} | ||
} | ||
|
||
module.exports = Factory |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
'use strict' | ||
|
||
const IpfsdCtl = require('../..') | ||
const each = require('async/each') | ||
const waterfall = require('async/waterfall') | ||
|
||
class Factory { | ||
constructor () { | ||
this.nodes = [] | ||
} | ||
|
||
/* yields a new started node */ | ||
spawnNode (repoPath, opts, callback) { | ||
if (typeof repoPath === 'function') { | ||
callback = repoPath | ||
repoPath = null | ||
} | ||
if (typeof opts === 'function') { | ||
callback = opts | ||
opts = {} | ||
} | ||
|
||
opts = Object.assign({}, opts, { repoPath }) | ||
|
||
waterfall([ | ||
(cb) => IpfsdCtl.disposable(opts, cb), | ||
(node, cb) => { | ||
this.nodes.push(node) | ||
node.startDaemon(['--enable-pubsub-experiment'], cb) | ||
} | ||
], callback) | ||
} | ||
|
||
dismantle (callback) { | ||
each(this.nodes, (node, cb) => node.stopDaemon(cb), callback) | ||
} | ||
} | ||
|
||
module.exports = Factory |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
'use strict' | ||
|
||
const io = require('socket.io-client') | ||
const IpfsApi = require('ipfs-api') | ||
|
||
const { toPayload, toRes } = require('./utils') | ||
|
||
class Client { | ||
constructor (sio) { | ||
this._sio = sio | ||
} | ||
|
||
_request () { | ||
const action = Array.from(arguments).shift() | ||
const args = Array.from(arguments).splice(1, arguments.length - 2) | ||
const cb = Array.from(arguments).splice(arguments.length - 1, 1).shift() | ||
this._sio.on(action, (data) => toRes(data, cb)) | ||
this._sio.emit(action, toPayload(args)) | ||
} | ||
|
||
start (opts, cb) { | ||
if (typeof opts === 'function') { | ||
cb = opts | ||
opts = {} | ||
} | ||
|
||
this._request('start', opts, (err, api) => { | ||
if (err) { | ||
return cb(err) | ||
} | ||
|
||
cb(null, new IpfsApi(api.apiAddr)) | ||
}) | ||
} | ||
|
||
stop (nodes, cb) { | ||
if (typeof nodes === 'function') { | ||
cb = nodes | ||
nodes = undefined | ||
} | ||
|
||
cb = cb || (() => {}) | ||
this._request('stop', nodes, cb) | ||
} | ||
} | ||
|
||
function createClient (options, callback) { | ||
if (typeof options === 'function') { | ||
callback = options | ||
options = {} | ||
} | ||
|
||
callback = callback || (() => {}) | ||
options = options || {} | ||
const url = options.url ? (delete options.url) : 'http://localhost:55155' | ||
options = Object.assign({}, options, { | ||
transports: ['websocket'], | ||
'force new connection': true | ||
}) | ||
|
||
const sio = io.connect(url, options) | ||
sio.once('connect_error', (err) => { throw err }) | ||
sio.once('connect', () => { | ||
callback(null, new Client(sio)) | ||
}) | ||
} | ||
|
||
module.exports = createClient |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
'use strict' | ||
|
||
const createClient = require('./client') | ||
|
||
class Factory { | ||
constructor (options) { | ||
this._options = options || {} | ||
this._client = null | ||
} | ||
|
||
_spawn (repoPath, opts, callback) { | ||
if (typeof repoPath === 'function') { | ||
callback = repoPath | ||
repoPath = null | ||
} | ||
if (typeof opts === 'function') { | ||
callback = opts | ||
opts = {} | ||
} | ||
|
||
opts = Object.assign({}, opts, { repoPath }) | ||
this._client.start(opts, callback) | ||
} | ||
|
||
spawnNode (repoPath, opts, callback) { | ||
if (!this._client) { | ||
return createClient(this._options, (err, cl) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
this._client = cl | ||
return this._spawn(repoPath, opts, callback) | ||
}) | ||
} | ||
|
||
return this._spawn(repoPath, opts, callback) | ||
} | ||
|
||
dismantle (callback) { | ||
if (!this._client) { | ||
return callback() | ||
} | ||
|
||
this._client.stop(callback) | ||
} | ||
} | ||
|
||
module.exports = Factory |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
'use strict' | ||
|
||
const IpfsdCtl = require('..') | ||
const SocketIO = require('socket.io') | ||
const each = require('async/each') | ||
const waterfall = require('async/waterfall') | ||
const eachSeries = require('async/eachSeries') | ||
const series = require('async/series') | ||
const parsePayload = require('./utils').parsePayload | ||
|
||
const nodes = new Map() | ||
|
||
function start (opts, callback) { | ||
if (typeof opts === 'function') { | ||
callback = opts | ||
opts = null | ||
} | ||
|
||
let node = null | ||
waterfall([ | ||
(cb) => IpfsdCtl.disposable(opts, cb), | ||
(n, cb) => { | ||
node = n | ||
series([ | ||
(pCb) => { | ||
const configValues = { | ||
Bootstrap: [], | ||
Discovery: {}, | ||
'API.HTTPHeaders.Access-Control-Allow-Origin': ['*'], | ||
'API.HTTPHeaders.Access-Control-Allow-Methods': [ | ||
'PUT', | ||
'POST', | ||
'GET' | ||
] | ||
} | ||
eachSeries(Object.keys(configValues), (configKey, cb) => { | ||
const configVal = JSON.stringify(configValues[configKey]) | ||
node.setConfig(configKey, configVal, cb) | ||
}, pCb) | ||
}, | ||
(pCb) => node.startDaemon(['--enable-pubsub-experiment'], cb) | ||
], cb) | ||
}, | ||
(api, cb) => api.id(cb), | ||
(id, cb) => cb(null, nodes.set(id.id, node)) | ||
], (err) => { | ||
callback(err, { | ||
apiAddr: node.apiAddr.toString() | ||
}) | ||
}) | ||
} | ||
|
||
function stop (node, callback) { | ||
if (typeof node === 'function') { | ||
callback = node | ||
node = undefined | ||
} | ||
|
||
if (node) { | ||
return nodes.get(node).stopDaemon(callback) | ||
} | ||
|
||
each(nodes, (node, cb) => node[1].stopDaemon(cb), callback) | ||
} | ||
|
||
module.exports = (http) => { | ||
const io = new SocketIO(http.listener) | ||
io.on('connection', handle) | ||
|
||
function handle (socket) { | ||
const response = (action) => (err, data) => { | ||
if (err) { | ||
return socket.emit(action, JSON.stringify({ err })) | ||
} | ||
|
||
socket.emit(action, JSON.stringify({ data })) | ||
} | ||
|
||
socket.on('start', (data) => start.apply(null, parsePayload(data).concat(response('start')))) | ||
socket.on('stop', (data) => stop.apply(null, parsePayload(data).concat(response('stop')))) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
'use strict' | ||
|
||
const Hapi = require('hapi') | ||
const routes = require('./routes') | ||
|
||
const port = Number(process.env.PORT) || 55155 | ||
const options = { | ||
connections: { | ||
routes: { | ||
cors: true | ||
} | ||
} | ||
} | ||
|
||
function server (callback) { | ||
const http = new Hapi.Server(options) | ||
|
||
http.connection({ port: port }) | ||
|
||
http.start((err) => { | ||
if (err) { | ||
return callback(err) | ||
} | ||
|
||
routes(http) | ||
|
||
callback(null, http) | ||
}) | ||
} | ||
|
||
module.exports = server |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
'use strict' | ||
|
||
const factoryServer = require('./server') | ||
|
||
let factory | ||
module.exports = { | ||
start (done) { | ||
factoryServer((err, http) => { | ||
if (err) { | ||
return done(err) | ||
} | ||
factory = http | ||
done() | ||
}) | ||
}, | ||
stop (done) { | ||
factory.stop(done) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
'use strict' | ||
|
||
exports.toPayload = (args) => JSON.stringify({ args }) | ||
|
||
exports.toRes = (payload, cb) => { | ||
payload = JSON.parse(payload) | ||
if (payload.err) { | ||
return cb(payload.err) | ||
} | ||
|
||
return cb(null, payload.data) | ||
} | ||
|
||
exports.parsePayload = (data) => { | ||
const args = JSON.parse(data).args | ||
if (!Array.isArray(args)) { | ||
throw new Error('args field should be an array') | ||
} | ||
|
||
return args | ||
} |
Oops, something went wrong.