From 212b01092cadb7394358e49ec519c118d3fec2ef Mon Sep 17 00:00:00 2001 From: hacksalot Date: Mon, 1 Feb 2016 09:25:22 -0500 Subject: [PATCH] Improve proc spawn behavior. Interim until async / promises support is in. --- dist/cli/error.js | 1 - dist/core/status-codes.js | 2 +- dist/generators/html-pdf-cli-generator.js | 58 ++++++++------------ dist/utils/safe-spawn.js | 36 ++++++------ src/cli/error.coffee | 1 - src/core/status-codes.coffee | 2 +- src/generators/html-pdf-cli-generator.coffee | 52 ++++++++---------- src/utils/safe-spawn.coffee | 18 +++--- 8 files changed, 75 insertions(+), 95 deletions(-) diff --git a/dist/cli/error.js b/dist/cli/error.js index ab1f2ba..c5d9bad 100644 --- a/dist/cli/error.js +++ b/dist/cli/error.js @@ -140,7 +140,6 @@ Error-handling routines for HackMyResume. if (ex.inner) { msg += chalk.red('\n' + ex.inner); } - withStack = true; quit = false; etype = 'error'; break; diff --git a/dist/core/status-codes.js b/dist/core/status-codes.js index c5d83ad..3c2f79c 100644 --- a/dist/core/status-codes.js +++ b/dist/core/status-codes.js @@ -16,7 +16,7 @@ Status codes for HackMyResume. resumeNotFoundAlt: 6, inputOutputParity: 7, createNameMissing: 8, - pdfgeneration: 9, + pdfGeneration: 9, missingPackageJSON: 10, invalid: 11, invalidFormat: 12, diff --git a/dist/generators/html-pdf-cli-generator.js b/dist/generators/html-pdf-cli-generator.js index 317d428..65bfcf5 100644 --- a/dist/generators/html-pdf-cli-generator.js +++ b/dist/generators/html-pdf-cli-generator.js @@ -6,20 +6,20 @@ Definition of the HtmlPdfCLIGenerator class. */ (function() { - var FS, HTML, HtmlPdfCLIGenerator, PATH, SLASH, SPAWN, TemplateGenerator, engines; + var FS, HMSTATUS, HtmlPdfCLIGenerator, PATH, SLASH, TemplateGenerator, _, engines; TemplateGenerator = require('./template-generator'); FS = require('fs-extra'); - HTML = require('html'); - PATH = require('path'); - SPAWN = require('../utils/safe-spawn'); - SLASH = require('slash'); + _ = require('underscore'); + + HMSTATUS = require('../core/status-codes'); + /** An HTML-driven PDF resume generator for HackMyResume. Talks to Phantom, @@ -34,30 +34,20 @@ Definition of the HtmlPdfCLIGenerator class. /** Generate the binary PDF. */ onBeforeSave: function(info) { - var ex, safe_eng; - try { - safe_eng = info.opts.pdf || 'wkhtmltopdf'; - if (safe_eng !== 'none') { - engines[safe_eng].call(this, info.mk, info.outputFile); - return null; - } - } catch (_error) { - ex = _error; - if (ex.inner && ex.inner.code === 'ENOENT') { - throw { - fluenterror: this.codes.notOnPath, - inner: ex.inner, - engine: ex.cmd, - stack: ex.inner && ex.inner.stack - }; - } else { - throw { - fluenterror: this.codes.pdfGeneration, - inner: ex, - stack: ex.stack - }; - } + var safe_eng; + safe_eng = info.opts.pdf || 'wkhtmltopdf'; + if (safe_eng === 'phantom') { + safe_eng = 'phantomjs'; } + if (_.has(engines, safe_eng)) { + this.SPAWN = require('../utils/safe-spawn'); + this.errHandler = info.opts.errHandler; + engines[safe_eng].call(this, info.mk, info.outputFile, this.onError); + return null; + } + }, + onError: function(ex, param) { + param.errHandler.err(HMSTATUS.pdfGeneration, ex); } }); @@ -70,11 +60,11 @@ Definition of the HtmlPdfCLIGenerator class. TODO: If HTML generation has run, reuse that output TODO: Local web server to ease wkhtmltopdf rendering */ - wkhtmltopdf: function(markup, fOut) { - var info, tempFile; + wkhtmltopdf: function(markup, fOut, on_error) { + var tempFile; tempFile = fOut.replace(/\.pdf$/i, '.pdf.html'); FS.writeFileSync(tempFile, markup, 'utf8'); - return info = SPAWN('wkhtmltopdf', [tempFile, fOut]); + return this.SPAWN('wkhtmltopdf', [tempFile, fOut], false, on_error, this); }, /** @@ -84,14 +74,14 @@ Definition of the HtmlPdfCLIGenerator class. TODO: If HTML generation has run, reuse that output TODO: Local web server to ease Phantom rendering */ - phantom: function(markup, fOut) { - var destPath, info, scriptPath, sourcePath, tempFile; + phantomjs: function(markup, fOut, on_error) { + var destPath, scriptPath, sourcePath, tempFile; tempFile = fOut.replace(/\.pdf$/i, '.pdf.html'); FS.writeFileSync(tempFile, markup, 'utf8'); scriptPath = SLASH(PATH.relative(process.cwd(), PATH.resolve(__dirname, '../utils/rasterize.js'))); sourcePath = SLASH(PATH.relative(process.cwd(), tempFile)); destPath = SLASH(PATH.relative(process.cwd(), fOut)); - return info = SPAWN('phantomjs', [scriptPath, sourcePath, destPath]); + return this.SPAWN('phantomjs', [scriptPath, sourcePath, destPath], false, on_error, this); } }; diff --git a/dist/utils/safe-spawn.js b/dist/utils/safe-spawn.js index dda5e9d..8a1b754 100644 --- a/dist/utils/safe-spawn.js +++ b/dist/utils/safe-spawn.js @@ -5,41 +5,39 @@ Safe spawn utility for HackMyResume / FluentCV. @license MIT. See LICENSE.md for details. */ + +/** Safely spawn a process synchronously or asynchronously without throwing an +exception + */ + (function() { - module.exports = function(cmd, args, isSync, callback) { + module.exports = function(cmd, args, isSync, callback, param) { var info, spawn; try { spawn = require('child_process')[isSync ? 'spawnSync' : 'spawn']; info = spawn(cmd, args); if (!isSync) { info.on('error', function(err) { - if (callback != null) { - callback(err); - } else { - throw { - cmd: cmd, - inner: err - }; + if (typeof callback === "function") { + callback(err, param); } }); } else { if (info.error) { - if (callback != null) { - callback(err); - } else { - throw { - cmd: cmd, - inner: info.error - }; + if (typeof callback === "function") { + callback(info.error, param); } + return { + cmd: cmd, + inner: info.error + }; } } } catch (_error) { - if (callback != null) { - return callback(_error); - } else { - throw _error; + if (typeof callback === "function") { + callback(_error, param); } + return _error; } }; diff --git a/src/cli/error.coffee b/src/cli/error.coffee index e293170..d45154f 100644 --- a/src/cli/error.coffee +++ b/src/cli/error.coffee @@ -139,7 +139,6 @@ assembleError = ( ex ) -> when HMSTATUS.pdfGeneration msg = M2C( this.msgs.pdfGeneration.msg, 'bold' ) msg += chalk.red('\n' + ex.inner) if ex.inner - withStack = true quit = false etype = 'error' diff --git a/src/core/status-codes.coffee b/src/core/status-codes.coffee index 6f32d9d..9bbd4b9 100644 --- a/src/core/status-codes.coffee +++ b/src/core/status-codes.coffee @@ -15,7 +15,7 @@ module.exports = resumeNotFoundAlt: 6 inputOutputParity: 7 createNameMissing: 8 - pdfgeneration: 9 + pdfGeneration: 9 missingPackageJSON: 10 invalid: 11 invalidFormat: 12 diff --git a/src/generators/html-pdf-cli-generator.coffee b/src/generators/html-pdf-cli-generator.coffee index 6827e77..cd0f431 100644 --- a/src/generators/html-pdf-cli-generator.coffee +++ b/src/generators/html-pdf-cli-generator.coffee @@ -6,12 +6,12 @@ Definition of the HtmlPdfCLIGenerator class. -TemplateGenerator = require('./template-generator') -FS = require('fs-extra') -HTML = require( 'html' ) -PATH = require('path') -SPAWN = require('../utils/safe-spawn') -SLASH = require('slash'); +TemplateGenerator = require './template-generator' +FS = require 'fs-extra' +PATH = require 'path' +SLASH = require 'slash' +_ = require 'underscore' +HMSTATUS = require '../core/status-codes' @@ -29,25 +29,18 @@ HtmlPdfCLIGenerator = module.exports = TemplateGenerator.extend ###* Generate the binary PDF. ### onBeforeSave: ( info ) -> - try - safe_eng = info.opts.pdf || 'wkhtmltopdf'; - if safe_eng != 'none' - engines[ safe_eng ].call this, info.mk, info.outputFile - return null # halt further processing - catch ex - # { [Error: write EPIPE] code: 'EPIPE', errno: 'EPIPE', ... } - # { [Error: ENOENT] } - if ex.inner && ex.inner.code == 'ENOENT' - throw - fluenterror: this.codes.notOnPath - inner: ex.inner - engine: ex.cmd, - stack: ex.inner && ex.inner.stack - else - throw - fluenterror: this.codes.pdfGeneration - inner: ex - stack: ex.stack + safe_eng = info.opts.pdf || 'wkhtmltopdf'; + if safe_eng == 'phantom' + safe_eng = 'phantomjs' + if _.has engines, safe_eng + @SPAWN = require '../utils/safe-spawn' + @errHandler = info.opts.errHandler + engines[ safe_eng ].call @, info.mk, info.outputFile, @onError + return null # halt further processing + + onError: (ex, param) -> + param.errHandler.err HMSTATUS.pdfGeneration, ex + return @@ -63,11 +56,11 @@ engines = TODO: If HTML generation has run, reuse that output TODO: Local web server to ease wkhtmltopdf rendering ### - wkhtmltopdf: (markup, fOut) -> + wkhtmltopdf: (markup, fOut, on_error) -> # Save the markup to a temporary file tempFile = fOut.replace /\.pdf$/i, '.pdf.html' FS.writeFileSync tempFile, markup, 'utf8' - info = SPAWN 'wkhtmltopdf', [ tempFile, fOut ] + @SPAWN 'wkhtmltopdf', [ tempFile, fOut ], false, on_error, @ @@ -78,8 +71,7 @@ engines = TODO: If HTML generation has run, reuse that output TODO: Local web server to ease Phantom rendering ### - - phantom: ( markup, fOut ) -> + phantomjs: ( markup, fOut, on_error ) -> # Save the markup to a temporary file tempFile = fOut.replace(/\.pdf$/i, '.pdf.html'); @@ -88,4 +80,4 @@ engines = PATH.resolve( __dirname, '../utils/rasterize.js' ) ) ); sourcePath = SLASH( PATH.relative( process.cwd(), tempFile) ); destPath = SLASH( PATH.relative( process.cwd(), fOut) ); - info = SPAWN('phantomjs', [ scriptPath, sourcePath, destPath ]); + @SPAWN 'phantomjs', [ scriptPath, sourcePath, destPath ], false, on_error, @ diff --git a/src/utils/safe-spawn.coffee b/src/utils/safe-spawn.coffee index d71321d..67932e3 100644 --- a/src/utils/safe-spawn.coffee +++ b/src/utils/safe-spawn.coffee @@ -4,7 +4,9 @@ Safe spawn utility for HackMyResume / FluentCV. @license MIT. See LICENSE.md for details. ### -module.exports = ( cmd, args, isSync, callback ) -> +###* Safely spawn a process synchronously or asynchronously without throwing an +exception ### +module.exports = ( cmd, args, isSync, callback, param ) -> try @@ -12,17 +14,17 @@ module.exports = ( cmd, args, isSync, callback ) -> spawn = require('child_process')[ if isSync then 'spawnSync' else 'spawn']; info = spawn cmd, args - # Check for error depending on whether we're sync or async + # Check for error depending on whether we're sync or async TODO: Promises if !isSync info.on 'error', (err) -> - if callback? then callback err; return - else throw cmd: cmd, inner: err + callback?(err, param) + return return else if info.error - if callback? then callback err; return - else throw cmd: cmd, inner: info.error + callback?(info.error, param) + return cmd: cmd, inner: info.error catch - if callback? then callback _error - else throw _error + callback?(_error, param) + _error