Error handling: add ExpectedError type as alternative to exitWithExpectedError()

Change-type: patch
Signed-off-by: Paulo Castro <paulo@balena.io>
This commit is contained in:
Paulo Castro 2019-10-31 01:40:57 +00:00
parent 268bc36843
commit a25a52c21b
3 changed files with 43 additions and 18 deletions

View File

@ -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<string, Error>(
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());
}

View File

@ -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/\
`;

View File

@ -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<void> {
});
}
export async function exitIfNotLoggedIn(): Promise<void> {
export async function checkLoggedIn(): Promise<void> {
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<void> {
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?',