Add isError & ExtError (#16)

* Add isError & ExtError

* Check fixes

* Check fixes
This commit is contained in:
Jaco Greeff
2017-11-24 20:49:25 +01:00
committed by GitHub
parent 23dcf026cc
commit b4c67178a1
13 changed files with 291 additions and 8 deletions
+1
View File
@@ -4,6 +4,7 @@ Utility methods for this package are split into groups
- [bn](bn.md) Utility methods to convert to and from `BN` objects
- [buffer](buffer.md) Utility methods to convert to and from `Buffer` objects
- [ext](ext.md) Extensions to basic classes
- [hex](hex.md) Internal utilities to create and test for hex values
- [is](is.md) Type checking utilities
- [jsonrpc](jsonrpc.md) Convenience functions for values from @polkadot/jsonrpc
+22
View File
@@ -0,0 +1,22 @@
# ext
Extensions to basic classes
- [ExtError](#exterror) Extension to the basic JS Error.
## ExtError
Extension to the basic JS Error.
```js
ExtError (message: string = '', code: number = UNKNOWN_ERROR, value: any)
```
The built-in JavaScript Error class is extended by adding a code to allow for Error categorization. In addition to the normal `stack`, `message`, the numeric `code` and `data` (any types) parameters are available on the object.
```js
const { ExtError } = require('@polkadot/util');
throw new ExtError('some message', ExtError.CODES.METHOD_NOT_FOUND); // => error.code = -32601
```
+18
View File
@@ -4,6 +4,7 @@ Type checking utilities
- [isBN](#isbn) Tests for a `BN` object instance.
- [isBuffer](#isbuffer) Tests for a `Buffer` object instance.
- [isError](#iserror) Tests for a `Error` object instance.
- [isFunction](#isfunction) Tests for a `function`.
- [isHex](#ishex) Tests for a hex string.
- [isInstanceOf](#isinstanceof) Tests for a instance of a class.
@@ -46,6 +47,23 @@ import { isBuffer } from '@polkadot/util';
console.log('isBuffer', isBuffer(Buffer.from([]))); // => true
```
## isError
Tests for a `Error` object instance.
```js
isError (value: any): boolean
```
Checks to see if the input object is an instance of `Error`.
```js
import { isError } from '@polkadot/util';
console.log('isError', isError(new Error('message'))); // => true
```
## isFunction
Tests for a `function`.
+56
View File
@@ -0,0 +1,56 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
import type { ExtErrorInterface } from '../types';
const isFunction = require('../is/function');
const UNKNOWN = -99999;
/**
@name ExtError
@signature ExtError (message: string = '', code: number = UNKNOWN_ERROR, value: any)
@summary Extension to the basic JS Error.
@description
The built-in JavaScript Error class is extended by adding a code to allow for Error categorization. In addition to the normal `stack`, `message`, the numeric `code` and `data` (any types) parameters are available on the object.
@example
const { ExtError } = require('@polkadot/util');
throw new ExtError('some message', ExtError.CODES.METHOD_NOT_FOUND); // => error.code = -32601
*/
module.exports = class ExtError extends Error implements ExtErrorInterface {
code: number;
data: any;
message: string;
name: string;
stack: string;
constructor (message: string = '', code: number = UNKNOWN, data: any) {
super();
const extend = (name: string, value: any): void => {
Object.defineProperty(this, name, {
configurable: true,
enumerable: false,
value
});
};
extend('message', String(message));
extend('name', this.constructor.name);
extend('data', data);
extend('code', code);
if (isFunction(Error.captureStackTrace)) {
Error.captureStackTrace(this, this.constructor);
} else {
extend('stack', (new Error(message)).stack);
}
}
static CODES = {
UNKNOWN,
INVALID_JSONRPC: -99998,
METHOD_NOT_FOUND: -32601 // Rust client
};
};
+97
View File
@@ -0,0 +1,97 @@
// ISC, Copyright 2017 Jaco Greeff
const ExtError = require('./error');
const isError = require('../is/error');
describe('Error', () => {
describe('constructor', () => {
it('constructs an Error that is still an Error', () => {
expect(
isError(
new ExtError()
)
).toEqual(true);
});
});
describe('static', () => {
it('exposes the .CODES as a static', () => {
expect(
Object.keys(ExtError.CODES)
).not.toEqual(0);
});
});
describe('constructor properties', () => {
it('sets the .message property', () => {
expect(
new ExtError('test message').message
).toEqual('test message');
});
it("sets the .message to '' when not set", () => {
expect(
new ExtError().message
).toEqual('');
});
it('sets the .code property', () => {
expect(
new ExtError('test message', 1234).code
).toEqual(1234);
});
it('sets the .code to UKNOWN when not set', () => {
expect(
new ExtError('test message').code
).toEqual(ExtError.CODES.UNKNOWN);
});
it('sets the .data property', () => {
const data = { some: { value: 'here' } };
expect(
new ExtError('test message', 1234, data).data
).toEqual(data);
});
});
describe('stack traces', () => {
let captureStackTrace;
beforeEach(() => {
captureStackTrace = Error.captureStackTrace;
Error.captureStackTrace = function (error) {
Object.defineProperty(error, 'stack', {
configurable: true,
get: function getStack () {
const value = 'some stack returned';
Object.defineProperty(this, 'stack', { value });
return value;
}
});
};
});
afterEach(() => {
Error.captureStackTrace = captureStackTrace;
});
it('captures via captureStackTrace when available', () => {
expect(
new ExtError().stack
).toEqual('some stack returned');
});
it('captures via stack when captureStackTrace not available', () => {
Error.captureStackTrace = null;
expect(
new ExtError().stack.length
).not.toEqual(0);
});
});
});
+11
View File
@@ -0,0 +1,11 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
const ExtError = require('./error');
/**
@summary Extensions to basic classes
*/
module.exports = {
ExtError
};
+2 -1
View File
@@ -3,6 +3,7 @@
const bn = require('./bn');
const buffer = require('./buffer');
const ext = require('./ext');
const hex = require('./hex');
const is = require('./is');
const jsonrpc = require('./jsonrpc');
@@ -13,5 +14,5 @@ const logger = require('./logger');
@summary Utility methods for this package are split into groups
*/
module.exports = Object.assign(
{}, bn, buffer, hex, is, jsonrpc, keccak, logger
{}, bn, buffer, ext, hex, is, jsonrpc, keccak, logger
);
+19
View File
@@ -0,0 +1,19 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
const isInstanceOf = require('./instanceOf');
/**
@name isError
@signature isError (value: any): boolean
@summary Tests for a `Error` object instance.
@description
Checks to see if the input object is an instance of `Error`.
@example
import { isError } from '@polkadot/util';
console.log('isError', isError(new Error('message'))); // => true
*/
module.exports = function isError (value: any): boolean {
return isInstanceOf(value, Error);
};
+4
View File
@@ -2,6 +2,8 @@
// @flow
const isBN = require('./bn');
const isBuffer = require('./buffer');
const isError = require('./error');
const isFunction = require('./function');
const isHex = require('./hex');
const isInstanceOf = require('./instanceOf');
@@ -14,6 +16,8 @@ const isUndefined = require('./undefined');
*/
module.exports = {
isBN,
isBuffer,
isError,
isFunction,
isHex,
isInstanceOf,
+29 -1
View File
@@ -4,7 +4,7 @@
const BN = require('bn.js');
const { isBN, isFunction, isHex, isInstanceOf, isNumber, isString, isUndefined } = require('./index');
const { isBN, isBuffer, isError, isFunction, isHex, isInstanceOf, isNumber, isString, isUndefined } = require('./index');
describe('is', () => {
describe('isBN', () => {
@@ -21,6 +21,34 @@ describe('is', () => {
});
});
describe('isBuffer', () => {
it('returns true when a Buffer value', () => {
expect(
isBuffer(Buffer.from([]))
).toEqual(true);
});
it('returns false on non-Buffer values', () => {
expect(
isBuffer(0)
).toEqual(false);
});
});
describe('isError', () => {
it('returns true when an Error value', () => {
expect(
isError(new Error('testing'))
).toEqual(true);
});
it('returns false on non-Error values', () => {
expect(
isError(0)
).toEqual(false);
});
});
describe('isFunction', () => {
it('returns true on valid functions', () => {
expect(
+14 -2
View File
@@ -10,11 +10,23 @@ describe('jsonrpc', () => {
'test_method',
[
{ name: 'b', type: 'A' },
{ name: 'a', type: 'B' }
{ name: 'a', type: 'B' },
{ type: 'C' },
{ type: 'D' }
],
{ type: 'A' }
)
).toEqual('test_method (b: A, a: B): A');
).toEqual('test_method (b: A, a: B, C, D): A');
});
it('empty inputs format correctly', () => {
expect(
jsonrpcSignature(
'test_method',
[],
{ type: 'A' }
)
).toEqual('test_method (): A');
});
});
});
+9 -4
View File
@@ -3,6 +3,12 @@
import type { InterfaceInputType, InterfaceOutputType } from '@polkadot/jsonrpc/types';
function formatParam (param: InterfaceInputType | InterfaceOutputType): string {
return param.name
? `${((param.name: any): string)}: ${param.type}`
: param.type;
}
/**
@name jsonrpcSignature
@signature jsonrpcSignature (name: string, _inputs: Array<InterfaceInputType>, _output: InterfaceOutputType): string
@@ -17,9 +23,8 @@ import type { InterfaceInputType, InterfaceOutputType } from '@polkadot/jsonrpc/
)); // => test_method (destination: Address): Address
*/
module.exports = function jsonrpcSignature (name: string, _inputs: Array<InterfaceInputType>, _output: InterfaceOutputType): string {
const inputParams: string = _inputs
.map(({ name, type }) => `${name}: ${type}`)
.join(', ');
const inputs: string = _inputs.map(formatParam).join(', ');
const output: string = formatParam(_output);
return `${name} (${inputParams}): ${_output.type}`;
return `${name} (${inputs}): ${output}`;
};
+9
View File
@@ -0,0 +1,9 @@
// ISC, Copyright 2017 Jaco Greeff
// @flow
export interface ExtErrorInterface {
code: number;
data: any;
message: string;
stack: string;
}