Skip to content

Commit

Permalink
Support generators 🎉
Browse files Browse the repository at this point in the history
  • Loading branch information
vladimyr committed Nov 20, 2019
1 parent 9fa7814 commit 6defec0
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 50 deletions.
4 changes: 3 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ module.exports = {
strict: ['error', 'safe'],
'no-underscore-dangle': 'off',
'no-param-reassign': 'off',
'no-unused-vars': ['error', { 'argsIgnorePattern': 'next|res|req|err' }]
'no-unused-vars': ['error', { 'argsIgnorePattern': 'next|res|req|err' }],
'func-names': ['error', 'always', { generators: 'never' }],
'require-yield': 'off'
}
};
6 changes: 6 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
'use strict';

const { IncomingMessage, ServerResponse } = require('http');
const co = require('co');
const Layer = require('express/lib/router/layer');
const { Router } = require('express');

// eslint-disable-next-line func-names, no-empty-function
const GeneratorFunction = (function* () {}).constructor;

const isError = (arg) => arg instanceof Error;
const isGeneratorFunction = (arg) => arg instanceof GeneratorFunction;
const isRequest = (arg) => arg instanceof IncomingMessage;
const isResponse = (arg) => arg instanceof ServerResponse;
const noop = () => {};
Expand All @@ -18,6 +23,7 @@ function copyProps(source, dest) {

function wrap(fn) {
const newFn = function newFn(...args) {
if (isGeneratorFunction(fn)) fn = co.wrap(fn);
const ret = fn.apply(this, args);
const predicates = [isError, isRequest, isResponse];
const next = args.find((arg) => predicates.every((match) => !match(arg))) || noop;
Expand Down
3 changes: 3 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,5 +48,8 @@
},
"peerDependencies": {
"express": "^4.16.2"
},
"dependencies": {
"co": "^4.6.0"
}
}
178 changes: 129 additions & 49 deletions test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,80 +10,160 @@ const assert = require('assert');
const last = (arr) => arr[arr.length - 1];

describe('express-async-errors', () => {
it('should propagate route handler errors to error handler', () => {
const app = express();
describe('supports async', () => {
it('should propagate route handler errors to error handler', () => {
const app = express();

app.get('/test', async () => {
throw new Error('error');
});
app.get('/test', async () => {
throw new Error('error');
});

app.use((err, req, res, next) => {
res.status(495).end();
app.use((err, req, res, next) => {
res.status(495).end();
});

return supertest(app)
.get('/test')
.expect(495);
});

return supertest(app)
.get('/test')
.expect(495);
});
it('should propagate middleware errors to error handler', () => {
const app = express();

it('should propagate middleware errors to error handler', () => {
const app = express();
app.use(async () => {
throw new Error('error');
});

app.use(async () => {
throw new Error('error');
});
app.get('/test', async () => {
throw new Error('error');
});

app.get('/test', async () => {
throw new Error('error');
});
app.use((err, req, res, next) => {
res.status(495).end();
});

app.use((err, req, res, next) => {
res.status(495).end();
return supertest(app)
.get('/test')
.expect(495);
});

return supertest(app)
.get('/test')
.expect(495);
});
it('should propagate error middleware errors to error handler', () => {
const app = express();

it('should propagate error middleware errors to error handler', () => {
const app = express();
app.get('/test', async () => {
throw new Error('error');
});

app.get('/test', async () => {
throw new Error('error');
});
app.use(async (err, req, res, next) => {
throw new Error('error');
});

app.use(async (err, req, res, next) => {
throw new Error('error');
});
app.use((err, req, res, next) => {
res.status(495).end();
});

app.use((err, req, res, next) => {
res.status(495).end();
return supertest(app)
.get('/test')
.expect(495);
});

return supertest(app)
.get('/test')
.expect(495);
it('should propagate param middleware errors to error handler', () => {
const app = express();

app.param('id', async () => {
throw new Error('error');
});

app.get('/test/:id', async (err, req, next, id) => {
throw new Error(`error ${id}`);
});

app.use((err, req, res, next) => {
res.status(495).end();
});

return supertest(app)
.get('/test/12')
.expect(495);
});
});

it('should propagate param middleware errors to error handler', () => {
const app = express();
describe('supports generators', () => {
it('should propagate route handler errors to error handler', () => {
const app = express();

app.get('/test', function* () {
throw new Error('error');
});

app.param('id', async () => {
throw new Error('error');
app.use((err, req, res, next) => {
res.status(495).end();
});

return supertest(app)
.get('/test')
.expect(495);
});

app.get('/test/:id', async (err, req, next, id) => {
throw new Error(`error ${id}`);
it('should propagate middleware errors to error handler', () => {
const app = express();

app.use(function* () {
throw new Error('error');
});

app.get('/test', function* () {
throw new Error('error');
});

app.use((err, req, res, next) => {
res.status(495).end();
});

return supertest(app)
.get('/test')
.expect(495);
});

app.use((err, req, res, next) => {
res.status(495).end();
it('should propagate error middleware errors to error handler', () => {
const app = express();

app.get('/test', function* () {
throw new Error('error');
});

app.use(async (err, req, res, next) => {
throw new Error('error');
});

app.use((err, req, res, next) => {
res.status(495).end();
});

return supertest(app)
.get('/test')
.expect(495);
});

return supertest(app)
.get('/test/12')
.expect(495);
it('should propagate param middleware errors to error handler', () => {
const app = express();

app.param('id', function* () {
throw new Error('error');
});

app.get('/test/:id', function* (err, req, next, id) {
throw new Error(`error ${id}`);
});

app.use((err, req, res, next) => {
res.status(495).end();
});

return supertest(app)
.get('/test/12')
.expect(495);
});
});

it('should preserve the router stack for external routes', () => {
Expand Down
5 changes: 5 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@ cliui@^5.0.0:
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"

co@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=

color-convert@^1.9.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.0.tgz#1accf97dd739b983bf994d56fec8f95853641b7a"
Expand Down

0 comments on commit 6defec0

Please sign in to comment.