/** Error-handling routines for HackMyResume. @module error.js @license MIT. See LICENSE.md for details. */ // TODO: Logging library (function() { var HACKMYSTATUS = require('../core/status-codes') , PKG = require('../../package.json') , FS = require('fs') , FCMD = require('../hackmyapi') , PATH = require('path') , WRAP = require('word-wrap') , M2C = require('../utils/md2chalk.js') , chalk = require('chalk') , YAML = require('yamljs') , printf = require('printf') , SyntaxErrorEx = require('../utils/syntax-error-ex'); require('string.prototype.startswith'); /** Error handler for HackMyResume. All errors are handled here. @class ErrorHandler */ var ErrorHandler = module.exports = { init: function( debug, assert ) { this.debug = debug; this.assert = assert; this.msgs = require('./msg.js').errors; return this; }, err: function( ex, shouldExit ) { if( !this.msgs ) { this.msgs = require('./msg.js').errors; } if( ex.pass ) throw ex; if( ex.fluenterror ) { // Output the error message var objError = assembleError.call( this, ex ); o( this[ 'format' + (objError.warning ? 'Warning' : 'Error')]( objError.msg )); // Output the stack (sometimes) if( objError.showStack ) o( chalk.red( ex.stack || ex.inner.stack ) ); // Quit if necessary if( objError.quit ) { this.debug && o( chalk.cyan('Exiting with error code ' + ex.fluenterror.toString())); if( this.assert ) { ex.pass = true; throw ex; } process.exit( ex.fluenterror ); } } else { o( ex ); var stackTrace = ex.stack || (ex.inner && ex.inner.stack); if( stackTrace && this.debug ) o( ex.stack || ex.inner.stack ); // if( this.debug ) // o( ex.stack || ex.inner.stack ); } }, formatError: function( msg ) { return chalk.red.bold( msg.toUpperCase().startsWith('ERROR:') ? msg : 'Error: ' + msg ); }, formatWarning: function( brief, msg ) { return chalk.yellow(brief) + chalk.yellow(msg || ''); } }; var o = function() { console.log.apply( console.log, arguments ); }; function assembleError( ex ) { var msg = '', withStack = false, isError = false, quit = true, warn = true; switch( ex.fluenterror ) { case HACKMYSTATUS.themeNotFound: msg = printf( M2C( this.msgs.themeNotFound.msg, 'yellow' ), ex.data); break; case HACKMYSTATUS.copyCSS: msg = M2C( this.msgs.copyCSS.msg, 'red' ); quit = false; break; case HACKMYSTATUS.resumeNotFound: msg = M2C( this.msgs.resumeNotFound.msg, 'yellow' ); break; case HACKMYSTATUS.missingCommand: msg = M2C( this.msgs.missingCommand.msg + " (", 'yellow'); msg += Object.keys( FCMD.verbs ).map( function(v, idx, ar) { return (idx === ar.length - 1 ? chalk.yellow('or ') : '') + chalk.yellow.bold(v.toUpperCase()); }).join( chalk.yellow(', ')) + chalk.yellow(").\n\n"); msg += chalk.gray(FS.readFileSync( PATH.resolve(__dirname, '../cli/use.txt'), 'utf8' )); break; case HACKMYSTATUS.invalidCommand: msg = printf( M2C( this.msgs.invalidCommand.msg, 'yellow'), ex.attempted ); break; case HACKMYSTATUS.resumeNotFoundAlt: msg = M2C( this.msgs.resumeNotFoundAlt.msg, 'yellow' ); break; case HACKMYSTATUS.inputOutputParity: msg = M2C( this.msgs.inputOutputParity.msg ); break; case HACKMYSTATUS.createNameMissing: msg = M2C( this.msgs.createNameMissing.msg ); break; case HACKMYSTATUS.pdfGeneration: msg = M2C( this.msgs.pdfGeneration.msg, 'bold' ); if( ex.inner ) msg += chalk.red('\n' + ex.inner); withStack = true; quit = false; warn = false; break; case HACKMYSTATUS.invalid: msg = M2C( this.msgs.invalid.msg, 'red' ); warn = false; break; case HACKMYSTATUS.invalidFormat: ex.data.forEach(function(d){ msg += printf( M2C( this.msgs.invalidFormat.msg, 'bold' ), ex.theme.name.toUpperCase(), d.format.toUpperCase()); }, this); break; case HACKMYSTATUS.notOnPath: msg = printf( M2C(this.msgs.notOnPath.msg, 'bold'), ex.engine); quit = false; warn = false; break; case HACKMYSTATUS.readError: console.error( printf( M2C(this.msgs.readError.msg, 'red'), ex.file ) ); msg = ex.inner.toString(); warn = false; break; case HACKMYSTATUS.parseError: if( SyntaxErrorEx.is( ex.inner )) { var se = new SyntaxErrorEx( ex, ex.raw ); msg = printf( M2C( this.msgs.parseError.msg, 'red' ), se.line, se.col); } else { msg = ex; } warn = false; break; } return { warning: warn, // True if this is a warning, false if error msg: msg, // The error message to display withStack: withStack, // Whether to include the stack quit: quit }; } }());