Select Git revision
replay-block.md
-
Cédric Moreau authoredCédric Moreau authored
index.js 5.97 KiB
"use strict";
const _ = require('underscore')
const co = require('co');
const fs = require('fs');
const bodyParser = require('body-parser');
const http = require('http');
const express = require('express');
const path = require('path');
const cors = require('cors');
const fileUpload = require('express-fileupload');
const webminController = require('./server/controller/webmin.js');
// Inject 'webstart' command if no argument was given
if (process.argv.length === 2) {
process.argv.push('direct_webstart');
}
module.exports = {
duniter: {
cliOptions: [
// Webmin options
{ value: '--webmhost <host>', desc: 'Local network interface to connect to (IP)' },
{ value: '--webmport <port>', desc: 'Local network port to connect', parser: parseInt }
],
cli: [{
name: 'webstart',
desc: 'Starts Duniter as a daemon (background task).',
logs: false,
onConfiguredExecute: (server, conf, program, params) => co(function*() {
yield server.checkConfig()
const daemon = server.getDaemon('direct_webstart', 'webstart')
yield startDaemon(program, daemon)
})
}, {
name: 'webrestart',
desc: 'Stops Duniter daemon and restart it with its web interface.',
logs: false,
onConfiguredExecute: (server, conf, program, params) => co(function*() {
yield server.checkConfig()
const daemon = server.getDaemon('direct_webstart', 'webrestart')
yield stopDaemon(daemon)
yield startDaemon(program, daemon)
})
}, {
name: 'direct_webstart',
desc: 'Do a webstart',
onDatabaseExecute: (server, conf, program, params, startServices, stopServices, stack) => co(function*(){
try {
/****************************************
* SPECIALISATION
***************************************/
const app = express();
const HOTE = program.webmhost || 'localhost';
const PORT = program.webmport || 9220;
/**
* Sur appel de l'URL /abc
*/
app.use(express.static(path.join(__dirname, '..', 'duniter-ui', 'public')));
app.use(cors());
// File upload for backup API
app.use(fileUpload());
app.use(bodyParser.urlencoded({
extended: true
}));
app.use(bodyParser.json());
const wbmin = webminController(server, startServices, stopServices, listDuniterPlugins, stack);
const httpServer = http.createServer(app);
httpServer.listen(PORT, HOTE);
server.logger.info("Web administration accessible at following address: http://%s:%s", HOTE, PORT);
require('./server/lib/routes').webmin(wbmin, app);
require('./server/lib/routes').webminWS(wbmin)(httpServer);
const uiDeps = listDuniterUIPlugins()
for (const dep of uiDeps) {
// Eventual HTTP routing
if (dep.required.duniterUI.route) {
const subApp = express()
dep.required.duniterUI.route(subApp, server, conf, program, params)
app.use('/modules/', subApp)
}
}
const currentBlock = yield server.dal.getCurrentBlockOrNull()
if (currentBlock) {
yield wbmin.startAllServices()
}
// Never ending promise
return new Promise((resolve) => {});
/****************************************/
} catch (e) {
console.error(e);
process.exit(1);
}
})
}]
}
};
function startDaemon(program, daemon) {
return co(function*() {
const PORT = program.webmport || 9220
const isPortAlreadyTaken = yield new Promise((resolve) => {
isPortTaken(PORT, (err, taken) => err ? reject(err) : resolve(taken))
})
if (isPortAlreadyTaken) {
console.error('Port ' + PORT + ' already used.')
process.exit(3)
}
return new Promise((resolve, reject) => daemon.start((err) => {
if (err) return reject(err)
resolve()
}))
})
}
/**
* Checks if a port is already taken by another app.
*
* Source: https://gist.github.com/timoxley/1689041
* @param port
* @param fn
*/
function isPortTaken(port, fn) {
const net = require('net')
const tester = net.createServer()
.once('error', function (err) {
if (err.code != 'EADDRINUSE') return fn(err)
fn(null, true)
})
.once('listening', function() {
tester.once('close', function() { fn(null, false) })
.close()
})
.listen(port)
}
function stopDaemon(daemon) {
return new Promise((resolve, reject) => daemon.stop((err) => {
err && console.error(err);
if (err) return reject(err)
resolve()
}))
}
function listDuniterPlugins() {
return listPlugins(r => !!r.duniter || !!r.duniterUI)
}
function listDuniterUIPlugins() {
return listPlugins(r => !!r.duniterUI)
}
function listPlugins(conditionTest) {
const uiDependencies = []
const pathToPackageJSON = path.resolve('./package.json')
const pkgJSON = JSON.parse(fs.readFileSync(pathToPackageJSON, 'utf8'))
const peerDeps = pkgJSON.peerDependencies || {}
const allDeps = _.extend(pkgJSON.dependencies || {}, pkgJSON.devDependencies || {})
const deps = Object.keys(allDeps)
for (const dep of deps) {
try {
const required = require(dep)
if (required && conditionTest(required)) {
uiDependencies.push({
name: dep,
version: allDeps[dep],
locked: !!peerDeps[dep],
required
})
}
} catch (e) {}
}
// Special: self dependency (if local package is also a module)
if (pkgJSON.main && pkgJSON.main.match(/\.js/)) { // With NW.js, the main is an index.html file, which causes a bug
const dep = pkgJSON.name
const required = require(path.resolve('./' + pkgJSON.main))
if (required && conditionTest(required)) {
uiDependencies.push({
name: dep,
version: 'local',
locked: true,
required
})
}
}
return uiDependencies
}