diff --git a/CHANGELOG.md b/CHANGELOG.md index 97a2603a..601c5315 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file automatically by Versionist. DO NOT EDIT THIS FILE MANUALLY! This project adheres to [Semantic Versioning](http://semver.org/). +## v7.3.8 - 2018-05-03 + +* Catch require errors and provide helpful instructions #874 [Tim Perry] +* Inline the entire resin-cli-errors module #874 [Tim Perry] + ## v7.3.7 - 2018-04-30 * Pin node types to v9.0.0 to avoid build errors with transient dependencies #871 [Cameron Diver] diff --git a/lib/errors.ts b/lib/errors.ts index 6e9bf9ec..a8ec40e8 100644 --- a/lib/errors.ts +++ b/lib/errors.ts @@ -14,18 +14,98 @@ See the License for the specific language governing permissions and limitations under the License. */ -import errors = require('resin-cli-errors'); -import patterns = require('./utils/patterns'); -import Raven = require('raven'); -import Promise = require('bluebird'); +import * as _ from 'lodash'; +import * as os from 'os'; +import * as Raven from 'raven'; +import * as Promise from 'bluebird'; +import { stripIndent } from 'common-tags'; + +import * as patterns from './utils/patterns'; const captureException = Promise.promisify( Raven.captureException, { context: Raven }, ); +function hasCode(error: any): error is Error & { code: string } { + return error.code != null; +} + +function treatFailedBindingAsMissingModule(error: any): void { + if (error.message.startsWith('Could not locate the bindings file.')) { + error.code = 'MODULE_NOT_FOUND'; + } +} + +function interpret(error: any): string | undefined { + if (!(error instanceof Error)) { + return; + } + + treatFailedBindingAsMissingModule(error); + + if (hasCode(error)) { + const errorCodeHandler = messages[error.code]; + const message = errorCodeHandler && errorCodeHandler(error); + + if (message) { + return message; + } + + if (!_.isEmpty(error.message)) { + return `${error.code}: ${error.message}`; + } + } else { + return error.message; + } +} + +const messages: { + [key: string]: (error: Error & { path?: string }) => string; +} = { + EISDIR: error => `File is a directory: ${error.path}`, + + ENOENT: error => `No such file or directory: ${error.path}`, + + ENOGIT: () => stripIndent` + Git is not installed on this system. + Head over to http://git-scm.com to install it and run this command again.`, + + EPERM: () => stripIndent` + You don't have enough privileges to run this operation. + ${ + os.platform() === 'win32' + ? 'Run a new Command Prompt as administrator and try running this command again.' + : 'Try running this command again prefixing it with `sudo`.' + } + + If this is not the case, and you're trying to burn an SDCard, check that the write lock is not set.`, + + EACCES: e => messages.EPERM(e), + + ETIMEDOUT: () => + 'Oops something went wrong, please check your connection and try again.', + + MODULE_NOT_FOUND: () => stripIndent` + Part of the CLI could not be loaded. This typically means your CLI install is in a broken state. + ${ + os.arch() === 'x64' + ? 'You can normally fix this by uninstalling and reinstalling the CLI.' + : stripIndent` + You're using an unsupported architecture (${os.arch()}), so this is typically caused by missing native modules. + Reinstalling may help, but pay attention to errors in native module build steps en route. + ` + } + `, + + ResinExpiredToken: () => stripIndent` + Looks like your session token is expired. + Please try logging in again with: + $ resin login`, +}; + exports.handle = function(error: any) { - let message = errors.interpret(error); + let message = interpret(error); if (message == null) { return; } @@ -34,7 +114,7 @@ exports.handle = function(error: any) { message = error.stack; } - patterns.printErrorMessage(message); + patterns.printErrorMessage(message!); return captureException(error) .timeout(1000) diff --git a/package.json b/package.json index bc1f8a96..a24567fb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "resin-cli", - "version": "7.3.7", + "version": "7.3.8", "description": "The official resin.io CLI tool", "main": "./build/actions/index.js", "homepage": "https://github.com/resin-io/resin-cli", @@ -133,7 +133,6 @@ "reconfix": "^0.0.3", "request": "^2.81.0", "resin-bundle-resolve": "^0.5.3", - "resin-cli-errors": "^1.2.0", "resin-cli-form": "^1.4.1", "resin-cli-visuals": "^1.4.0", "resin-compose-parse": "^1.8.1", diff --git a/typings/resin-cli-errors.d.ts b/typings/resin-cli-errors.d.ts deleted file mode 100644 index b62af69f..00000000 --- a/typings/resin-cli-errors.d.ts +++ /dev/null @@ -1 +0,0 @@ -declare module 'resin-cli-errors';