UNPKG

@duetds/date-picker

Version:

Duet Date Picker is an open source version of Duet Design System’s accessible date picker.

224 lines (179 loc) 6.72 kB
"use strict"; exports.__esModule = true; exports.setup = setup; exports.getServers = getServers; exports.teardown = teardown; exports.JestDevServerError = exports.ERROR_NO_COMMAND = exports.ERROR_PORT_USED = exports.ERROR_TIMEOUT = void 0; var _stream = _interopRequireDefault(require("stream")); var _net = _interopRequireDefault(require("net")); var _chalk = _interopRequireDefault(require("chalk")); var _spawnd = _interopRequireDefault(require("spawnd")); var _cwd = _interopRequireDefault(require("cwd")); var _waitOn = _interopRequireDefault(require("wait-on")); var _findProcess = _interopRequireDefault(require("find-process")); var _util = require("util"); var _treeKill = _interopRequireDefault(require("tree-kill")); var _prompts = _interopRequireDefault(require("prompts")); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); } const DEFAULT_CONFIG = { debug: false, options: {}, launchTimeout: 5000, host: 'localhost', port: null, protocol: 'tcp', usedPortAction: 'ask', waitOnScheme: {} }; const pTreeKill = (0, _util.promisify)(_treeKill.default); const serverLogPrefixer = new _stream.default.Transform({ transform(chunk, encoding, callback) { this.push(_chalk.default.magentaBright(`[Jest Dev server] ${chunk.toString()}`)); callback(); } }); const ERROR_TIMEOUT = 'ERROR_TIMEOUT'; exports.ERROR_TIMEOUT = ERROR_TIMEOUT; const ERROR_PORT_USED = 'ERROR_PORT_USED'; exports.ERROR_PORT_USED = ERROR_PORT_USED; const ERROR_NO_COMMAND = 'ERROR_NO_COMMAND'; exports.ERROR_NO_COMMAND = ERROR_NO_COMMAND; class JestDevServerError extends Error { constructor(message, code) { super(message); this.code = code; } } exports.JestDevServerError = JestDevServerError; const servers = []; function logProcDetection(proc, port) { console.log(_chalk.default.blue(`🕵️ Detecting a process "${proc.name}" running on port "${port}"`)); } async function killProc(proc) { console.log(_chalk.default.yellow(`Killing process ${proc.name}...`)); await pTreeKill(proc.pid); console.log(_chalk.default.green(`Successfully killed process ${proc.name}`)); } function runServer(config = {}, index) { if (!config.command) { throw new JestDevServerError('You must define a `command`', ERROR_NO_COMMAND); } servers[index] = (0, _spawnd.default)(config.command, _extends({ shell: true, env: process.env, cwd: (0, _cwd.default)() }, config.options)); if (config.debug) { // eslint-disable-next-line no-console console.log(_chalk.default.magentaBright('\nJest dev-server output:')); servers[index].stdout.pipe(serverLogPrefixer).pipe(process.stdout); } } async function outOfStin(block) { const { stdin } = process; const listeners = stdin.listeners('data'); const result = await block(); listeners.forEach(listener => stdin.on('data', listener)); stdin.setRawMode(true); stdin.setEncoding('utf8'); stdin.resume(); return result; } function getIsPortTaken(config) { let server; const cleanupAndReturn = result => new Promise(resolve => server.once('close', () => resolve(result)).close()); return new Promise((resolve, reject) => { server = _net.default.createServer().once('error', err => err.code === 'EADDRINUSE' ? resolve(cleanupAndReturn(true)) : reject()).once('listening', () => resolve(cleanupAndReturn(false))).listen(config.port, config.host); }); } async function setup(providedConfigs) { // Compatible with older versions const configs = Array.isArray(providedConfigs) ? providedConfigs : [providedConfigs]; await Promise.all(configs.map((providedConfig, index) => setupJestServer(providedConfig, index))); } async function setupJestServer(providedConfig, index) { const config = _extends({}, DEFAULT_CONFIG, {}, providedConfig); const usedPortHandlers = { error() { throw new JestDevServerError(`Port ${config.port} is in use`, ERROR_PORT_USED); }, async kill() { console.log(''); console.log(`Killing process listening to ${config.port}. On linux, this may require you to enter your password.`); const [portProcess] = await (0, _findProcess.default)('port', config.port); logProcDetection(portProcess, config.port); await killProc(portProcess); }, async ask() { console.log(''); const answers = await outOfStin(() => (0, _prompts.default)({ type: 'confirm', name: 'kill', message: `Another process is listening on ${config.port}. Should I kill it for you? On linux, this may require you to enter your password.`, initial: true })); if (answers.kill) { const [portProcess] = await (0, _findProcess.default)('port', config.port); logProcDetection(portProcess, config.port); await killProc(portProcess); } else { process.exit(1); } }, ignore() {} }; const usedPortHandler = usedPortHandlers[config.usedPortAction]; if (!usedPortHandler) { const availableActions = Object.keys(usedPortHandlers).map(action => `\`${action}\``).join(', '); throw new JestDevServerError(`Invalid \`usedPortAction\`, only ${availableActions} are possible`); } if (config.port) { const isPortTaken = await getIsPortTaken(config); if (isPortTaken) { await usedPortHandler(); } if (config.usedPortAction === 'ignore' && isPortTaken) { console.log(''); console.log('Port is already taken. Assuming server is already running.'); } else { runServer(config, index); } } else { runServer(config, index); } if (config.port) { const { launchTimeout, protocol, host, port, waitOnScheme } = config; let url = ''; if (protocol === 'tcp' || protocol === 'socket') { url = `${protocol}:${host}:${port}`; } else { url = `${protocol}://${host}:${port}`; } const opts = _extends({ resources: [url], timeout: launchTimeout }, waitOnScheme); try { await (0, _waitOn.default)(opts); } catch (err) { throw new JestDevServerError(`Server has taken more than ${launchTimeout}ms to start.`, ERROR_TIMEOUT); } } } function getServers() { return servers; } async function teardown() { if (servers.length) { await Promise.all(servers.map(server => server.destroy())); } }