Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/j3k0/ganomede-errors
Ganomede's extended restify errors
https://github.com/j3k0/ganomede-errors
Last synced: 22 days ago
JSON representation
Ganomede's extended restify errors
- Host: GitHub
- URL: https://github.com/j3k0/ganomede-errors
- Owner: j3k0
- License: apache-2.0
- Created: 2017-04-04T19:48:08.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2017-04-07T13:01:00.000Z (over 7 years ago)
- Last Synced: 2024-10-04T15:38:08.034Z (about 1 month ago)
- Language: JavaScript
- Size: 11.7 KB
- Stars: 0
- Watchers: 4
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# ganomede-errors
Ganomede's extended restify errors
The way to distinguish our app's logic-level errors from others.
(Like `socket hang up` vs `user already exists`.)## Basic Usage
The idea is to create error classes like `UserNotFoundError extends GanomedeError`,
define appropriate `statusCode` and `message` on it with optional params,
and return those from lower-level places.``` js
//
// Database.js
//class Db {
getDocument (id, callback) {
this.redis.get(id, (err, reply) => {
// Propagate "fundamental" errors.
if (err)
return callback(err);// Wrap app-level errors into more meaningful objects.
if (reply === null)
return callback(new Db.DocumentNotFoundError({id}));callback(null, reply);
});
}
}Db.DocumentNotFoundError = class DocumentNotFoundError extends GanomedeError {
constructor (query) {
super('No documents matching `%j`', query);
this.severity = 'info';
this.statusCode = 404;
}
};
```In app-code, make use of more meaningful errors and act accordingly.
``` js
//
// app.js
//app.get('/users/:id', (req, res) => {
db.getDocument(`users:${req.params.id}`, (err, user) => {
if (err instanceof Db.DocumentNotFoundError) {
// This will:
// - call `logger[err.severity]` with approprite message;
// - call `next(toRestError(err))`.
//
// Resulting in HTTP response will have appropriate status code (`err.statusCode`)
// and contain JSON body:
//
// { // `error.name` (default is `error.constructor.name`)
// "restCode": "DocumentNotFoundError",
//
// // `error.statusCode`,
// "statusCode": 404,
//
// // `error.message`
// "message": "No documents matching `{\"id\": \"users:4\"}`"
// }
return sendHttpError(logger, next, err);
}
else if (err) {
// Same as above, except log level is "error"
// and `next` will receive restify.InternalServerError instance
// (which `next` already knows how to upcast to `RestError`).
return sendHttpError(logger, next, new restify.InternalServerError());
}res.json(user);
});
});
```It can also be sometimes useful to have more granular error classes.
``` js
//
// Orm.js
//const findUser = (userId, callback) => {
new Db().getDocument(userId, (err, json) => {
if (err instanceof Db.DocumentNotFoundError) {
// here we now what missing document means
// (and DB knows how to distinguish missing document errors
// from, say, "cannot connect to hostname")
return callback(new UserNotFoundError(userId));
}
else if (err)
return callback(err);callback(null, json);
});
};
```## Included Errors
Some situations are quite common, so error classes for them with
appropriate severity levels, status codes and names are already included.Class Name (as exported) | HTTP Status | Rest Code | Message | Severity
-------------------------|-------------|-----------|---------|---------
`InvalidAuthTokenError` | 401 | `'InvalidAuthTokenError'` | Invalid auth token | `severity.info`
`InvalidCredentialsError` | 401 | `'InvalidCredentialsError'` | Invalid credentials | `severity.info`
`RequestValidationError` | 400 | First argument passed to constructor | Rest of constructor arguments | severity.info``` js
if (!req.params.token)
return sendHttpError(logger, next, new InvalidAuthTokenError());if (req.headers['Authorization'] !== 'Bearer 0xdeadbeef')
return sendHttpError(logger, next, new InvalidCredentialsError());if (typeof req.body.message !== 'string')
return sendHttpError(logger, next, new RequestValidationError(
'BadMessage',
'Message must be a string, got `%s`', typeof req.body.message
));
```