Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: add typescript support #12

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,5 @@ build/Release
# Deployed apps should consider commenting this line out:
# see https://npmjs.org/doc/faq.html#Should-I-check-my-node_modules-folder-into-git
node_modules

dist
123 changes: 69 additions & 54 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ Descriptive errors through metadata
[![](https://img.shields.io/npm/v/erroz.svg)](https://www.npmjs.com/package/erroz)
[![](https://img.shields.io/npm/dm/erroz.svg)](https://www.npmjs.com/package/erroz)

Typical strategies of parsing errors are fragile and couple code to the error messages. By defining error objects consistently, working with errors becomes predictable and efficient.
Typical strategies of parsing errors are fragile and couple code to the error
messages. By defining error objects consistently, working with errors becomes
predictable and efficient.

## Features

Expand All @@ -18,13 +20,13 @@ Typical strategies of parsing errors are fragile and couple code to the error me
## Example

```javascript
var erroz = require("erroz");
import { erroz } from "erroz";

var DuplicateError = erroz({
name: "Duplicate",
code: "duplicate",
statusCode: 409,
template: "Resource %resource (%id) already exists"
const DuplicateError = erroz({
name: "Duplicate",
code: "duplicate",
statusCode: 409,
template: "Resource %resource (%id) already exists",
});

// ...
Expand Down Expand Up @@ -53,17 +55,19 @@ throw new DuplicateError({ resource: "Unicorn", id: 1 });
## Defining errors

```javascript
var errorDefinition = {
name: "NotFound",
template: "%resource (%id) not found"
const errorDefinition = {
name: "NotFound",
template: "%resource (%id) not found",
};

var NotFoundError = erroz(errorDefinition);
const NotFoundError = erroz(errorDefinition);
```

### errorDefinition _object_

Arbitrary data structure for metadata which will be available on every error instance. Some attributes have a special meaning which is why they are described below:
Arbitrary data structure for metadata which will be available on every error
instance. Some attributes have a special meaning which is why they are described
below:

#### `name` _string_

Expand All @@ -75,38 +79,44 @@ A static error message.

#### `template` _string_

A dynamic error message. Variable substitution from [the data object](https://github.com/peerigon/erroz#throwing-with-data-object) is done with `%<variable name>`.
A dynamic error message. Variable substitution from
[the data object](https://github.com/peerigon/erroz#throwing-with-data-object)
is done with `%<variable name>`.

## Throwing (with data object)

```javascript
var data = { resource: "Unicorn", id: 1 };
const data = { resource: "Unicorn", id: 1 };
throw new NotFoundError(data);
// Duplicate: Resource Unicorn (1) already exists
```

### data _object_

A set of data to be used with [the `errorDefinition.template` property](https://github.com/peerigon/erroz#template-string).
A set of data to be used with
[the `errorDefinition.template` property](https://github.com/peerigon/erroz#template-string).

## Throwing (with error message)

```javascript
var overrideMessage = "You are not authorized to eat my cookies";
const overrideMessage = "You are not authorized to eat my cookies";

throw new ForbiddenError(overrideMessage);
// Forbidden: You are not authorized to eat my cookies
```

### overrideMessage _string_

A message to override `errorDefinition.message` or `errorDefinition.template`. Use of this option will set `error.data` to an empty object.
A message to override `errorDefinition.message` or `errorDefinition.template`.
Use of this option will set `error.data` to an empty object.

## JSON

Errors can be converted to JSON with `JSON.stringify()`.
Errors can be converted to JSON with `JSON.stringify()`.

```javascript
const err = new DuplicateError({ resource: "Unicorn", id: 1 });

```javascript
var err = new DuplicateError({ resource: "Unicorn", id: 1 });
console.log(JSON.stringify(err));

/*
Expand All @@ -125,36 +135,40 @@ console.log(JSON.stringify(err));
*/
```

__Custom JSON format__
**Custom JSON format**

The `AbstractError.toJSON` method can be defined to customize the JSON format.
The `options.toJSON` method can be defined to customize the JSON format.

```javascript
import { erroz } from "erroz";

// Set a custom `toJSON` method for all errors
erroz.AbstractError.prototype.toJSON = function() {
return {
name: this.name,
code: this.code
};
erroz.options.toJSON = function () {
return {
name: this.name,
code: this.code,
};
};

console.log(JSON.stringify(err));
const DuplicateError = erroz(errorConfig);

console.log(JSON.stringify(new DuplicateError()));
/*
{
"name": "Duplicate",
"code": "duplicate"
}
*/
```

### `error.toJSend()`

Converts the error to a JSend-style object.
The JSend `status` attribute is derived from the statusCode if not passed explicitly. Valid codes are 4xx and 5xx.
In case of an invalid statusCode, `.toJSend()` will throw an error.
Converts the error to a JSend-style object. The JSend `status` attribute is
derived from the statusCode if not passed explicitly. Valid codes are 4xx and
5xx. In case of an invalid statusCode, `.toJSend()` will throw an error.

```javascript
var err = new DuplicateError({ resource: "Unicorn", id: 1, status: 409 });
const err = new DuplicateError({ resource: "Unicorn", id: 1, status: 409 });

err.toJSend();

Expand All @@ -178,51 +192,52 @@ err.toJSend();

Define a custom error renderer.

```javascript
erroz.options.renderMessage = function(data, template) {
return "Ooops";
}
```javascript
erroz.options.renderMessage = function (data, template) {
return "Ooops";
};
```

### includeStack _boolean_

Whether the stack should be included in errors. Default is true.

```javascript
```javascript
erroz.options.includeStack = false;
```

Consider turning this off in production and sending it to a logger instead.

## Pro Tip: Using erroz with Connect / Express error handlers

Define a global error handler which calls `toJSend()` if the error is an instance of `erroz.AbstractError`.
**why do this?** So you can simply `next` all your errors in your route-handlers.
Define a global error handler which calls `toJSend()` if the error is an
instance of `erroz.AbstractError`. **why do this?** So you can simply `next` all
your errors in your route-handlers.

```javascript
function myAwesomeRoute(req, res, next) {
if (!req.awesome) {
next(new NotAwesomeError());
return;
}
if (!req.awesome) {
next(new NotAwesomeError());
return;
}

next();
}
next();
}
```

```javascript
app.use(function errozHandler(err, req, res, next) {
if (err instanceof erroz.AbstractError) {
res.status(err.statusCode).send(err.toJSend());
return;
}
if (err instanceof erroz.AbstractError) {
res.status(err.statusCode).send(err.toJSend());
return;
}

// Pass on all non-erroz errors
next(err);
// Pass on all non-erroz errors
next(err);
});
```

## Licence
## Licence

MIT

Expand Down
30 changes: 0 additions & 30 deletions examples/customJson.js

This file was deleted.

26 changes: 26 additions & 0 deletions examples/customJson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { erroz } from "../src/main";

erroz.options.toJSON = function () {
return {
name: this.name,
code: this.code,
};
};

const DuplicateError = erroz({
name: "Duplicate",
code: "duplicate",
statusCode: 409,
template: "Resource %resource (%id) already exists",
});

const err = new DuplicateError({ resource: "Unicorn", id: 1 });

console.log(JSON.stringify(err));

/*
{
"name": "Duplicate",
"code": "duplicate"
}
*/
Original file line number Diff line number Diff line change
@@ -1,20 +1,17 @@
'use strict';
import { erroz } from "../src/main";

var erroz = require("../lib/index.js");
erroz.options.renderMessage = (template, data) => {
template = template.replace("%resource", data.resource?.toString() ?? "");
template = template.replace("%id", data.id?.toString() ?? "");

erroz.options.renderMessage = function(template, data) {
template = template.replace("%resource", data.resource);
template = template.replace("%id", data.id);

return "Something went wrong... " + template;
return "Something went wrong... " + template;
};

var NotFoundError = erroz({
name: "NotFound",
code: "not-found",
status: "fail",
statusCode: 404,
template: "%resource (%id) not found"
name: "NotFound",
code: "not-found",
statusCode: 404,
template: "%resource (%id) not found",
});

throw new NotFoundError({ resource: "User", id: 1 });
Expand All @@ -31,4 +28,4 @@ throw new NotFoundError({ resource: "User", id: 1 });
at Function.Module.runMain (module.js:497:10)
at startup (node.js:119:16)
at node.js:902:3
*/
*/
29 changes: 13 additions & 16 deletions examples/httpError.js → examples/httpError.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
"use strict";

var http = require("http"),
erroz = require("../lib/index.js");
import http from "http";
import { erroz } from "../src/main";

var NotFoundError = erroz({
name: "NotFound",
code: "not-found",
status: "fail",
statusCode: 404,
template: "<%= resource %> (<%= id %>) not found"
name: "NotFound",
code: "not-found",
statusCode: 404,
template: "%resource (%id) not found",
});

http.createServer(function (req, res) {

http
.createServer(function (req, res) {
var err = new NotFoundError({ resource: "User", id: 1 });

res.writeHead(err.statusCode, {"Content-Type": "application/json"});
res.writeHead(err.statusCode, { "Content-Type": "application/json" });

res.end(JSON.stringify(err.toJSend()));

//returns jsend-style JSON
/*
{
Expand All @@ -37,7 +35,6 @@ http.createServer(function (req, res) {
}
}
*/


}).listen(1337, "127.0.0.1");
console.log("Server running at http://127.0.0.1:1337/");
})
.listen(1337, "127.0.0.1");
console.log("Server running at http://127.0.0.1:1337/");
Loading