1
0
mirror of https://github.com/JuanCanham/HackMyResume.git synced 2024-11-22 08:20:11 +00:00

Improve error handling.

This commit is contained in:
hacksalot 2016-01-18 17:13:37 -05:00
parent 3e3803ed85
commit c98d05270e
7 changed files with 105 additions and 86 deletions

View File

@ -59,8 +59,10 @@ Error-handling routines for HackMyResume.
)); ));
// Output the stack (sometimes) // Output the stack (sometimes)
if( objError.showStack ) if( objError.withStack ) {
o( chalk.red( ex.stack || ex.inner.stack ) ); var stack = ex.stack || (ex.inner && ex.inner.stack);
stack && o( chalk.red( stack ) );
}
// Quit if necessary // Quit if necessary
if( objError.quit ) { if( objError.quit ) {
@ -101,6 +103,7 @@ Error-handling routines for HackMyResume.
function assembleError( ex ) { function assembleError( ex ) {
var msg = '', withStack = false, isError = false, quit = true, warn = true; var msg = '', withStack = false, isError = false, quit = true, warn = true;
if( this.debug ) withStack = true;
switch( ex.fluenterror ) { switch( ex.fluenterror ) {
@ -156,7 +159,15 @@ Error-handling routines for HackMyResume.
break; break;
case HMSTATUS.generateError: case HMSTATUS.generateError:
console.log(ex); msg = (ex.inner && ex.inner.toString()) || ex;
quit = false;
warn = false;
break;
case HMSTATUS.fileSaveError:
msg = printf( M2C( this.msgs.fileSaveError.msg ), (ex.inner || ex).toString() );
warn = false;
quit = false;
break; break;
case HMSTATUS.invalidFormat: case HMSTATUS.invalidFormat:
@ -184,6 +195,11 @@ Error-handling routines for HackMyResume.
warn = false; warn = false;
break; break;
case HMSTATUS.mixedMerge:
msg = M2C( this.msgs.mixedMerge.msg );
quit = false;
break;
case HMSTATUS.parseError: case HMSTATUS.parseError:
if( SyntaxErrorEx.is( ex.inner )) { if( SyntaxErrorEx.is( ex.inner )) {
var se = new SyntaxErrorEx( ex, ex.raw ); var se = new SyntaxErrorEx( ex, ex.raw );

View File

@ -82,3 +82,7 @@ errors:
msg: Invalid or corrupt JSON on line %s column %s. msg: Invalid or corrupt JSON on line %s column %s.
invalidHelperUse: invalidHelperUse:
msg: Invalid use of the **%s** theme helper. msg: Invalid use of the **%s** theme helper.
fileSaveError:
msg: An error occurred while writing %s to disk: %s.
mixedMerge:
msg: "**Warning:** merging mixed resume types. Errors may occur."

View File

@ -97,13 +97,16 @@ Output routines for HackMyResume.
msg += printf( msg += printf(
((idx === 0) ? ((idx === 0) ?
this.msgs.beforeMerge.msg[0] : this.msgs.beforeMerge.msg[0] :
this.msgs.beforeMerge.msg[1] ), a.i().file this.msgs.beforeMerge.msg[1] ), a.file
); );
}, this); }, this);
L( M2C(msg, 'green') ); L( M2C(msg, evt.mixed ? 'yellow' : 'green') );
break; break;
case HME.afterMerge: case HME.afterMerge:
break;
case HME.applyTheme:
var numFormats = Object.keys( this.theme.formats ).length; var numFormats = Object.keys( this.theme.formats ).length;
L( M2C(this.msgs.afterMerge.msg, 'green'), L( M2C(this.msgs.afterMerge.msg, 'green'),
this.theme.name.toUpperCase(), this.theme.name.toUpperCase(),

View File

@ -25,7 +25,8 @@ Status codes for HackMyResume.
parseError: 15, parseError: 15,
fileSaveError: 16, fileSaveError: 16,
generateError: 17, generateError: 17,
invalidHelperUse: 18 invalidHelperUse: 18,
mixedMerge: 19
}; };
}()); }());

