UNPKG

micro-dev

Version:

This command line interface provides a belt full of tools that make building microservices using [micro](https://github.com/vercel/micro) a breeze! It's only meant to be used in development, **not in production** (that's where [micro](https://github.com/v

158 lines (125 loc) 3.57 kB
// Native const path = require('path'); const debounce = require('debounce'); // Packages const {write: copy} = require('clipboardy'); const ip = require('ip'); const chalk = require('chalk'); const boxen = require('boxen'); const {watch} = require('chokidar'); const pkgUp = require('pkg-up'); const copyToClipboard = async text => { try { await copy(text); return true; } catch (err) { return false; } }; const restartServer = (file, flags, watcher) => { const watched = watcher.getWatched(); const toDelete = []; for (const mainPath in watched) { if (!{}.hasOwnProperty.call(watched, mainPath)) { continue; } const subPaths = watched[mainPath]; for (const subPath of subPaths) { const full = path.join(mainPath, subPath); toDelete.push(full); } } // Remove file that changed from the `require` cache for (const item of toDelete) { let location; try { location = require.resolve(item); } catch (err) { continue; } delete require.cache[location]; } // Restart the server require('./serve')(file, flags, true); }; const destroySockets = list => { // Destroy all sockets before closing the server // Otherwise it will gracefully exit and take a long time for (const socket of list) { socket.destroy(); } }; module.exports = async (server, inUse, flags, sockets) => { const details = server.address(); const ipAddress = ip.address(); const url = `http://${ipAddress}:${details.port}`; const {isTTY} = process.stdout; const file = flags._[0]; if (!flags.cold) { let toWatch = flags.watch || false; const watchConfig = { usePolling: flags.poll, ignoreInitial: true, ignored: [ /\.git|node_modules|\.nyc_output|\.sass-cache|coverage|\.cache/, /\.swp$/ ] }; // Ignore globs if (flags.ignore) { watchConfig.ignored = watchConfig.ignored.concat(new RegExp(flags.ignore)); } if (Array.isArray(toWatch)) { toWatch.push(file); } else if (toWatch) { toWatch = [toWatch, file]; } else { // Find out which directory to watch const closestPkg = await pkgUp(path.dirname(file)); toWatch = [closestPkg ? path.dirname(closestPkg) : process.cwd()]; } // Start watching the project files const watcher = watch(toWatch, watchConfig); // Ensure that the server gets restarted if a file changes watcher.once( 'all', debounce((event, filePath) => { const location = path.relative(process.cwd(), filePath); console.log( `\n${chalk.blue('File changed:')} ${location} - Restarting server...` ); destroySockets(sockets); // Ensure the same port when restarting server flags.port = details.port; // Restart server server.close(restartServer.bind(this, file, flags, watcher)); }, 10) ); } if (flags.restarted) { console.log(chalk.green('Restarted!')); return; } let message = chalk.green('Micro is running!'); if (inUse) { message += ` ${chalk.red(`(on port ${inUse.open}, because ${inUse.old} is already in use)`)}`; } message += '\n\n'; const host = flags.host === '::' ? 'localhost' : flags.host; const localURL = `http://${host}:${details.port}`; message += `• ${chalk.bold('Local: ')} ${localURL}\n`; message += `• ${chalk.bold('On Your Network: ')} ${url}\n\n`; if (isTTY) { const copied = await copyToClipboard(localURL); if (copied) { message += `${chalk.grey('Copied local address to clipboard!')}`; } } const box = boxen(message, { padding: 1, borderColor: 'green', margin: 1 }); // Print out the message console.log(box); };