From 7f9ee949eec2e9801372ac3263b025adf039e8aa Mon Sep 17 00:00:00 2001 From: Spencer Ahrens Date: Thu, 9 Apr 2015 17:49:20 -0700 Subject: [PATCH] [ReactNative] Don't redbox on flow config errors --- packager/getFlowTypeCheckMiddleware.js | 76 ++++++++++++++++++-------- 1 file changed, 54 insertions(+), 22 deletions(-) diff --git a/packager/getFlowTypeCheckMiddleware.js b/packager/getFlowTypeCheckMiddleware.js index e0f98bde2..312da45e2 100644 --- a/packager/getFlowTypeCheckMiddleware.js +++ b/packager/getFlowTypeCheckMiddleware.js @@ -8,8 +8,11 @@ */ 'use strict'; +var chalk = require('chalk'); var exec = require('child_process').exec; +var hasWarned = {}; + function getFlowTypeCheckMiddleware(options) { return function(req, res, next) { if (options.skipflow) { @@ -18,13 +21,19 @@ function getFlowTypeCheckMiddleware(options) { if (options.flowroot || options.projectRoots.length === 1) { var flowroot = options.flowroot || options.projectRoots[0]; } else { - console.warn('flow: No suitable root'); + if (!hasWarned.noRoot) { + hasWarned.noRoot = true; + console.warn('flow: No suitable root'); + } return next(); } exec('command -v flow >/dev/null 2>&1', function(error, stdout) { if (error) { - console.warn('flow: Skipping because not installed. Install with ' + - '`brew install flow`.'); + if (!hasWarned.noFlow) { + hasWarned.noFlow = true; + console.warn(chalk.yellow('flow: Skipping because not installed. Install with ' + + '`brew install flow`.')); + } return next(); } else { return doFlowTypecheck(res, flowroot, next); @@ -36,10 +45,19 @@ function getFlowTypeCheckMiddleware(options) { function doFlowTypecheck(res, flowroot, next) { var flowCmd = 'cd "' + flowroot + '" && flow --json --timeout 20'; var start = Date.now(); - console.log('flow: Running static typechecks.'); - exec(flowCmd, function(flowError, stdout) { + // Log start message if flow is slow to let user know something is happening. + var flowSlow = setTimeout( + function() { + console.log(chalk.gray('flow: Running static typechecks.')); + }, + 500 + ); + exec(flowCmd, function(flowError, stdout, stderr) { + clearTimeout(flowSlow); if (!flowError) { - console.log('flow: Typechecks passed (' + (Date.now() - start) + 'ms).'); + console.log(chalk.gray( + 'flow: Typechecks passed (' + (Date.now() - start) + 'ms).') + ); return next(); } else { try { @@ -61,24 +79,38 @@ function doFlowTypecheck(res, flowroot, next) { }); errorNum++; }); - var message = 'Flow found type errors. If you think these are wrong, ' + - 'make sure flow is up to date, or disable with --skipflow.'; + var error = { + status: 500, + message: 'Flow found type errors. If you think these are wrong, ' + + 'make sure your flow bin and .flowconfig are up to date, or ' + + 'disable with --skipflow.', + type: 'FlowError', + errors: errors, + }; + console.error(chalk.yellow('flow: Error running command `' + flowCmd + + '`:\n' + JSON.stringify(error)) + ); + res.writeHead(error.status, { + 'Content-Type': 'application/json; charset=UTF-8', + }); + res.end(JSON.stringify(error)); } catch (e) { - var message = - 'Flow failed to provide parseable output:\n\n`' + stdout + '`'; - console.error(message, '\nException: `', e, '`\n\n'); + if (stderr.match(/Could not find a \.flowconfig/)) { + if (!hasWarned.noConfig) { + hasWarned.noConfig = true; + console.warn(chalk.yellow('flow: ' + stderr)); + } + } else { + if (!hasWarned.brokenFlow) { + hasWarned.brokenFlow = true; + console.warn(chalk.yellow( + 'Flow failed to provide parseable output:\n\n`' + stdout + + '`.\n' + 'stderr: `' + stderr + '`' + )); + } + } + return next(); } - var error = { - status: 500, - message: message, - type: 'FlowError', - errors: errors, - }; - console.error('flow: Error running command `' + flowCmd + '`:\n', error); - res.writeHead(error.status, { - 'Content-Type': 'application/json; charset=UTF-8', - }); - res.end(JSON.stringify(error)); } }); }