├── .editorconfig ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── SECURITY.md ├── package.json ├── src ├── index.spec.ts └── index.ts ├── tsconfig.json └── tslint.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | root = true 4 | 5 | [*] 6 | indent_size = 2 7 | indent_style = space 8 | end_of_line = lf 9 | charset = utf-8 10 | trim_trailing_whitespace = true 11 | insert_final_newline = true 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | coverage/ 3 | node_modules/ 4 | npm-debug.log 5 | dist/ 6 | typings/ 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | 4 | notifications: 5 | email: 6 | on_success: never 7 | on_failure: change 8 | 9 | node_js: 10 | - "4" 11 | - "stable" 12 | 13 | after_script: "npm install coveralls@2 && cat ./coverage/lcov.info | coveralls" 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Blake Embrey (hello@blakeembrey.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Async Middleware 2 | 3 | [![NPM version][npm-image]][npm-url] 4 | [![NPM downloads][downloads-image]][downloads-url] 5 | [![Build status][travis-image]][travis-url] 6 | [![Test coverage][coveralls-image]][coveralls-url] 7 | [![Greenkeeper badge](https://badges.greenkeeper.io/blakeembrey/async-middleware.svg)](https://greenkeeper.io/) 8 | 9 | > Wrap an asynchronous middleware (or handler) function for Express, Connect, router, etc. 10 | 11 | ## Installation 12 | 13 | ```sh 14 | npm install async-middleware --save 15 | ``` 16 | 17 | ## Usage 18 | 19 | Wrap a middleware function using `async` and/or promises to catch errors and forward them to `next(err)`. 20 | 21 | ```js 22 | var express = require('express') 23 | var wrap = require('async-middleware').wrap 24 | 25 | var app = express() 26 | 27 | app.use(wrap(function (req, res) { 28 | return Promise.reject(new Error('boom!')) 29 | })) 30 | ``` 31 | 32 | ## License 33 | 34 | MIT 35 | 36 | [npm-image]: https://img.shields.io/npm/v/async-middleware.svg?style=flat 37 | [npm-url]: https://npmjs.org/package/async-middleware 38 | [downloads-image]: https://img.shields.io/npm/dm/async-middleware.svg?style=flat 39 | [downloads-url]: https://npmjs.org/package/async-middleware 40 | [travis-image]: https://img.shields.io/travis/blakeembrey/async-middleware.svg?style=flat 41 | [travis-url]: https://travis-ci.org/blakeembrey/async-middleware 42 | [coveralls-image]: https://img.shields.io/coveralls/blakeembrey/async-middleware.svg?style=flat 43 | [coveralls-url]: https://coveralls.io/r/blakeembrey/async-middleware?branch=master 44 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Security contact information 4 | 5 | To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. 6 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "async-middleware", 3 | "version": "1.2.1", 4 | "description": "Wrap an asynchronous middleware (or handler) function for Express, Connect, router, etc.", 5 | "main": "dist/index.js", 6 | "typings": "dist/index.d.ts", 7 | "files": [ 8 | "dist/", 9 | "LICENSE" 10 | ], 11 | "scripts": { 12 | "lint": "tslint \"src/**/*.ts\" --project tsconfig.json --type-check", 13 | "build": "rm -rf dist && tsc", 14 | "test-spec": "blue-tape 'dist/**/*.spec.js' | tap-spec", 15 | "test-cov": "istanbul cover -x '*.spec.js' node_modules/blue-tape/bin/blue-tape.js -- 'dist/**/*.spec.js' | tap-spec", 16 | "test": "npm run build && npm run lint && npm run test-cov", 17 | "prepublish": "npm run build" 18 | }, 19 | "repository": { 20 | "type": "git", 21 | "url": "git://github.com/blakeembrey/async-middleware.git" 22 | }, 23 | "keywords": [ 24 | "middleware", 25 | "express", 26 | "async", 27 | "promise", 28 | "handler" 29 | ], 30 | "author": { 31 | "name": "Blake Embrey", 32 | "email": "hello@blakeembrey.com", 33 | "url": "http://blakeembrey.me" 34 | }, 35 | "license": "MIT", 36 | "bugs": { 37 | "url": "https://github.com/blakeembrey/async-middleware/issues" 38 | }, 39 | "homepage": "https://github.com/blakeembrey/async-middleware", 40 | "devDependencies": { 41 | "@types/blue-tape": "^0.1.31", 42 | "@types/node": "^8.0.4", 43 | "blue-tape": "^1.0.0", 44 | "bluebird": "^3.3.5", 45 | "chai": "^4.0.0", 46 | "istanbul": "^0.4.4", 47 | "tap-spec": "^4.1.1", 48 | "tslint": "^5.4.3", 49 | "tslint-config-standard": "^6.0.1", 50 | "typescript": "^2.4.1" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/index.spec.ts: -------------------------------------------------------------------------------- 1 | import test = require('blue-tape') 2 | import { wrap, NextFunction } from './index' 3 | 4 | test('async middleware', t => { 5 | t.test('middleware', t => { 6 | const m = wrap(function (req: any, res: any) { 7 | return Promise.reject(new Error('test')) 8 | }) 9 | 10 | m({}, {}, function (err) { 11 | t.equal(err!.message, 'test') 12 | t.end() 13 | }) 14 | }) 15 | 16 | t.test('error middleware', t => { 17 | const m = wrap(function (err: Error, req: any, res: any, next: NextFunction) { 18 | t.equal(err.message, 'test') 19 | t.end() 20 | }) 21 | 22 | m(new Error('test'), {}, {}, function () {/* */}) 23 | }) 24 | 25 | t.test('error in error middleware', t => { 26 | const m = wrap(function (err: Error, req: any, res: any, next: NextFunction) { 27 | return Promise.reject(err) 28 | }) 29 | 30 | m(new Error('test'), {}, {}, function (err) { 31 | t.equal(err!.message, 'test') 32 | t.end() 33 | }) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export interface NextFunction { 2 | (err?: Error): void 3 | } 4 | 5 | export interface Handler { 6 | (req: T, res: U, next: NextFunction): any 7 | } 8 | 9 | export interface ErrorHandler { 10 | (err: Error, req: T, res: U, next: NextFunction): any 11 | } 12 | 13 | function handle (result: any, next: NextFunction) { 14 | if (result && typeof result.then === 'function') { 15 | return result.then(undefined, function (err: Error) { 16 | return next(err || new Error('Promise was rejected with a falsy value')) 17 | }) 18 | } 19 | 20 | return result 21 | } 22 | 23 | export function wrap (fn: Handler): Handler 24 | export function wrap (fn: ErrorHandler): ErrorHandler 25 | export function wrap (fn: Handler | ErrorHandler): Handler | ErrorHandler { 26 | if (fn.length === 4) { 27 | return function (err: Error, req: T, res: U, next: NextFunction): any { 28 | return handle((fn as ErrorHandler)(err, req, res, next), next) 29 | } 30 | } 31 | 32 | return function (req: T, res: U, next: NextFunction): any { 33 | return handle((fn as Handler)(req, res, next), next) 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["es2015"], 5 | "outDir": "dist", 6 | "rootDir": "src", 7 | "module": "commonjs", 8 | "declaration": true, 9 | "noImplicitAny": true, 10 | "noImplicitThis": true, 11 | "strictNullChecks": true, 12 | "removeComments": true, 13 | "sourceMap": true, 14 | "inlineSources": true 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint-config-standard" 3 | } 4 | --------------------------------------------------------------------------------