Socket
Socket
Sign inDemoInstall

express-router-api

Package Overview
Dependencies
65
Maintainers
1
Versions
23
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.2.2 to 1.2.3

.vscode/launch.json

8

dist/index.js

@@ -45,2 +45,6 @@ "use strict";

const promiseProps = (obj) => {
const keys = Object.keys(obj);
if (!keys.length) {
return rxjs_1.of(obj);
}
return rxjs_1.forkJoin(Object.keys(obj).map(key => {

@@ -92,3 +96,5 @@ return resolve(obj[key]).pipe(operators_1.map(val => {

};
const isPlainObject = (obj) => (typeof obj === 'object' && !(obj instanceof ApiResponse) && !(obj instanceof ApiError));
const isPlainObject = (obj) => {
return (typeof obj === 'object' && !(obj instanceof ApiResponse) && !(obj instanceof ApiError)) && !(obj instanceof Array);
};
const subscription = rxjs_1.defer(() => resolve(origHandler(req, res, next)))

@@ -95,0 +101,0 @@ .pipe(operators_1.switchMap((obj) => {

3

package.json
{
"name": "express-router-api",
"version": "1.2.2",
"version": "1.2.3",
"description": "Express router that lets you construct your API entirely on promises",

@@ -25,2 +25,3 @@ "main": "dist/index.js",

"request-promise": "^4.2.2",
"tslint": "^5.11.0",
"typescript": "^3.1.3"

@@ -27,0 +28,0 @@ },

@@ -1,5 +0,5 @@

import { Router, Request, Response, NextFunction, RequestParamHandler, RequestHandler, RouterOptions } from 'express';
import { NextFunction, Request, RequestHandler, RequestParamHandler, Response, Router, RouterOptions } from 'express';
import { PathParams, RequestHandlerParams } from 'express-serve-static-core';
import { Observable, isObservable, from, identity, defer, of, throwError, forkJoin } from 'rxjs';
import { switchMap, catchError, map } from 'rxjs/operators';
import { defer, forkJoin, from, identity, isObservable, Observable, of, throwError } from 'rxjs';
import { catchError, map, switchMap } from 'rxjs/operators';

@@ -35,3 +35,3 @@ const isPromise = (val: any): val is Promise<any> => (val && typeof val.then === 'function');

constructor(public apiResult: SimpleApiResult, public code: number = 200) {}
};
}

@@ -49,3 +49,3 @@ type ApiResult = SimpleApiResult | ApiResponse;

internalServerError?: string;
};
}

@@ -62,8 +62,12 @@ function resolve<T>(value: T | Promise<T> | Observable<T>): Observable<T> {

const promiseProps = (obj:{ [key: string]: string; }) => {
return forkJoin(Object.keys(obj).map(key => {
return resolve(obj[key]).pipe(map(val => {
const promiseProps = (obj: { [key: string]: string; }) => {
const keys = Object.keys(obj);
if (!keys.length) {
return of(obj);
}
return forkJoin(Object.keys(obj).map((key) => {
return resolve(obj[key]).pipe(map((val) => {
return { [key]: val };
}));
})).pipe(map(results => Object.assign({}, ...results)));
})).pipe(map((results) => Object.assign({}, ...results)));
};

@@ -76,3 +80,3 @@

if(typeof apiResponse.apiResult === 'undefined') {
if (typeof apiResponse.apiResult === 'undefined') {
return false;

@@ -85,11 +89,9 @@ }

res.status(apiResponse.code);
if(typeof apiResponse.apiResult === 'object') {
if (typeof apiResponse.apiResult === 'object') {
res.json(apiResponse.apiResult);
return true;
}
else if(typeof apiResponse.apiResult === 'string') {
} else if (typeof apiResponse.apiResult === 'string') {
res.send(apiResponse.apiResult);
return true;
}
else {
} else {
res.end();

@@ -100,3 +102,5 @@ return true;

function toMiddleware(this: ExpressApiRouter, origHandler: RequestHandler, options: ApiRouterOptions = {}, callNext: boolean) {
function toMiddleware(this: ExpressApiRouter,
origHandler: RequestHandler,
options: ApiRouterOptions = {}, callNext: boolean) {
const internalServerError = options.internalServerError || {error: 'Internal server error'};

@@ -106,6 +110,6 @@

return defer(() => resolve(this.errorFormatter(err, req, res)))
.pipe(map(formatted => formatted ? new ApiResponse(formatted)
: new ApiResponse(err.message, err.statusCode || 500)
.pipe(map((formatted) => formatted ? new ApiResponse(formatted)
: new ApiResponse(err.message, err.statusCode || 500),
));
}
};

@@ -118,3 +122,3 @@ return (req: Request, res: Response, next: NextFunction) => {

return defer(() => resolve(this.errorFormatter(err, req, res)))
.pipe(map(formatted => new ApiResponse(formatted, 500)));
.pipe(map((formatted) => new ApiResponse(formatted, 500)));
}

@@ -124,3 +128,8 @@ return of(undefined);

const isPlainObject = (obj: ApiResult) => (typeof obj === 'object' && !(obj instanceof ApiResponse) && !(obj instanceof ApiError));
const isPlainObject = (obj: ApiResult) => {
return (typeof obj === 'object' &&
!(obj instanceof ApiResponse) &&
!(obj instanceof ApiError)) &&
!(obj instanceof Array);
};
const subscription = defer(() => resolve(origHandler(req, res, next)))

@@ -132,7 +141,6 @@ .pipe(

this.successFormatter ? formatterOperator : identity,
switchMap(data => {
switchMap((data) => {
if (data instanceof ApiError) {
return processApiError(data, req, res);
}
else if (!(data instanceof ApiResponse)) {
} else if (!(data instanceof ApiResponse)) {
return of(new ApiResponse(data, 200));

@@ -145,8 +153,8 @@ }

res.emit('expressApiRouterError', err);
if(!options.silenceExpressApiRouterError) {
if (!options.silenceExpressApiRouterError) {
// tslint:disable-next-line:no-console
console.error(err.stack);
}
return of(undefined);
}
else if (err instanceof ApiError) {
} else if (err instanceof ApiError) {
return processApiError(err, req, res);

@@ -158,3 +166,3 @@ }

catchError((err: Error) => {
return resolve(formatError(err)).pipe(map(jsonError => {
return resolve(formatError(err)).pipe(map((jsonError) => {
return new ApiResponse(jsonError || internalServerError, 500);

@@ -174,3 +182,3 @@ }));

});
req.on('close', () => subscription.unsubscribe())
req.on('close', () => subscription.unsubscribe());
};

@@ -181,8 +189,8 @@ }

'options' | 'trace' | 'copy' | 'lock' |'mkcol' | 'move' |'purge' |
'propfind' | 'proppatch' | 'unlock' | 'report' | 'mkactivity' |
'propfind' | 'proppatch' | 'unlock' | 'report' | 'mkactivity' |
'checkout' | 'merge' | 'm-search' | 'notify' | 'subscribe' |
'unsubscribe' | 'patch' | 'search' | 'connect';
const methods: MethodName[] = [ 'get', 'post', 'put', 'head', 'delete',
'options', 'trace', 'copy', 'lock','mkcol', 'move','purge',
'propfind', 'proppatch', 'unlock', 'report', 'mkactivity',
'options', 'trace', 'copy', 'lock', 'mkcol', 'move', 'purge',
'propfind', 'proppatch', 'unlock', 'report', 'mkactivity',
'checkout', 'merge', 'm-search', 'notify', 'subscribe',

@@ -192,4 +200,4 @@ 'unsubscribe', 'patch', 'search', 'connect' ];

export interface ExpressApiRouter extends Router {
errorFormatter: ErrorFormatter,
successFormatter: SuccessFormatter,
errorFormatter: ErrorFormatter;
successFormatter: SuccessFormatter;
setErrorFormatter(formatter: ErrorFormatter): void;

@@ -218,7 +226,8 @@ setSuccessFormatter(formatter: SuccessFormatter): void;

methods.forEach((method: MethodName) => {
let oldImplementation = apiRouter[method];
const oldImplementation = apiRouter[method];
// tslint:disable-next-line:only-arrow-functions
apiRouter[method] = function(path: PathParams, ...callbacks: (RequestHandler | RequestHandlerParams)[]) {
callbacks = callbacks.map((origHandler: any, index: number) => {
// return orig handler if it provides a callback
if(origHandler.length >= 3) {
if (origHandler.length >= 3) {
return origHandler;

@@ -225,0 +234,0 @@ }

@@ -6,2 +6,3 @@ 'use strict';

const rp = require('request-promise');
const { Router } = require('express');
const { ExpressApiRouter, ApiError, ApiResponse, ApiErrors } = require('./dist');

@@ -22,18 +23,19 @@ const {expect, assert} = require('chai');

let app, router, server;
function routeTest() {
let args = Array.prototype.slice.call(arguments);
const args = Array.prototype.slice.call(arguments);
router.get.apply(router, ['/foo'].concat(args));
}
function paramTest() {
let args = Array.prototype.slice.call(arguments);
let paramHandler = args.pop();
const args = Array.prototype.slice.call(arguments);
const paramHandler = args.pop();
router.get.apply(router, ['/foo/:param'].concat(args));
router.param('param', paramHandler);
}
function requestTest(data, statusCode, extra) {
return rp(`http://localhost:${port}/foo${extra||''}`).then(data => {
if(data[0] === '[' || data[0] === '{') {
const url = `http://localhost:${port}/foo${extra||''}`;
return rp(url).then(data => {
if (data[0] === '[' || data[0] === '{') {
return JSON.parse(data);

@@ -43,3 +45,3 @@ }

}).catch(err => {
if(err.statusCode != (statusCode || 500)) {
if (err.statusCode != (statusCode || 500)) {
throw new Error(`Status code should equal ${statusCode || 500}, was ${err.statusCode}`);

@@ -50,3 +52,3 @@ }

}
beforeEach(cb => {

@@ -69,6 +71,6 @@ app = express();

});
return requestTest('test');
});
it('should support embedded promise', () => {

@@ -80,3 +82,3 @@ routeTest((req, res) => {

});
return requestTest({

@@ -86,3 +88,3 @@ foo: 'bar'

});
it('should support observables', () => {

@@ -92,3 +94,3 @@ routeTest((req, res) => {

});
return requestTest({

@@ -103,3 +105,3 @@ foo: 'bar'

});
return requestTest({

@@ -116,3 +118,3 @@ foo: 'bar'

});
return requestTest({

@@ -122,3 +124,3 @@ foo: 'bar'

});
it('should support plain object with success formatter', () => {

@@ -128,3 +130,3 @@ router.setSuccessFormatter(result => {

});
routeTest((req, res) => {

@@ -135,3 +137,3 @@ return {

});
return requestTest({test: {

@@ -141,3 +143,3 @@ foo: 'bar'

});
it('should support direct promise', () => {

@@ -149,3 +151,3 @@ routeTest((req, res) => {

});
return requestTest({

@@ -155,3 +157,3 @@ foo: 'bar'

});
it('should support reporting JSON errors', () => {

@@ -161,8 +163,8 @@ routeTest((req, res) => {

});
return requestTest({
error: 'test'
}, 403)
}, 403);
});
it('should support reporting JSON errors from promise', () => {

@@ -174,3 +176,3 @@ routeTest((req, res) => {

});
return requestTest({

@@ -180,3 +182,3 @@ error: 'test'

});
it('should support custom error formatter', () => {

@@ -186,3 +188,3 @@ router.setErrorFormatter(err => {

});
routeTest((req, res) => {

@@ -193,6 +195,6 @@ return Promise.delay(10).then(() => {

});
return requestTest({
data: 'foo'
}, 500)
}, 500)
});

@@ -204,3 +206,3 @@

});
routeTest((req, res) => {

@@ -211,9 +213,9 @@ return Promise.delay(10).then(() => {

});
return requestTest({
data: 'foo'
}, 500)
});
it('should report internal server error when error formatter fails', () => {

@@ -223,3 +225,3 @@ router.setErrorFormatter(err => {

});
routeTest((req, res) => {

@@ -230,3 +232,3 @@ return Promise.delay(10).then(() => {

});
return requestTest({

@@ -236,3 +238,3 @@ error: 'Internal server error'

});
it('should support regular middleware', () => {

@@ -245,3 +247,3 @@ routeTest((req, res, next) => {

});
return requestTest({

@@ -251,3 +253,3 @@ foo: 'abc'

});
it('should support param handler', () => {

@@ -261,3 +263,3 @@ paramTest((req, res) => {

});
return requestTest({

@@ -267,3 +269,3 @@ foo: 'xxx'

});
it('should support reporting JSON errors from promise when thrown from param handler', () => {

@@ -275,3 +277,3 @@ paramTest((req, res) => {}, (req, res, param) => {

});
return requestTest({

@@ -288,3 +290,3 @@ error: 'test'

});
return requestTest({

@@ -301,3 +303,3 @@ customResponse: 'test'

});
return requestTest({

@@ -315,3 +317,3 @@ error: 'test'

});
let timedOut = false;

@@ -324,2 +326,42 @@ await requestTest('', 500).timeout(50).catch(Promise.TimeoutError, () => {

it('should handle arrays from async value', () => {
routeTest((req, res) => {
return Promise.resolve(['aa']);
});
return requestTest(['aa']);
});
it('should handle direct arrays', () => {
routeTest((req, res) => {
return ['aa'];
});
return requestTest(['aa']);
});
it('should handle empty arrays from async function', () => {
routeTest(async (req, res) => {
return [];
});
return requestTest([]);
});
it('should handle empty arrays', () => {
routeTest((req, res) => {
return [];
});
return requestTest([]);
});
it('should handle empty objects from async function', () => {
routeTest(async (req, res) => {
return {};
});
return requestTest({});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc