gulp-server-io
Version:
A local static server, plus livereload and a socket.io debugger for your SPA development with gulp
141 lines (133 loc) • 4.5 kB
JavaScript
/**
* Main execution for everything
*/
const fs = require('fs');
const chalk = require('chalk');
const through = require('through2');
// Our modules
const appGenerator = require('./lib/app');
// Open browser
const openInBrowser = require('./lib/utils/open');
// Main express server
const { webserver, socketServer } = require('./lib/server');
const { serveStatic } = require('./lib/utils/helper');
// Other features
const debuggerServer = require('./lib/debugger');
const serverReload = require('./lib/reload/server-reload');
const reload = require('./lib/reload');
// Fancy log util
const { logutil } = require('./lib/utils/helper');
// Adding debug options here
const debug = require('debug')('gulp-server-io:main');
// Const emptyFn = () => {};
// Porting back from src/index.js
/**
* This will be come the main export file
* When the consumer call it
* const gulpServerIo = require('gulp-server-io')
* When they want to use the underlying connect server
* const server = require('gulp-server-io/server');
* neat!
*/
// Final export for gulp
module.exports = function(options = {}) {
debug('options', options);
const { app, config, mockServerInstance } = appGenerator(options);
let server = {};
let io = null;
let filePaths = [];
let unwatchFn = [];
// Create static server wrap in a stream
// Please note it could pass an array of paths
// So this will call multiple times
const stream = through
.obj((file, enc, callback) => {
// Serve up the files
app.use(config.path, serveStatic(file.path, config));
filePaths.push(file.path);
callback();
debug('[main][add file]', filePaths);
})
.on('data', f => {
filePaths.push(f.path);
debug('[main][data add file]', filePaths);
})
.on('end', () => {
debug('[main][on end]', filePaths);
// Debug('files/dir being serve', filePaths);
// Setup fallback i.e. 404.html
// TBC do we need this at all?
if (config.fallback !== false) {
filePaths.forEach(file => {
const fallbackFile = file + '/' + config.fallback;
if (fs.existsSync(fallbackFile)) {
app.use((req, res) => {
res.setHeader('Content-Type', 'text/html; charset=UTF-8');
fs.createReadStream(fallbackFile).pipe(res);
});
}
});
}
// Overwriting the callback
const cb = config.callback;
config.callback = () => {
// For some reason the config is undefined and nothing can pass to it
if (typeof cb === 'function') {
Reflect.apply(cb, null, [config]);
}
// Notify
logutil(
chalk.white(`gulp-server-io (${config.version}) running at`),
chalk.cyan(
['http', config.https ? 's' : '', '://', config.host, ':', config.port].join(
''
)
)
);
// Open in browser
openInBrowser(config);
};
server = webserver(app, config);
// Debug('server', server);
if (
config.reload.enable ||
(config.debugger.enable && config.debugger.server === true)
) {
io = socketServer(server, config);
}
// @TODO we need to combine the two socket server into one
// 1. check if those modules that require a socket server is needed
// 2. generate a socket server, then passing the instance back to
// their respective constructors
// Run the watcher, return an unwatch function
if (config.reload.enable) {
// Limiting the config options
unwatchFn.push(reload(filePaths, io, config.reload));
}
// Debugger server start
if (config.debugger.enable && config.debugger.server === true) {
unwatchFn.push(debuggerServer(config, io));
}
// @TODO add watching server side files
// New @1.4.0-beta.11 watch a different path and pass a callback
if (config.serverReload.enable) {
unwatchFn.push(serverReload(config.serverReload));
}
});
// When ctrl-c or stream.emit('kill')
stream.on('kill', () => {
// @1.4.0-beta.11 change to array
unwatchFn.forEach(fn => fn());
// Explicitly close the express server
server.close(() => {
if (io && io.server && io.server.close) {
// Close the socket.io server
io.server.close();
}
});
// Close the mock server
mockServerInstance.close();
});
// Return
return stream;
};