View File

@ -15,7 +15,6 @@ Definition of the TemplateGenerator class. TODO: Refactor
, PATH = require('path') , PATH = require('path')
, parsePath = require('parse-filepath') , parsePath = require('parse-filepath')
, MKDIRP = require('mkdirp') , MKDIRP = require('mkdirp')
, HMSTATUS = require('../core/status-codes')
, BaseGenerator = require( './base-generator' ) , BaseGenerator = require( './base-generator' )
, EXTEND = require('../utils/extend') , EXTEND = require('../utils/extend')
, FRESHTheme = require('../core/fresh-theme') , FRESHTheme = require('../core/fresh-theme')
@ -102,12 +101,13 @@ Definition of the TemplateGenerator class. TODO: Refactor
var that = this; var that = this;
// "Generate": process individual files within the theme // "Generate": process individual files within the theme
// The transform() method catches exceptions internally
return { return {
files: curFmt.files.map( function( tplInfo ) { files: curFmt.files.map( function( tplInfo ) {
return { return {
info: tplInfo, info: tplInfo,
data: tplInfo.action === 'transform' ? data: tplInfo.action === 'transform' ?
transform.call( that, rez, tplInfo, theme ) : undefined transform.call( that, rez, tplInfo, theme, opts ) : undefined
}; };
}).filter(function(item){ return item !== null; }), }).filter(function(item){ return item !== null; }),
themeInfo: themeInfo themeInfo: themeInfo
@ -153,7 +153,6 @@ Definition of the TemplateGenerator class. TODO: Refactor
if( file.info.action === 'transform' ) { if( file.info.action === 'transform' ) {
thisFilePath = PATH.join( outFolder, file.info.orgPath ); thisFilePath = PATH.join( outFolder, file.info.orgPath );
try {
if( that.onBeforeSave ) { if( that.onBeforeSave ) {
file.data = that.onBeforeSave({ file.data = that.onBeforeSave({
theme: theme, theme: theme,
@ -170,22 +169,11 @@ Definition of the TemplateGenerator class. TODO: Refactor
that.onAfterSave && that.onAfterSave( that.onAfterSave && that.onAfterSave(
{ outputFile: fileName, mk: file.data, opts: that.opts } ); { outputFile: fileName, mk: file.data, opts: that.opts } );
} }
catch( ex ) {
that.stat( HME.error, ex.fluenterrror ||
{ fluenterror: HMSTATUS.fileSaveError, inner: ex } );
}
}
else if( file.info.action === null/* && theme.explicit*/ ) { else if( file.info.action === null/* && theme.explicit*/ ) {
thisFilePath = PATH.join( outFolder, file.info.orgPath ); thisFilePath = PATH.join( outFolder, file.info.orgPath );
try {
MKDIRP.sync( PATH.dirname(thisFilePath) ); MKDIRP.sync( PATH.dirname(thisFilePath) );
FS.copySync( file.info.path, thisFilePath ); FS.copySync( file.info.path, thisFilePath );
} }
catch( ex ) {
that.stat( HME.error, ex.fluenterrror ||
{ fluenterror: HMSTATUS.fileSaveError, inner: ex } );
}
}
}); });
// Some themes require a symlink structure. If so, create it. // Some themes require a symlink structure. If so, create it.
@ -271,7 +259,7 @@ Definition of the TemplateGenerator class. TODO: Refactor
function transform( rez, tplInfo, theme ) { function transform( rez, tplInfo, theme, opts ) {
try { try {
var cssInfo = { var cssInfo = {
file: tplInfo.css ? tplInfo.cssPath : null, file: tplInfo.css ? tplInfo.cssPath : null,
@ -281,15 +269,8 @@ Definition of the TemplateGenerator class. TODO: Refactor
theme ); theme );
} }
catch(ex) { catch(ex) {
if( ex.fluenterror ) if( opts.errHandler ) opts.errHandler(ex);
throw ex; else throw ex;
else {
console.log('Ballyhoo');
console.log(ex.stack);
throw {
fluenterror: HMSTATUS.generateError, inner: ex
};
}
} }
} }

View File

@ -279,7 +279,7 @@ Generic template helper definitions for HackMyResume / FluentCV.
// Prevent accidental use of safe.start, safe.end, safe.date // Prevent accidental use of safe.start, safe.end, safe.date
// The dateRange helper is for raw dates only // The dateRange helper is for raw dates only
if( moment.isMoment( dateA ) || moment.isMoment( dateB ) ) { if( moment.isMoment( dateA ) || moment.isMoment( dateB ) ) {
_reportError( HMSTATUS.invalidHelperUse, { helper: 'dateRange' } ) _reportError( HMSTATUS.invalidHelperUse, { helper: 'dateRange' } );
return ''; return '';
} }

View File

@ -32,7 +32,7 @@ Implementation of the 'build' verb for HackMyResume.
, pad = require('string-padding') , pad = require('string-padding')
, Verb = require('../verbs/verb'); , Verb = require('../verbs/verb');
var _err, _log, rez; var _err, _log, _rezObj;
@ -65,50 +65,62 @@ Implementation of the 'build' verb for HackMyResume.
*/ */
function build( src, dst, opts ) { function build( src, dst, opts ) {
if( !src || !src.length ) { this.err( HMSTATUS.resumeNotFound ); } if( !src || !src.length ) { this.err( HMSTATUS.resumeNotFound ); }
prep( src, dst, opts ); prep( src, dst, opts );
// Load input resumes... // Load input resumes as JSON...
var sheets = ResumeFactory.load(src, { var sheetObjects = ResumeFactory.load(src, {
format: null, objectify: true, throw: true, inner: { sort: _opts.sort } format: null, objectify: false, throw: true, inner: { sort: _opts.sort }
}, this).map( function(sh) { }, this);
return sh.rez;
});
// Load the theme...we do this first because the theme choice (FRESH or var sheets = sheetObjects.map(function(r) { return r.json; });
// JSON Resume) determines what format we'll convert the resume to.
// Load the theme...
this.stat( HMEVENT.beforeTheme, { theme: _opts.theme }); this.stat( HMEVENT.beforeTheme, { theme: _opts.theme });
var tFolder = verifyTheme.call( this, _opts.theme ); var tFolder = verifyTheme.call( this, _opts.theme );
var theme = loadTheme( tFolder ); var theme = loadTheme( tFolder );
this.stat( HMEVENT.afterTheme, { theme: theme }); this.stat( HMEVENT.afterTheme, { theme: theme });
// Check for invalid outputs // Check for invalid outputs...
var inv = verifyOutputs.call( this, dst, theme ); var inv = verifyOutputs.call( this, dst, theme );
if( inv && inv.length ) { if( inv && inv.length ) {
this.err( HMSTATUS.invalidFormat, { data: inv, theme: theme } ); this.err( HMSTATUS.invalidFormat, { data: inv, theme: theme } );
} }
// Convert resume inputs as necessary // Merge input resumes, yielding a single source resume.
var toFormat = theme.render ? 'JRS' : 'FRESH'; var rez;
sheets.forEach( function( sh, idx ) { if( sheets.length > 1 ) {
if( sh.format() !== toFormat ) {
this.stat( HMEVENT.beforeInlineConvert );
sheets[ idx ] = new (RTYPES[ toFormat ])();
var convJSON = RConverter[ 'to' + toFormat ]( sh );
sheets[ idx ].parseJSON( convJSON );
this.stat( HMEVENT.afterInlineConvert, { file: sh.i().file, fmt: toFormat } );
}
}, this);
// Merge input resumes... var isFRESH = !sheets[0].basics;
(sheets.length > 1) && this.stat( HMEVENT.beforeMerge, { f: _.clone(sheets) }); var mixed = _.any( sheets, function(s) { return isFRESH ? s.basics : !s.basics; });
this.stat( HMEVENT.beforeMerge, { f: _.clone(sheetObjects), mixed: mixed });
if( mixed ) {
this.err( HMSTATUS.mixedMerge );
}
rez = _.reduceRight( sheets, function( a, b, idx ) { rez = _.reduceRight( sheets, function( a, b, idx ) {
return extend( true, b, a ); return extend( true, b, a );
}); });
// TODO: Fix this condition this.stat( HMEVENT.afterMerge, { r: rez } );
(sheets.length) && this.stat( HMEVENT.afterMerge, { r: rez } ); }
else {
rez = sheets[0];
}
this.stat( HMEVENT.applyTheme, { r: rez });
// Convert the merged source resume to the theme's format, if necessary
var orgFormat = rez.basics ? 'JRS' : 'FRESH';
var toFormat = theme.render ? 'JRS' : 'FRESH';
if( toFormat !== orgFormat ) {
this.stat( HMEVENT.beforeInlineConvert );
rez = RConverter[ 'to' + toFormat ]( rez );
this.stat( HMEVENT.afterInlineConvert, { file: sheetObjects[0].file, fmt: toFormat });
}
// Load the resume into a FRESHResume or JRSResume object
_rezObj = new (RTYPES[ toFormat ])().parseJSON( rez );
// Expand output resumes... // Expand output resumes...
var targets = expand( dst, theme ); var targets = expand( dst, theme );
@ -148,6 +160,10 @@ Implementation of the 'build' verb for HackMyResume.
} }
function handleInternalError( ex ) {
console.log(ex);
}
/** /**
Generate a single target resume such as "out/rez.html" or "out/rez.doc". Generate a single target resume such as "out/rez.html" or "out/rez.doc".
@ -157,14 +173,12 @@ Implementation of the 'build' verb for HackMyResume.
*/ */
function single( targInfo, theme, finished ) { function single( targInfo, theme, finished ) {
var ret, ex; var ret, ex, f = targInfo.file;
try { try {
if( !targInfo.fmt ) {
return; if( !targInfo.fmt ) { return; }
} var fType = targInfo.fmt.outFormat
var f = targInfo.file
, fType = targInfo.fmt.outFormat
, fName = PATH.basename(f, '.' + fType) , fName = PATH.basename(f, '.' + fType)
, theFormat; , theFormat;
@ -180,8 +194,8 @@ Implementation of the 'build' verb for HackMyResume.
function(fmt) { return fmt.name === targInfo.fmt.outFormat; })[0]; function(fmt) { return fmt.name === targInfo.fmt.outFormat; })[0];
MKDIRP.sync( PATH.dirname( f ) ); // Ensure dest folder exists; MKDIRP.sync( PATH.dirname( f ) ); // Ensure dest folder exists;
_opts.targets = finished; _opts.targets = finished;
_opts.errHandler = this; _opts.errHandler = handleInternalError;
ret = theFormat.gen.generate( rez, f, _opts ); ret = theFormat.gen.generate( _rezObj, f, _opts );
} }
//Otherwise this is an ad-hoc format (JSON, YML, or PNG) that every theme //Otherwise this is an ad-hoc format (JSON, YML, or PNG) that every theme
// gets "for free". // gets "for free".
@ -191,8 +205,8 @@ Implementation of the 'build' verb for HackMyResume.
})[0]; })[0];
var outFolder = PATH.dirname( f ); var outFolder = PATH.dirname( f );
MKDIRP.sync( outFolder ); // Ensure dest folder exists; MKDIRP.sync( outFolder ); // Ensure dest folder exists;
_opts.errHandler = this; _opts.errHandler = handleInternalError;
ret = theFormat.gen.generate( rez, f, _opts ); ret = theFormat.gen.generate( _rezObj, f, _opts );
} }
} }
catch( e ) { catch( e ) {