From 46ebb7b1fdda76e15c4dd84cc93c48191df763eb Mon Sep 17 00:00:00 2001 From: Juan Cruz Viotti Date: Mon, 22 Dec 2014 12:47:12 -0400 Subject: [PATCH] Move errors.handle() out of resin sdk --- lib/actions/app.coffee | 13 ++--- lib/actions/auth.coffee | 7 +-- lib/actions/device.coffee | 11 +++-- lib/actions/environment-variables.coffee | 15 +++--- lib/actions/examples.coffee | 7 +-- lib/actions/keys.coffee | 11 +++-- lib/actions/logs.coffee | 7 +-- lib/actions/os.coffee | 3 +- lib/app.coffee | 5 +- lib/errors/errors.coffee | 18 +++++++ lib/errors/errors.spec.coffee | 63 ++++++++++++++++++++++++ lib/resin/errors/errors.coffee | 30 ----------- lib/resin/errors/errors.spec.coffee | 59 ---------------------- 13 files changed, 125 insertions(+), 124 deletions(-) create mode 100644 lib/errors/errors.coffee create mode 100644 lib/errors/errors.spec.coffee diff --git a/lib/actions/app.coffee b/lib/actions/app.coffee index 08939dc8..83d1d66b 100644 --- a/lib/actions/app.coffee +++ b/lib/actions/app.coffee @@ -4,6 +4,7 @@ gitCli = require('git-cli') resin = require('../resin') ui = require('../ui') log = require('../log/log') +errors = require('../errors/errors') permissions = require('../permissions/permissions') exports.create = permissions.user (params, options) -> @@ -26,11 +27,11 @@ exports.create = permissions.user (params, options) -> resin.models.application.create(params.name, slugifiedType, callback) - ], resin.errors.handle + ], errors.handle exports.list = permissions.user -> resin.models.application.getAll (error, applications) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? log.out ui.widgets.table.horizontal applications, (application) -> application.device_type = resin.device.getDisplayName(application.device_type) @@ -43,7 +44,7 @@ exports.list = permissions.user -> exports.info = permissions.user (params) -> resin.models.application.get params.id, (error, application) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? log.out ui.widgets.table.vertical application, (application) -> application.device_type = resin.device.getDisplayName(application.device_type) @@ -53,12 +54,12 @@ exports.info = permissions.user (params) -> exports.restart = permissions.user (params) -> resin.models.application.restart params.id, (error) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? exports.remove = permissions.user (params, options) -> ui.patterns.remove 'application', options.yes, (callback) -> resin.models.application.remove(params.id, callback) - , resin.errors.handle + , errors.handle exports.init = permissions.user (params) -> @@ -82,4 +83,4 @@ exports.init = permissions.user (params) -> resin.vcs.initProjectWithApplication(application, currentDirectory, callback) ], (error) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? diff --git a/lib/actions/auth.coffee b/lib/actions/auth.coffee index 812ed436..511959eb 100644 --- a/lib/actions/auth.coffee +++ b/lib/actions/auth.coffee @@ -4,6 +4,7 @@ async = require('async') resin = require('../resin') ui = require('../ui') log = require('../log/log') +errors = require('../errors/errors') permissions = require('../permissions/permissions') exports.login = (params) -> @@ -18,7 +19,7 @@ exports.login = (params) -> (credentials, callback) -> resin.auth.login(credentials, callback) - ], resin.errors.handle + ], errors.handle exports.logout = permissions.user -> resin.auth.logout() @@ -30,10 +31,10 @@ exports.signup = -> exports.whoami = permissions.user -> resin.auth.whoami (error, username) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? if not username? error = new Error('Username not found') - resin.errors.handle(error) + errors.handle(error) log.out(username) diff --git a/lib/actions/device.coffee b/lib/actions/device.coffee index 07336a65..d0d53ea5 100644 --- a/lib/actions/device.coffee +++ b/lib/actions/device.coffee @@ -3,11 +3,12 @@ async = require('async') resin = require('../resin') ui = require('../ui') log = require('../log/log') +errors = require('../errors/errors') permissions = require('../permissions/permissions') exports.list = permissions.user (params) -> resin.models.device.getAllByApplication params.id, (error, devices) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? log.out ui.widgets.table.horizontal devices, (device) -> device.application = device.application[0].app_name @@ -21,7 +22,7 @@ exports.list = permissions.user (params) -> exports.info = permissions.user (params) -> resin.models.device.get params.id, (error, device) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? log.out ui.widgets.table.vertical device, (device) -> device.device_type = resin.device.getDisplayName(device.device_type) @@ -46,11 +47,11 @@ exports.info = permissions.user (params) -> exports.remove = permissions.user (params, options) -> ui.patterns.remove 'device', options.yes, (callback) -> resin.models.device.remove(params.id, callback) - , resin.errors.handle + , errors.handle exports.identify = permissions.user (params) -> resin.models.device.identify params.uuid, (error) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? # TODO: This action doesn't return any error # if trying to rename a device that does not @@ -67,4 +68,4 @@ exports.rename = permissions.user (params) -> resin.models.device.rename(params.id, name, callback) ], (error) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? diff --git a/lib/actions/environment-variables.coffee b/lib/actions/environment-variables.coffee index b41db734..1fbfc5cd 100644 --- a/lib/actions/environment-variables.coffee +++ b/lib/actions/environment-variables.coffee @@ -3,6 +3,7 @@ resin = require('../resin') ui = require('../ui') permissions = require('../permissions/permissions') log = require('../log/log') +errors = require('../errors/errors') SYSTEM_VAR_REGEX = /^RESIN_/ @@ -11,10 +12,10 @@ isSystemVariable = (environmentVariable) -> exports.list = permissions.user (params, options) -> if not options.application? - resin.errors.handle(new Error('You have to specify an application')) + errors.handle(new Error('You have to specify an application')) resin.models.environmentVariables.getAllByApplication options.application, (error, environmentVariables) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? if not options.verbose environmentVariables = _.reject(environmentVariables, isSystemVariable) @@ -24,23 +25,23 @@ exports.list = permissions.user (params, options) -> exports.remove = permissions.user (params, options) -> ui.patterns.remove 'environment variable', options.yes, (callback) -> resin.models.environmentVariables.remove(params.id, callback) - , resin.errors.handle + , errors.handle exports.add = permissions.user (params, options) -> if not options.application? - resin.errors.handle(new Error('You have to specify an application')) + errors.handle(new Error('You have to specify an application')) if not params.value? params.value = process.env[params.key] if not params.value? - resin.errors.handle(new Error("Environment value not found for key: #{params.key}")) + errors.handle(new Error("Environment value not found for key: #{params.key}")) else log.info("Warning: using #{params.key}=#{params.value} from host environment") resin.models.environmentVariables.create options.application, params.key, params.value, (error) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? exports.rename = permissions.user (params, options) -> resin.models.environmentVariables.update params.id, params.value, (error) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? diff --git a/lib/actions/examples.coffee b/lib/actions/examples.coffee index d2340226..1f4cd690 100644 --- a/lib/actions/examples.coffee +++ b/lib/actions/examples.coffee @@ -7,6 +7,7 @@ resin = require('../resin') permissions = require('../permissions/permissions') ui = require('../ui') log = require('../log/log') +errors = require('../errors/errors') examplesData = require('../data/examples.json') exports.list = permissions.user -> @@ -28,7 +29,7 @@ exports.info = permissions.user (params) -> if not example? error = new Error("Unknown example: #{id}") - resin.errors.handle(error) + errors.handle(error) log.out ui.widgets.table.vertical example, (example) -> delete example.name @@ -48,7 +49,7 @@ exports.clone = permissions.user (params) -> if not example? error = new Error("Unknown example: #{id}") - resin.errors.handle(error) + errors.handle(error) async.waterfall [ @@ -65,4 +66,4 @@ exports.clone = permissions.user (params) -> gitCli.Repository.clone(example.repository, example.name, callback) ], (error) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? diff --git a/lib/actions/keys.coffee b/lib/actions/keys.coffee index f509d85d..27673329 100644 --- a/lib/actions/keys.coffee +++ b/lib/actions/keys.coffee @@ -7,10 +7,11 @@ helpers = require('../helpers/helpers') ui = require('../ui') log = require('../log/log') permissions = require('../permissions/permissions') +errors = require('../errors/errors') exports.list = permissions.user -> resin.server.get resin.settings.get('urls.keys'), (error, response, keys) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? log.out ui.widgets.table.horizontal keys, (key) -> delete key.public_key return key @@ -22,10 +23,10 @@ exports.info = permissions.user (params) -> # As a workaround, we request all of them, and filter # the one we need. Fix once we have a better way. resin.server.get resin.settings.get('urls.keys'), (error, response, keys) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? key = _.findWhere(keys, id: params.id) if not key? - resin.errors.handle(new resin.errors.NotFound("key #{params.id}")) + errors.handle(new resin.errors.NotFound("key #{params.id}")) key.public_key = '\n' + _.str.chop(key.public_key, resin.settings.get('sshKeyWidth')).join('\n') log.out(ui.widgets.table.vertical(key, _.identity, [ 'ID', 'Title', 'Public Key' ])) @@ -34,7 +35,7 @@ exports.remove = permissions.user (params, options) -> ui.patterns.remove 'key', options.yes, (callback) -> url = _.template(resin.settings.get('urls.sshKey'), id: params.id) resin.server.delete(url, callback) - , resin.errors.handle + , errors.handle exports.add = permissions.user (params) -> async.waterfall [ @@ -66,4 +67,4 @@ exports.add = permissions.user (params) -> if error.code is 'ENOENT' error = new resin.errors.FileNotFound(params.path) - resin.errors.handle(error) + errors.handle(error) diff --git a/lib/actions/logs.coffee b/lib/actions/logs.coffee index 184c3def..2d571b2a 100644 --- a/lib/actions/logs.coffee +++ b/lib/actions/logs.coffee @@ -4,6 +4,7 @@ resin = require('../resin') helpers = require('../helpers/helpers') permissions = require('../permissions/permissions') log = require('../log/log') +errors = require('../errors/errors') LOGS_HISTORY_COUNT = 200 @@ -22,13 +23,13 @@ exports.logs = permissions.user (params, options) -> tailOutput = options.tail or false if numberOfLines? and not _.isNumber(numberOfLines) - resin.errors.handle(new Error('n/num should be a number')) + errors.handle(new Error('n/num should be a number')) helpers.isDeviceUUIDValid params.uuid, (error, isValidUUID) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? if not isValidUUID - return resin.errors.handle(new Error('Invalid UUID')) + return errors.handle(new Error('Invalid UUID')) # PubNub needs to be initialised after logs # action was called, otherwise it prevents diff --git a/lib/actions/os.coffee b/lib/actions/os.coffee index 42b5d27c..44a97ef2 100644 --- a/lib/actions/os.coffee +++ b/lib/actions/os.coffee @@ -8,6 +8,7 @@ connection = require('../connection/connection') ui = require('../ui') log = require('../log/log') permissions = require('../permissions/permissions') +errors = require('../errors/errors') exports.download = (params, options) -> networkParams = @@ -41,5 +42,5 @@ exports.download = (params, options) -> ui.patterns.downloadFile(downloadUrl, outputFile, callback) ], (error) -> - resin.errors.handle(error) if error? + errors.handle(error) if error? log.info("\nFinished downloading #{outputFile}") diff --git a/lib/app.coffee b/lib/app.coffee index ab3f5850..f8be86eb 100644 --- a/lib/app.coffee +++ b/lib/app.coffee @@ -3,12 +3,13 @@ capitano = require('capitano') resin = require('./resin') packageJSON = require('../package.json') actions = require('./actions') +log = require('./log/log') capitano.command signature: 'version' description: 'output the version number' action: -> - resin.log.out(packageJSON.version) + log.out(packageJSON.version) capitano.command signature: 'help [command...]' @@ -542,7 +543,7 @@ changeProjectDirectory = (directory) -> resin.data.prefix.set resin.settings.get('dataPrefix'), (error) -> resin.errors.handle(error) if error? - resin.log.setQuiet(cli.global.quiet) + log.setQuiet(cli.global.quiet) if cli.global.project? changeProjectDirectory(cli.global.project) diff --git a/lib/errors/errors.coffee b/lib/errors/errors.coffee new file mode 100644 index 00000000..6a76df07 --- /dev/null +++ b/lib/errors/errors.coffee @@ -0,0 +1,18 @@ +_ = require('lodash') +log = require('../log/log') + +exports.handle = (error, exit = true) -> + return if not error? or error not instanceof Error + + if process.env.DEBUG + log.error(error.stack) + else + if error.message? + log.error(error.message) + + if _.isNumber(error.code) + errorCode = error.code + else + errorCode = 1 + + process.exit(errorCode) if exit diff --git a/lib/errors/errors.spec.coffee b/lib/errors/errors.spec.coffee new file mode 100644 index 00000000..97b95593 --- /dev/null +++ b/lib/errors/errors.spec.coffee @@ -0,0 +1,63 @@ +expect = require('chai').expect +sinon = require('sinon') +log = require('../log/log') +errors = require('./errors') + +describe 'Errors:', -> + + describe '#handle()', -> + + it 'should log the error message to stderr', -> + message = 'Hello World' + logErrorStub = sinon.stub(log, 'error') + error = new Error(message) + errors.handle(error, false) + expect(logErrorStub).to.have.been.calledWith(message) + logErrorStub.restore() + + it 'should do nothing if error is not an instance of Error', -> + logErrorStub = sinon.stub(log, 'error') + + for item in [ + undefined + null + [ 1, 2, 3 ] + 'Hello' + { message: 'foo bar' } + ] + errors.handle(item, false) + + expect(logErrorStub).to.not.have.been.called + logErrorStub.restore() + + checkProcessExitOption = (error, value, expectations) -> + processExitStub = sinon.stub(process, 'exit') + logErrorStub = sinon.stub(log, 'error') + errors.handle(error, value) + expectations(processExitStub, logErrorStub) + processExitStub.restore() + logErrorStub.restore() + + it 'should exit if the last parameter is true', -> + error = new Error() + checkProcessExitOption error, true, (processExitStub) -> + expect(processExitStub).to.have.been.calledWith(1) + + it 'should not exit if the last parameter is false', -> + error = new Error() + checkProcessExitOption error, false, (processExitStub) -> + expect(processExitStub).to.not.have.been.called + + it 'should handle a custom error code from the error instance', -> + error = new Error() + error.code = 123 + checkProcessExitOption error, true, (processExitStub) -> + expect(processExitStub).to.have.been.calledWith(123) + + it 'should print stack trace if DEBUG is set', -> + process.env.DEBUG = true + error = new Error() + checkProcessExitOption error, false, (processExitStub, logErrorStub) -> + expect(logErrorStub).to.have.been.calledOnce + expect(logErrorStub).to.have.been.calledWith(error.stack) + delete process.env.DEBUG diff --git a/lib/resin/errors/errors.coffee b/lib/resin/errors/errors.coffee index 485c46b8..2d20777c 100644 --- a/lib/resin/errors/errors.coffee +++ b/lib/resin/errors/errors.coffee @@ -1,6 +1,4 @@ -_ = require('lodash') TypedError = require('typed-error') -log = require('../../log/log') exports.NotFound = class NotFound extends TypedError @@ -125,31 +123,3 @@ exports.FileNotFound = class FileNotFound extends TypedError # Error code code: 1 - -# Handle error instances -# -# Prints the message to stderr and aborts the program with the corresponding error code, or 0 if none. -# -# @param {Error} error the error instance -# @param {Boolean} exit whether to exit or not (defaults to true) -# -# @example Handle error -# error = new Error('My Error') -# shouldExit = false -# resin.errors.handle(error, shouldExit) -# -exports.handle = (error, exit = true) -> - return if not error? or error not instanceof Error - - if process.env.DEBUG - log.error(error.stack) - else - if error.message? - log.error(error.message) - - if _.isNumber(error.code) - errorCode = error.code - else - errorCode = 1 - - process.exit(errorCode) if exit diff --git a/lib/resin/errors/errors.spec.coffee b/lib/resin/errors/errors.spec.coffee index 1962263f..af202fdd 100644 --- a/lib/resin/errors/errors.spec.coffee +++ b/lib/resin/errors/errors.spec.coffee @@ -1,67 +1,8 @@ expect = require('chai').expect -sinon = require('sinon') -log = require('../../log/log') errors = require('./errors') describe 'Errors:', -> - describe '#handle()', -> - - it 'should log the error message to stderr', -> - message = 'Hello World' - logErrorStub = sinon.stub(log, 'error') - error = new Error(message) - errors.handle(error, false) - expect(logErrorStub).to.have.been.calledWith(message) - logErrorStub.restore() - - it 'should do nothing if error is not an instance of Error', -> - logErrorStub = sinon.stub(log, 'error') - - for item in [ - undefined - null - [ 1, 2, 3 ] - 'Hello' - { message: 'foo bar' } - ] - errors.handle(item, false) - - expect(logErrorStub).to.not.have.been.called - logErrorStub.restore() - - checkProcessExitOption = (error, value, expectations) -> - processExitStub = sinon.stub(process, 'exit') - logErrorStub = sinon.stub(log, 'error') - errors.handle(error, value) - expectations(processExitStub, logErrorStub) - processExitStub.restore() - logErrorStub.restore() - - it 'should exit if the last parameter is true', -> - error = new Error() - checkProcessExitOption error, true, (processExitStub) -> - expect(processExitStub).to.have.been.calledWith(1) - - it 'should not exit if the last parameter is false', -> - error = new Error() - checkProcessExitOption error, false, (processExitStub) -> - expect(processExitStub).to.not.have.been.called - - it 'should handle a custom error code from the error instance', -> - error = new Error() - error.code = 123 - checkProcessExitOption error, true, (processExitStub) -> - expect(processExitStub).to.have.been.calledWith(123) - - it 'should print stack trace if DEBUG is set', -> - process.env.DEBUG = true - error = new Error() - checkProcessExitOption error, false, (processExitStub, logErrorStub) -> - expect(logErrorStub).to.have.been.calledOnce - expect(logErrorStub).to.have.been.calledWith(error.stack) - delete process.env.DEBUG - describe 'NotFound', -> it 'should get a custom message', ->