diff --git a/lib/errors.ts b/lib/errors.ts index 70e9e5b9..7e1a4c0c 100644 --- a/lib/errors.ts +++ b/lib/errors.ts @@ -20,7 +20,9 @@ import * as _ from 'lodash'; import * as os from 'os'; import * as Raven from 'raven'; -import * as patterns from './utils/patterns'; +export class ExpectedError extends Error {} + +export class NotLoggedInError extends ExpectedError {} const captureException = Bluebird.promisify( Raven.captureException, @@ -37,11 +39,7 @@ function treatFailedBindingAsMissingModule(error: any): void { } } -function interpret(error: any): string | undefined { - if (!(error instanceof Error)) { - return; - } - +function interpret(error: Error): string { treatFailedBindingAsMissingModule(error); if (hasCode(error)) { @@ -55,9 +53,9 @@ function interpret(error: any): string | undefined { if (!_.isEmpty(error.message)) { return `${error.code}: ${error.message}`; } - } else { - return error.message; } + + return error.message; } const messages: { @@ -105,21 +103,35 @@ const messages: { }; export async function handleError(error: any) { - let message = interpret(error); - if (message == null) { + const { printErrorMessage } = await import('./utils/patterns'); + + process.exitCode = + error.exitCode === 0 + ? 0 + : parseInt(error.exitCode, 10) || process.exitCode || 1; + + if (!(error instanceof Error)) { + printErrorMessage(String(error)); return; } - if (process.env.DEBUG) { - message = error.stack; + const message = [interpret(error)]; + + if (process.env.DEBUG && error.stack) { + message.push(error.stack); + } + printErrorMessage(message.join('\n')); + + if (error instanceof ExpectedError) { + return; } - patterns.printErrorMessage(message!); - + // Report "unexpected" errors via Sentry.io await captureException(error) .timeout(1000) .catch(function() { // Ignore any errors (from error logging, or timeouts) }) - .finally(() => process.exit(error.exitCode || 1)); + // exit with the process.exitCode set earlier + .finally(() => process.exit()); } diff --git a/lib/utils/messages.ts b/lib/utils/messages.ts index 6c9035e1..4faae699 100644 --- a/lib/utils/messages.ts +++ b/lib/utils/messages.ts @@ -18,7 +18,7 @@ export const getHelp = `${DEBUG_MODE ? '' : debugHint}\ If you need help, don't hesitate in contacting our support forums at https://forums.balena.io -For bug reports or feature requests, have a look at the GitHub issues or +For CLI bug reports or feature requests, have a look at the GitHub issues or create a new one at: https://github.com/balena-io/balena-cli/issues/\ `; diff --git a/lib/utils/patterns.ts b/lib/utils/patterns.ts index e65208d1..235e1b81 100644 --- a/lib/utils/patterns.ts +++ b/lib/utils/patterns.ts @@ -22,6 +22,7 @@ import _ = require('lodash'); import _form = require('resin-cli-form'); import _visuals = require('resin-cli-visuals'); +import { NotLoggedInError } from '../errors'; import messages = require('./messages'); import validation = require('./validation'); @@ -77,16 +78,28 @@ export function authenticate(options: {}): Bluebird { }); } -export async function exitIfNotLoggedIn(): Promise { +export async function checkLoggedIn(): Promise { const balena = getBalenaSdk(); if (!(await balena.auth.isLoggedIn())) { - exitWithExpectedError(stripIndent` + throw new NotLoggedInError(stripIndent` You have to log in to continue Run the following command to go through the login wizard: $ balena login`); } } +export async function exitIfNotLoggedIn(): Promise { + try { + await checkLoggedIn(); + } catch (error) { + if (error instanceof NotLoggedInError) { + exitWithExpectedError(error); + } else { + throw error; + } + } +} + export function askLoginType() { return getForm().ask({ message: 'How would you like to login?',