UNPKG

rollup-plugin-serve

Version:
182 lines (154 loc) 5.63 kB
'use strict'; var fs = require('fs'); var https = require('https'); var http = require('http'); var path = require('path'); var lite = require('mime/lite'); var standardTypes = require('mime/types/standard.js'); var otherTypes = require('mime/types/other.js'); var opener = require('opener'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var standardTypes__default = /*#__PURE__*/_interopDefaultLegacy(standardTypes); var otherTypes__default = /*#__PURE__*/_interopDefaultLegacy(otherTypes); var opener__default = /*#__PURE__*/_interopDefaultLegacy(opener); var server; /** * Serve your rolled up bundle like webpack-dev-server * @param {import('..').RollupServeOptions} options */ function serve (options) { if ( options === void 0 ) options = { contentBase: '' }; var mime = new lite.Mime(standardTypes__default["default"], otherTypes__default["default"]); if (Array.isArray(options) || typeof options === 'string') { options = { contentBase: options }; } options.contentBase = Array.isArray(options.contentBase) ? options.contentBase : [options.contentBase || '']; options.port = options.port || 10001; options.headers = options.headers || {}; options.https = options.https || false; options.openPage = options.openPage || ''; options.onListening = options.onListening || function noop () { }; if (options.mimeTypes) { mime.define(options.mimeTypes, true); } var requestListener = function (request, response) { // Remove querystring var unsafePath = decodeURI(request.url.split('?')[0]); // Don't allow path traversal var urlPath = path.posix.normalize(unsafePath); Object.keys(options.headers).forEach(function (key) { response.setHeader(key, options.headers[key]); }); readFileFromContentBase(options.contentBase, urlPath, function (error, content, filePath) { if (!error) { return found(response, mime.getType(filePath), content) } if (error.code !== 'ENOENT') { response.writeHead(500); response.end('500 Internal Server Error' + '\n\n' + filePath + '\n\n' + Object.values(error).join('\n') + '\n\n(rollup-plugin-serve)', 'utf-8'); return } if (options.historyApiFallback) { var fallbackPath = typeof options.historyApiFallback === 'string' ? options.historyApiFallback : '/index.html'; readFileFromContentBase(options.contentBase, fallbackPath, function (error, content, filePath) { if (error) { notFound(response, filePath); } else { found(response, mime.getType(filePath), content); } }); } else { notFound(response, filePath); } }); }; // release previous server instance if rollup is reloading configuration in watch mode if (server) { server.close(); } else { closeServerOnTermination(); } // If HTTPS options are available, create an HTTPS server server = options.https ? https.createServer(options.https, requestListener) : http.createServer(requestListener); server.listen(options.port, options.host, function () { return options.onListening(server); }); // Assemble url for error and info messages var url = (options.https ? 'https' : 'http') + '://' + (options.host || 'localhost') + ':' + options.port; // Handle common server errors server.on('error', function (e) { if (e.code === 'EADDRINUSE') { console.error(url + ' is in use, either stop the other server or use a different port.'); process.exit(); } else { throw e } }); var first = true; return { name: 'serve', generateBundle: function generateBundle () { if (first) { first = false; // Log which url to visit if (options.verbose !== false) { options.contentBase.forEach(function (base) { console.log(green(url) + ' -> ' + path.resolve(base)); }); } // Open browser if (options.open) { if (/https?:\/\/.+/.test(options.openPage)) { opener__default["default"](options.openPage); } else { opener__default["default"](url + options.openPage); } } } } } } function readFileFromContentBase (contentBase, urlPath, callback) { var filePath = path.resolve(contentBase[0] || '.', '.' + urlPath); // Load index.html in directories if (urlPath.endsWith('/')) { filePath = path.resolve(filePath, 'index.html'); } fs.readFile(filePath, function (error, content) { if (error && contentBase.length > 1) { // Try to read from next contentBase readFileFromContentBase(contentBase.slice(1), urlPath, callback); } else { // We know enough callback(error, content, filePath); } }); } function notFound (response, filePath) { response.writeHead(404); response.end('404 Not Found' + '\n\n' + filePath + '\n\n(rollup-plugin-serve)', 'utf-8'); } function found (response, mimeType, content) { response.writeHead(200, { 'Content-Type': mimeType || 'text/plain' }); response.end(content, 'utf-8'); } function green (text) { return '\u001b[1m\u001b[32m' + text + '\u001b[39m\u001b[22m' } function closeServerOnTermination () { var terminationSignals = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP']; terminationSignals.forEach(function (signal) { process.on(signal, function () { if (server) { server.close(); process.exit(); } }); }); } module.exports = serve;