Comparing version 4.0.11 to 5.0.0
@@ -6,2 +6,27 @@ # Change Log | ||
## [v5.0.0](https://github.com/JS-DevTools/ono/tree/v5.0.0) (2019-02-18) | ||
### Breaking Changes | ||
#### in Node.js | ||
- Ono errors previously included an `inspect()` method to support Node's [`util.inspect()` function](https://nodejs.org/api/util.html#util_util_inspect_object_options). As of Node v6.6.0, the `inspect()` method is deprecated in favor of a [`util.inspect.custom`](https://nodejs.org/api/util.html#util_util_inspect_custom). Ono has updated accordingly, so errors no longer have an `inspect()` method. | ||
#### in Web Browsers | ||
- We no longer automatically include a polyfill for [Node's `util.format()` function](https://nodejs.org/api/util.html#util_util_format_format_args). We recommend using [ES6 template strings](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals) instead. Or you can import [a polyfill](https://github.com/tmpfs/format-util) yourself and assign it to [the `ono.formatter` property](https://jsdevtools.org/ono/#onoformatter). | ||
### New Features | ||
- Completely rewritten in TypeScript. | ||
- Ono is now completely dependency free. | ||
- You can now create your own Ono functions for custom error classes. See [the docs](https://jsdevtools.org/ono/#custom-error-classes) for details. | ||
- Symbol-keyed properties are now supported. If the `originalError` and/or `props` objects has Symbol-keyed properties, they will be copied to the Ono error. | ||
[Full Changelog](https://github.com/JS-DevTools/ono/compare/v4.0.11...v5.0.0) | ||
## [v4.0.0](https://github.com/JS-DevTools/ono/tree/v4.0.0) (2017-07-07) | ||
@@ -18,3 +43,3 @@ | ||
I removed the direct dependency on [Node's `util.format()`](https://nodejs.org/api/util.html#util_util_format_format_args), which was needlessly bloating the browser bundle. Instead, I now import [`format-util`](https://www.npmjs.com/package/format-util), which a much more [lightweight browser implementation](https://github.com/tmpfs/format-util/blob/f88c550ef10c5aaadc15a7ebab595f891bb385e1/format.js). There's no change when running in Node.js, because `format-util` simply [exports `util.format()`](https://github.com/tmpfs/format-util/blob/392628c5d45e558589f2f19ffb9d79d4b5540010/index.js#L1). | ||
We removed the direct dependency on [Node's `util.format()`](https://nodejs.org/api/util.html#util_util_format_format_args), which was needlessly bloating the browser bundle. Instead, I now import [`format-util`](https://www.npmjs.com/package/format-util), which a much more [lightweight browser implementation](https://github.com/tmpfs/format-util/blob/f88c550ef10c5aaadc15a7ebab595f891bb385e1/format.js). There's no change when running in Node.js, because `format-util` simply [exports `util.format()`](https://github.com/tmpfs/format-util/blob/392628c5d45e558589f2f19ffb9d79d4b5540010/index.js#L1). | ||
@@ -21,0 +46,0 @@ [Full Changelog](https://github.com/JS-DevTools/ono/compare/v3.0.0...v3.1.0) |
{ | ||
"name": "ono", | ||
"version": "4.0.11", | ||
"version": "5.0.0", | ||
"description": "Throw better errors.", | ||
@@ -13,3 +13,6 @@ "keywords": [ | ||
"wrap", | ||
"inner" | ||
"inner", | ||
"original", | ||
"stack", | ||
"properties" | ||
], | ||
@@ -20,2 +23,3 @@ "author": { | ||
}, | ||
"license": "MIT", | ||
"homepage": "https://jsdevtools.org/ono", | ||
@@ -26,54 +30,54 @@ "repository": { | ||
}, | ||
"license": "MIT", | ||
"main": "lib/ono.js", | ||
"typings": "lib/ono.d.ts", | ||
"main": "cjs/index.js", | ||
"module": "esm/index.js", | ||
"typings": "esm/index.d.ts", | ||
"browser": { | ||
"./cjs/isomorphic.node.js": "./cjs/isomorphic.browser.js", | ||
"./esm/isomorphic.node.js": "./esm/isomorphic.browser.js" | ||
}, | ||
"files": [ | ||
"dist/ono.js", | ||
"dist/ono.js.map", | ||
"dist/ono.min.js", | ||
"dist/ono.min.js.map", | ||
"lib" | ||
"cjs", | ||
"esm" | ||
], | ||
"scripts": { | ||
"lint": "eslint lib test/fixtures test/specs", | ||
"build": "simplifyify lib/ono.js --outfile dist/ono.js --standalone ono --bundle --debug --minify", | ||
"test": "npm run test:node && npm run test:browser && npm run test:typescript && npm run lint", | ||
"clean": "shx rm -rf .nyc_output coverage cjs esm", | ||
"lint": "npm run lint:typescript && npm run lint:javascript", | ||
"lint:typescript": "tslint -p tsconfig.json", | ||
"lint:javascript": "eslint test ./*.js", | ||
"build": "npm run build:cjs && npm run build:esm", | ||
"build:esm": "tsc", | ||
"build:cjs": "tsc --module commonjs --outDir cjs", | ||
"test": "npm run test:node && npm run test:typescript && npm run test:browser && npm run lint", | ||
"test:node": "mocha", | ||
"test:browser": "karma start --single-run", | ||
"test:typescript": "tsc --noEmit test/specs/typescript-definition.ts", | ||
"test:typescript": "tsc --noEmit test/specs/typescript.spec.ts", | ||
"coverage": "npm run coverage:node && npm run coverage:browser", | ||
"coverage:node": "nyc --reporter=text --reporter=lcov --report-dir coverage/node mocha", | ||
"coverage:browser": "npm run build -- --coverage && npm run test:browser -- --coverage", | ||
"coverage:browser": "npm run test:browser -- --coverage", | ||
"upgrade": "npm-check -u", | ||
"bump": "bump --prompt --grep dist/* --tag --push --all", | ||
"release": "npm run upgrade && npm run build && npm test && npm run bump && npm publish" | ||
"bump": "bump --prompt --tag --push --all", | ||
"release": "npm run upgrade && npm run clean && npm run build && npm test && npm run bump" | ||
}, | ||
"devDependencies": { | ||
"@babel/polyfill": "^7.2.5", | ||
"@types/node": "^11.9.5", | ||
"chai": "^4.2.0", | ||
"coveralls": "^3.0.2", | ||
"eslint": "^5.10.0", | ||
"eslint-config-modular": "^5.0.0", | ||
"karma": "^3.1.3", | ||
"karma-chai": "^0.1.0", | ||
"karma-chrome-launcher": "^2.2.0", | ||
"coveralls": "^3.0.3", | ||
"eslint": "^5.14.1", | ||
"eslint-config-modular": "^7.0.0", | ||
"host-environment": "^1.1.1", | ||
"karma": "^4.0.0", | ||
"karma-cli": "^2.0.0", | ||
"karma-coverage": "^1.1.2", | ||
"karma-edge-launcher": "^0.4.2", | ||
"karma-firefox-launcher": "^1.1.0", | ||
"karma-host-environment": "^1.1.6", | ||
"karma-ie-launcher": "^1.0.0", | ||
"karma-mocha": "^1.3.0", | ||
"karma-safari-launcher": "^1.0.0", | ||
"karma-sauce-launcher": "^1.2.0", | ||
"karma-verbose-reporter": "0.0.6", | ||
"mocha": "^5.2.0", | ||
"karma-config": "^1.5.1", | ||
"mocha": "^6.0.1", | ||
"npm-check": "^5.9.0", | ||
"nyc": "^13.1.0", | ||
"simplifyify": "^7.0.0", | ||
"typescript": "^3.2.2", | ||
"shx": "^0.3.2", | ||
"tslint": "^5.13.0", | ||
"tslint-modular": "^1.1.8", | ||
"typescript": "^3.3.3333", | ||
"typescript-tslint-plugin": "^0.3.0", | ||
"version-bump-prompt": "^4.2.1" | ||
}, | ||
"dependencies": { | ||
"format-util": "^1.0.3" | ||
} | ||
"dependencies": {} | ||
} |
221
README.md
ono (Oh No!) | ||
============================ | ||
#### Throw better errors. | ||
### Throw better errors. | ||
@@ -12,13 +12,22 @@ [![Build Status](https://api.travis-ci.com/JS-DevTools/ono.svg?branch=master)](https://travis-ci.com/JS-DevTools/ono) | ||
[![OS and Browser Compatibility](https://jsdevtools.org/img/ci-badges-with-ie.svg)](https://travis-ci.com/JS-DevTools/ono) | ||
[![OS and Browser Compatibility](https://jsdevtools.org/img/badges/ci-badges-with-ie.svg)](https://travis-ci.com/JS-DevTools/ono) | ||
Features | ||
-------------------------- | ||
* Formatted error messages, using Node's [`util.format()`](https://nodejs.org/api/util.html#util_util_format_format_args) or your own custom formatter | ||
* Wrap and re-throw an error _without_ losing the original error's message, stack trace, and properties | ||
* Add custom properties to your errors — great for error codes, support numbers, help URLs, etc. | ||
* Errors can be serialized as JSON, including all native and custom properties | ||
* [Tested](https://jsdevtools.org/ono/test/) on Node.js and all modern web browsers on Mac, Windows, Linux, iOS, and Android | ||
- Wrap and re-throw an error _without_ losing the original error's message, stack trace, and properties | ||
- Add custom properties to errors — great for error numbers, status codes, etc. | ||
- Use [format strings](#onoformatter) for error messages — great for localization | ||
- Enhanced support for [`JSON.stringify()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify) and [`util.inspect()`](https://nodejs.org/api/util.html#util_util_inspect_object_options) — great for logging | ||
- Create Ono instances for your own [custom error classes](#custom-error-classes) | ||
- [Tested](https://travis-ci.com/JS-DevTools/ono) on Node.js and all modern web browsers on Mac, Windows, and Linux. | ||
Example | ||
@@ -28,25 +37,37 @@ -------------------------- | ||
```javascript | ||
// Throw an error with formatted message | ||
throw ono("%s is invalid. Must be at least %d characters.", username, minLength); | ||
const ono = require("ono"); | ||
// Wrap and re-throw an error without losing the original error's message and stack | ||
throw ono(err, "An error occurred while saving your changes"); | ||
// Throw an error with custom properties | ||
throw ono({ code: "NOT_FOUND", status: 404 }, `Resource not found: ${url}`); | ||
// Throw an error with custom properties (even a custom method!) | ||
throw ono({code: 413, status: "Invalid data", retry: function() {...}}); | ||
// Wrap an error without losing the original error's stack and props | ||
throw ono(originalError, "An error occurred while saving your changes"); | ||
// Add custom properties to an existing Error | ||
throw ono(err, {code: 413, status: "Invalid data", retry: function() {...}}) | ||
// Wrap an error and add custom properties | ||
throw ono(originalError, { code: 404, status: "NOT_FOUND" }); | ||
// Any of the above can throw a specific Error subtype instead | ||
throw ono.range(...); // RangeError | ||
throw ono.syntax(...); // SyntaxError | ||
throw ono.reference(...); // ReferenceError | ||
// Wrap an error, add custom properties, and change the error message | ||
throw ono(originalError, { code: 404, status: "NOT_FOUND" }, `Resource not found: ${url}`); | ||
// Throw a specific Error subtype instead | ||
// (works with any of the above signatures) | ||
throw ono.range(...); // RangeError | ||
throw ono.syntax(...); // SyntaxError | ||
throw ono.reference(...); // ReferenceError | ||
// Create an Ono instance for your own custom error class | ||
const { Ono } = require("ono"); | ||
class MyErrorClass extends Error {} | ||
ono.myError = new Ono(MyErrorClass); | ||
// And use it just like any other Ono method | ||
throw ono.myError(...); // MyErrorClass | ||
``` | ||
Installation | ||
-------------------------- | ||
#### Node | ||
Install using [npm](https://docs.npmjs.com/getting-started/what-is-npm): | ||
Install using [npm](https://docs.npmjs.com/about-npm/): | ||
@@ -57,62 +78,149 @@ ```bash | ||
Then require it in your code: | ||
Usage | ||
-------------------------- | ||
When using Ono in Node.js apps, you'll probably want to use **CommonJS** syntax: | ||
```javascript | ||
var ono = require("ono"); | ||
const host = require("ono"); | ||
``` | ||
#### Web Browsers | ||
Reference [`ono.js`](dist/ono.js) or [`ono.min.js`](dist/ono.min.js) in your HTML: | ||
When using a transpiler such as [Babel](https://babeljs.io/) or [TypeScript](https://www.typescriptlang.org/), or a bundler such as [Webpack](https://webpack.js.org/) or [Rollup](https://rollupjs.org/), you can use **ECMAScript modules** syntax instead: | ||
```html | ||
<script src="https://cdn.rawgit.com/JS-DevTools/ono/master/dist/ono.js"></script> | ||
<script> | ||
var timestamp = new Date().toISOString(); | ||
throw ono('This error was thrown at %s', timestamp); | ||
</script> | ||
```javascript | ||
import host from "ono"; | ||
``` | ||
Browser support | ||
-------------------------- | ||
Ono supports recent versions of every major web browser. Older browsers may require [Babel](https://babeljs.io/) and/or [polyfills](https://babeljs.io/docs/en/next/babel-polyfill). | ||
To use Ono in a browser, you'll need to use a bundling tool such as [Webpack](https://webpack.js.org/), [Rollup](https://rollupjs.org/), [Parcel](https://parceljs.org/), or [Browserify](http://browserify.org/). Some bundlers may require a bit of configuration, such as setting `browser: true` in [rollup-plugin-resolve](https://github.com/rollup/rollup-plugin-node-resolve). | ||
API | ||
-------------------------- | ||
### `ono([err], [props], [message, ...])` | ||
### `ono([originalError], [props], [message, ...])` | ||
Creates an [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) object with the given properties. | ||
* `err` - _(optional)_ An existing error object. This error's message, stack trace, and properties will be appended to the new error. | ||
* `originalError` - _(optional)_ The original error that occurred, if any. This error's message, stack trace, and properties will be copied to the new error. | ||
* `props` - _(optional)_ An object whose properties will be added to the new error. Properties can be anything, including objects and functions. | ||
* `props` - _(optional)_ An object whose properties will be copied to the new error. Properties can be anything, including objects and functions. | ||
* `message` - _(optional)_ The error message string. If it contains placeholders, then pass each placeholder's value as an additional parameter. See [`ono.formatter`](#onoformatter) for more info. | ||
##### Specific error types | ||
#### Specific error types | ||
The default `ono()` function always creates [`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) objects, but you can use any of the following methods to explicitly create the corresponding Error subclass. The method signatures are exactly the same as above. | ||
Method | Error type | ||
:-----------------|:------------------- | ||
`ono.error()` |[`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) (this is just an alternate syntax) | ||
`ono.eval()` |[`EvalError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError) | ||
`ono.range()` |[`RangeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError) | ||
`ono.reference()` |[`ReferenceError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError) | ||
`ono.syntax()` |[`SyntaxError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError) | ||
`ono.type()` |[`TypeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError) | ||
`ono.uri()` |[`URIError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError) | ||
|Method | Return Type | ||
|:-----------------|:------------------- | ||
|`ono.error()` |[`Error`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error) | ||
|`ono.eval()` |[`EvalError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError) | ||
|`ono.range()` |[`RangeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError) | ||
|`ono.reference()` |[`ReferenceError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError) | ||
|`ono.syntax()` |[`SyntaxError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError) | ||
|`ono.type()` |[`TypeError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError) | ||
|`ono.uri()` |[`URIError`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError) | ||
### `ono.formatter` | ||
By default, Node's [`util.format()`](https://nodejs.org/api/util.html#util_util_format_format) function is used (even in browsers) to format error messages and substitute placeholders with their corresponding values. You can set `ono.formatter` to a [third-party formatter](https://www.npmjs.com/package/format) or even your own custom implementation, like this: | ||
When running in Node.js, the `ono.formatter` property is set to [the `util.format()` function](https://nodejs.org/api/util.html#util_util_format_format_args), which let you use placeholders such as `%s`, `%d`, and `%j`. You can provide the values for these when calling `ono` or any Ono method: | ||
```javascript | ||
ono.formatter = function(message) { | ||
var params = Array.prototype.slice.call(arguments, 1); | ||
return params.reduce(function(message, param, index) { | ||
return message.replace("$" + index, param); | ||
}, message); | ||
throw ono("%s is invalid. Must be at least %d characters.", username, minLength); | ||
``` | ||
This is especially useful for localization. Here's a simplistic example: | ||
```javascript | ||
const errorMessages { | ||
invalidLength: { | ||
en: "%s is invalid. Must be at least %d characters.", | ||
es: "%s no es válido. Debe tener al menos %d caracteres.", | ||
zh: "%s 无效。 必须至少%d个字符。", | ||
} | ||
} | ||
throw ono("$0 must be greater than $1", 4, 10); | ||
let lang = getCurrentUsersLanguage(); | ||
throw ono(errorMessages.invalidLength[lang], username, minLength); | ||
``` | ||
#### `ono.formatter` in web browsers | ||
Web browsers don't have a built-in equivalent of Node's [`util.format()` function](https://nodejs.org/api/util.html#util_util_format_format_args), so format strings are only supported in Node.js by default. However, you can set the `ono.formatter` property to any compatible polyfill library to enable this functionality in web browsers too. | ||
Here are some compatible polyfill libraries: | ||
- [format](https://www.npmjs.com/package/format) | ||
- [format-util](https://github.com/tmpfs/format-util) | ||
#### Custom `ono.formatter` implementation | ||
If the standard [`util.format()`](https://nodejs.org/api/util.html#util_util_format_format_args) functionality isn't sufficient for your needs, then you can set the `ono.formatter` property to your own custom implementation. Here's a simplistic example: | ||
```javascript | ||
// This is a simple formatter that replaces $0, $1, $2, ... with the corresponding argument | ||
function myCustomFormatter(message, ...args) { | ||
for (let [index, arg] of args) { | ||
message = message.replace("$" + index, arg); | ||
} | ||
return message; | ||
} | ||
// Tell Ono to use your custom formatter | ||
ono.formatter = myCustomFormatter; | ||
// Now all Ono functions support your custom formatter | ||
throw ono("$0 is invalid. Must be at least $1 characters.", username, minLength); | ||
``` | ||
Custom Error Classes | ||
-------------------------- | ||
Ono has built-in support for all of [the built-in JavaScript Error types](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error#Error_types). For example, you can use `ono.reference()` to create a `ReferenceError`, or `ono.syntax()` to create a `SyntaxError`. In addition to the built-in types, you can also create Ono instances for your own custom error classes. | ||
```javascript | ||
const { ono, Ono } = require("ono"); | ||
let counter = 0; | ||
// A custom Error class that assigns a unique ID and timestamp to each error | ||
class MyErrorClass extends Error { | ||
constructor(message) { | ||
super(message); | ||
this.id = ++counter; | ||
this.timestamp = new Date(); | ||
} | ||
} | ||
// Create a new Ono method for your custom Error class | ||
ono.myError = new Ono(MyErrorClass); | ||
// You can use this method just like any other Ono method | ||
throw ono.myError({ code: 404, status: "NOT_FOUND" }, `Resource not found: ${url}`); | ||
``` | ||
The code above throws an instance of `MyErrorClass` that looks like this: | ||
```javascript | ||
{ | ||
"name": "MyErrorClass", | ||
"message": "Resource not found: xyz.html", | ||
"id": 1, | ||
"timestamp": "2019-01-01T12:30:00.456Z", | ||
"code": 404, | ||
"status": "NOT_FOUND", | ||
"stack": "MyErrorClass: Resource not found: xyz.html\n at someFunction (index.js:24:5)", | ||
} | ||
``` | ||
Contributing | ||
-------------------------- | ||
I welcome any contributions, enhancements, and bug-fixes. [File an issue](https://github.com/JS-DevTools/ono/issues) on GitHub and [submit a pull request](https://github.com/JS-DevTools/ono/pulls). | ||
Contributions, enhancements, and bug-fixes are welcome! [File an issue](https://github.com/JS-DevTools/ono/issues) on GitHub and [submit a pull request](https://github.com/JS-DevTools/ono/pulls). | ||
@@ -135,4 +243,15 @@ #### Building/Testing | ||
License | ||
-------------------------- | ||
Ono is 100% free and open-source, under the [MIT license](LICENSE). Use it however you want. | ||
Big Thanks To | ||
-------------------------- | ||
Thanks to these awesome companies for their support of Open Source developers ❤ | ||
[![Travis CI](https://jsdevtools.org/img/badges/travis-ci.svg)](https://travis-ci.com) | ||
[![SauceLabs](https://jsdevtools.org/img/badges/sauce-labs.svg)](https://saucelabs.com) | ||
[![Coveralls](https://jsdevtools.org/img/badges/coveralls.svg)](https://coveralls.io) |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
78289
0
19
52
1136
0
254
0
2
- Removedformat-util@^1.0.3
- Removedformat-util@1.0.5(transitive)