mirror of
https://github.com/JuanCanham/HackMyResume.git
synced 2024-11-05 09:56:22 +00:00
Improve error handling.
Better support for spawn errors encountered during generation (for ex, PDFs through wkhtml) + general refactoring.
This commit is contained in:
parent
13430bcad5
commit
02ef2b2241
93
src/core/error-handler.js
Normal file
93
src/core/error-handler.js
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/**
|
||||||
|
@module error-handler.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var HACKMYSTATUS = require('./status-codes')
|
||||||
|
, PKG = require('../../package.json')
|
||||||
|
, title = ('\n*** HackMyResume v' + PKG.version + ' ***').bold.white;
|
||||||
|
|
||||||
|
var ErrorHandler = module.exports = {
|
||||||
|
|
||||||
|
|
||||||
|
err: function( ex, shouldExit ) {
|
||||||
|
var msg = '', exitCode;
|
||||||
|
|
||||||
|
if( ex.fluenterror ){
|
||||||
|
switch( ex.fluenterror ) { // TODO: Remove magic numbers
|
||||||
|
|
||||||
|
case HACKMYSTATUS.themeNotFound:
|
||||||
|
msg = "The specified theme couldn't be found: " + ex.data;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HACKMYSTATUS.copyCSS:
|
||||||
|
msg = "Couldn't copy CSS file to destination folder";
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HACKMYSTATUS.resumeNotFound:
|
||||||
|
msg = 'Please '.guide + 'specify a valid input resume'.guide.bold +
|
||||||
|
' in FRESH or JSON Resume format.'.guide;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HACKMYSTATUS.missingCommand:
|
||||||
|
msg = title + "\nPlease ".guide + "specify a command".guide.bold + " (".guide +
|
||||||
|
Object.keys( FCMD.verbs ).map( function(v, idx, ar) {
|
||||||
|
return (idx === ar.length - 1 ? 'or '.guide : '') +
|
||||||
|
v.toUpperCase().guide;
|
||||||
|
}).join(', '.guide) + ").\n\n".guide +
|
||||||
|
FS.readFileSync( PATH.join(__dirname, 'use.txt'), 'utf8' ).info.bold;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HACKMYSTATUS.invalidCommand:
|
||||||
|
msg = 'Please '.guide + 'specify the output resume file'.guide.bold +
|
||||||
|
' that should be created.'.guide;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HACKMYSTATUS.resumeNotFoundAlt:
|
||||||
|
msg = 'Please '.guide + 'specify a valid input resume'.guide.bold +
|
||||||
|
' in either FRESH or JSON Resume format.'.guide;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HACKMYSTATUS.inputOutputParity:
|
||||||
|
msg = 'Please '.guide + 'specify an output file name'.guide.bold +
|
||||||
|
' for every input file you wish to convert.'.guide;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HACKMYSTATUS.createNameMissing:
|
||||||
|
msg = 'Please '.guide + 'specify the filename of the resume'.guide.bold +
|
||||||
|
' to create.'.guide;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case HACKMYSTATUS.wkhtmltopdf:
|
||||||
|
msg = 'ERROR: PDF generation failed. '.red.bold + ('Make sure wkhtmltopdf is ' +
|
||||||
|
'installed and accessible from your path.').red;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
exitCode = ex.fluenterror;
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg = ex.toString();
|
||||||
|
exitCode = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
var idx = msg.indexOf('Error: ');
|
||||||
|
var trimmed = idx === -1 ? msg : msg.substring( idx + 7 );
|
||||||
|
if( !ex.fluenterror || ex.fluenterror < 3 ) { // TODO: magic #s
|
||||||
|
console.log( ('ERROR: ' + trimmed.toString()).red.bold );
|
||||||
|
console.log( ex.stack.gray);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log( trimmed.toString() );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( shouldExit )
|
||||||
|
process.exit( exitCode );
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
22
src/core/spawn-watch.js
Normal file
22
src/core/spawn-watch.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
/**
|
||||||
|
@module spawn-watch.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
// Catch various out-of-band child process errors such as ENOENT for PDFs
|
||||||
|
// http://stackoverflow.com/q/27688804
|
||||||
|
var SpawnWatcher = module.exports = function() {
|
||||||
|
var childProcess = require("child_process");
|
||||||
|
var oldSpawn = childProcess.spawn;
|
||||||
|
childProcess.spawn = function() {
|
||||||
|
return oldSpawn.apply(this, arguments)
|
||||||
|
.on('error', function(err) {
|
||||||
|
require('./error-handler').err( err, false );
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
||||||
|
//SpawnWatcher();
|
||||||
|
|
||||||
|
}());
|
@ -1,6 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
Definition of the HtmlPdfGenerator class.
|
Definition of the HtmlPdfGenerator class.
|
||||||
@license MIT. Copyright (c) 2015 James Devlin / FluentDesk.
|
|
||||||
@module html-pdf-generator.js
|
@module html-pdf-generator.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -23,7 +22,7 @@ Definition of the HtmlPdfGenerator class.
|
|||||||
Generate the binary PDF.
|
Generate the binary PDF.
|
||||||
*/
|
*/
|
||||||
onBeforeSave: function( info ) {
|
onBeforeSave: function( info ) {
|
||||||
pdf( info.mk, info.outputFile );
|
pdf.call( this, info.mk, info.outputFile );
|
||||||
return null; // halt further processing
|
return null; // halt further processing
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,39 +33,50 @@ Definition of the HtmlPdfGenerator class.
|
|||||||
*/
|
*/
|
||||||
function pdf( markup, fOut ) {
|
function pdf( markup, fOut ) {
|
||||||
|
|
||||||
var pdfCount = 0;
|
pdf_wkhtmltopdf.call( this, markup, fOut );
|
||||||
if( false ) { //( _opts.pdf === 'phantom' || _opts.pdf == 'all' ) {
|
|
||||||
pdfCount++;
|
}
|
||||||
require('phantom').create( function( ph ) {
|
|
||||||
ph.createPage( function( page ) {
|
/**
|
||||||
page.setContent( markup );
|
Generate a PDF from HTML using wkhtmltopdf.
|
||||||
page.set('paperSize', {
|
*/
|
||||||
format: 'A4',
|
function pdf_wkhtmltopdf( markup, fOut ) {
|
||||||
orientation: 'portrait',
|
var wk;
|
||||||
margin: '1cm'
|
try {
|
||||||
});
|
wk = require('wkhtmltopdf');
|
||||||
page.set("viewportSize", {
|
wk( markup, { pageSize: 'letter' } )
|
||||||
width: 1024, // TODO: option-ify
|
.pipe( FS.createWriteStream( fOut ) );
|
||||||
height: 768 // TODO: Use "A" sizes
|
|
||||||
});
|
|
||||||
page.set('onLoadFinished', function(success) {
|
|
||||||
page.render( fOut );
|
|
||||||
pdfCount++;
|
|
||||||
ph.exit();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
{ dnodeOpts: { weak: false } } );
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
if( true ) { // _opts.pdf === 'wkhtmltopdf' || _opts.pdf == 'all' ) {
|
catch(ex) {
|
||||||
var fOut2 = fOut;
|
// { [Error: write EPIPE] code: 'EPIPE', errno: 'EPIPE', syscall: 'write' }
|
||||||
if( pdfCount == 1 ) {
|
// { [Error: ENOENT] }
|
||||||
fOut2 = fOut2.replace(/\.pdf$/g, '.b.pdf');
|
throw { fluenterror: this.codes.wkhtmltopdf };
|
||||||
}
|
|
||||||
require('wkhtmltopdf')( markup, { pageSize: 'letter' } )
|
|
||||||
.pipe( FS.createWriteStream( fOut2 ) );
|
|
||||||
pdfCount++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// function pdf_phantom() {
|
||||||
|
// pdfCount++;
|
||||||
|
// require('phantom').create( function( ph ) {
|
||||||
|
// ph.createPage( function( page ) {
|
||||||
|
// page.setContent( markup );
|
||||||
|
// page.set('paperSize', {
|
||||||
|
// format: 'A4',
|
||||||
|
// orientation: 'portrait',
|
||||||
|
// margin: '1cm'
|
||||||
|
// });
|
||||||
|
// page.set("viewportSize", {
|
||||||
|
// width: 1024, // TODO: option-ify
|
||||||
|
// height: 768 // TODO: Use "A" sizes
|
||||||
|
// });
|
||||||
|
// page.set('onLoadFinished', function(success) {
|
||||||
|
// page.render( fOut );
|
||||||
|
// pdfCount++;
|
||||||
|
// ph.exit();
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
// { dnodeOpts: { weak: false } } );
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
}());
|
}());
|
||||||
|
@ -156,7 +156,7 @@ Definition of the TemplateGenerator class.
|
|||||||
{ outputFile: fileName, mk: file.data } );
|
{ outputFile: fileName, mk: file.data } );
|
||||||
}
|
}
|
||||||
catch(ex) {
|
catch(ex) {
|
||||||
console.log(ex);
|
require('../core/error-handler').err(ex, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( file.info.action === null/* && theme.explicit*/ ) {
|
else if( file.info.action === null/* && theme.explicit*/ ) {
|
||||||
|
83
src/index.js
83
src/index.js
@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
Command-line interface (CLI) for HackMyResume.
|
Command-line interface (CLI) for HackMyResume.
|
||||||
@license MIT. Copyright (c) 2015 James M. Devlin / FluentDesk.
|
@license MIT. Copyright (c) 2015 hacksalot (https://github.com/hacksalot)
|
||||||
@module index.js
|
@module index.js
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var ARGS = require( 'minimist' )
|
|
||||||
|
|
||||||
|
var SPAWNW = require('./core/spawn-watch')
|
||||||
|
, ARGS = require( 'minimist' )
|
||||||
, FCMD = require( './hackmycmd')
|
, FCMD = require( './hackmycmd')
|
||||||
, PKG = require('../package.json')
|
, PKG = require('../package.json')
|
||||||
, COLORS = require('colors')
|
, COLORS = require('colors')
|
||||||
@ -19,11 +22,12 @@ var ARGS = require( 'minimist' )
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
main();
|
main();
|
||||||
}
|
}
|
||||||
catch( ex ) {
|
catch( ex ) {
|
||||||
handleError( ex );
|
require('./core/error-handler').err( ex, true );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -91,76 +95,3 @@ function getOpts( args ) {
|
|||||||
silent: args.s || args.silent
|
silent: args.s || args.silent
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: refactor
|
|
||||||
function handleError( ex ) {
|
|
||||||
var msg = '', exitCode;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if( ex.fluenterror ){
|
|
||||||
switch( ex.fluenterror ) { // TODO: Remove magic numbers
|
|
||||||
|
|
||||||
case HACKMYSTATUS.themeNotFound:
|
|
||||||
msg = "The specified theme couldn't be found: " + ex.data;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HACKMYSTATUS.copyCSS:
|
|
||||||
msg = "Couldn't copy CSS file to destination folder";
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HACKMYSTATUS.resumeNotFound:
|
|
||||||
msg = 'Please '.guide + 'specify a valid input resume'.guide.bold +
|
|
||||||
' in FRESH or JSON Resume format.'.guide;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HACKMYSTATUS.missingCommand:
|
|
||||||
msg = title + "\nPlease ".guide + "specify a command".guide.bold + " (".guide +
|
|
||||||
Object.keys( FCMD.verbs ).map( function(v, idx, ar) {
|
|
||||||
return (idx === ar.length - 1 ? 'or '.guide : '') +
|
|
||||||
v.toUpperCase().guide;
|
|
||||||
}).join(', '.guide) + ").\n\n".guide +
|
|
||||||
FS.readFileSync( PATH.join(__dirname, 'use.txt'), 'utf8' ).info.bold;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HACKMYSTATUS.invalidCommand:
|
|
||||||
msg = 'Please '.guide + 'specify the output resume file'.guide.bold +
|
|
||||||
' that should be created.'.guide;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HACKMYSTATUS.resumeNotFoundAlt:
|
|
||||||
msg = 'Please '.guide + 'specify a valid input resume'.guide.bold +
|
|
||||||
' in either FRESH or JSON Resume format.'.guide;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HACKMYSTATUS.inputOutputParity:
|
|
||||||
msg = 'Please '.guide + 'specify an output file name'.guide.bold +
|
|
||||||
' for every input file you wish to convert.'.guide;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case HACKMYSTATUS.createNameMissing:
|
|
||||||
msg = 'Please '.guide + 'specify the filename of the resume'.guide.bold +
|
|
||||||
' to create.'.guide;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
exitCode = ex.fluenterror;
|
|
||||||
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
msg = ex.toString();
|
|
||||||
exitCode = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
var idx = msg.indexOf('Error: ');
|
|
||||||
var trimmed = idx === -1 ? msg : msg.substring( idx + 7 );
|
|
||||||
if( !ex.fluenterror || ex.fluenterror < 3 ) { // TODO: magic #s
|
|
||||||
console.log( ('ERROR: ' + trimmed.toString()).red.bold );
|
|
||||||
console.log( ex.stack.gray);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
console.log( trimmed.toString() );
|
|
||||||
|
|
||||||
process.exit( exitCode );
|
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
var chai = require('chai')
|
var SPAWNWATCHER = require('../src/core/spawn-watch')
|
||||||
|
, chai = require('chai')
|
||||||
, expect = chai.expect
|
, expect = chai.expect
|
||||||
, should = chai.should()
|
, should = chai.should()
|
||||||
, path = require('path')
|
, path = require('path')
|
||||||
|
Loading…
Reference in New Issue
Block a user