gulp-server-io
Version:
A local static server, plus livereload and a socket.io debugger for your SPA development with gulp
129 lines (123 loc) • 4.97 kB
JavaScript
/**
* This will combine debugger and reload client file overwrite in one place
* there will be just one middleware to handle them
*/
const fs = require('fs');
const _ = require('lodash');
const chalk = require('chalk');
const { join } = require('path');
// Const gutil = require('gulp-util');
const { logutil } = require('../utils/helper');
const { getSocketConnectionConfig } = require('../utils/helper');
// @20171117 integration with stacktrace
// Note the config is only the debugger part
module.exports = config => {
// Now we need to supply a configurated option to not just point to our own local test machine
// const debuggerHost = config.server.host || config.host;
// const debuggerPort = config.server.port || config.port;
const stacktraceName = 'stacktrace.js';
// @BUG when this is running in server mode, the file disappeared?
// that's because the file is not copy inside the node_modules anymore
const searchStacktraceSrc = () => {
const stacktraceFile = join(
'node_modules',
'stacktrace-js',
'dist',
'stacktrace-with-promises-and-json-polyfills.js'
);
return [join(__dirname, '..', '..', '..', stacktraceFile), stacktraceFile]
.filter(f => {
return fs.existsSync(f);
})
.reduce((first, next) => {
return next;
}, null);
};
// Debugger
const debuggerPath = config.debugger.namespace;
const eventName = config.debugger.eventName;
const debuggerJs = [debuggerPath, config.debugger.js].join('/');
const stacktraceJsFile = [debuggerPath, stacktraceName].join('/');
// Reload
const reloadPath = config.reload.namespace;
const reloadEventName = config.reload.eventName;
const reloadJs = [reloadPath, config.reload.js].join('/');
// Just notify the console
// logutil(chalk.white('[debugger] ') + chalk.yellow('client is running'));
// Export middleware
return function(req, res, next) {
switch (req.url) {
case debuggerJs:
fs.readFile(join(__dirname, '..', 'debugger', 'client.tpl'), (err, data) => {
if (err) {
res.writeHead(500);
const msg = 'Error reading io-debugger-client file';
logutil(chalk.red(msg), chalk.yellow(err));
return res.end(msg);
}
// If they want to ping the server back on init
const ping =
typeof config.debugger.client === 'object' && config.debugger.client.ping
? 'true'
: 'false';
// There is a problem when the server is running from localhost
// and serving out to the proxy and the two ip address are not related to each other
// and for most of the cases, the client is always pointing back to itself anyway
const serveDataFn = _.template(data.toString());
// Force websocket connection
// see: http://stackoverflow.com/questions/8970880/cross-domain-connection-in-socket-io
// @2017-06-29 forcing the connection to socket only because it just serving up local!
const connectionOptions = getSocketConnectionConfig(config);
// Using the template method instead
const serveData = serveDataFn({
debuggerPath,
eventName,
ping,
connectionOptions,
consoleDebug: config.debugger.consoleDebug
});
// @TODO we should cache this file, otherwise every reload will have to generate it again
// The question is where do we cache it though ...
res.set('Content-Type', 'application/javascript');
res.writeHead(200);
res.end(serveData);
});
break;
case stacktraceJsFile:
fs.readFile(searchStacktraceSrc(), { encoding: 'utf8' }, (err, data) => {
if (err) {
res.writeHead(500);
const msg = 'Error reading stacktrace source file!';
logutil(chalk.red(msg), chalk.yellow(err));
return res.end(msg);
}
res.set('Content-Type', 'application/javascript');
res.writeHead(200);
res.end(`${data}`);
});
break;
case reloadJs:
fs.readFile(join(__dirname, '..', 'reload', 'reload.tpl'), (err, data) => {
if (err) {
res.writeHead(500);
const msg = 'Error reading io-reload-client file';
logutil(chalk.red(msg), chalk.yellow(err));
return res.end(msg);
}
const clientFileFn = _.template(data.toString());
const connectionOptions = getSocketConnectionConfig(config);
const serveData = clientFileFn({
reloadNamespace: reloadPath,
eventName: reloadEventName,
connectionOptions
});
res.set('Content-Type', 'application/javascript');
res.writeHead(200);
res.end(serveData);
});
break;
default:
next();
}
};
};