You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
125 lines
3.2 KiB
125 lines
3.2 KiB
"use strict";
|
|
var Router = require("express").Router;
|
|
var flattenDeep = require("lodash.flattendeep");
|
|
var isPromise = require("is-promise");
|
|
|
|
var wrapHandler = function (handler) {
|
|
if ("function" !== typeof handler) {
|
|
var type = Object.prototype.toString.call(handler);
|
|
var msg = "Expected a callback function but got a " + type;
|
|
throw new Error(msg);
|
|
}
|
|
|
|
var handleReturn = function (args) {
|
|
// Find the next function from the arguments
|
|
var next = args.slice(-1)[0];
|
|
|
|
// When calling router.param, the last parameter is a string, not next.
|
|
// If so, the next should be the one before it.
|
|
if ("string" === typeof next) {
|
|
next = args.slice(-2)[0];
|
|
}
|
|
|
|
// Call the route
|
|
var ret = handler.apply(null, args);
|
|
|
|
// If it doesn't return a promise, we exit.
|
|
if (!isPromise(ret)) {
|
|
return;
|
|
}
|
|
|
|
// Since we got a promise, we handle calling next
|
|
Promise.resolve(ret).then(
|
|
function (d) {
|
|
if (d === "next") {
|
|
next();
|
|
} else if (d === "route") {
|
|
next("route");
|
|
}
|
|
},
|
|
function (err) {
|
|
if (!err) {
|
|
err = new Error(
|
|
"returned promise was rejected but did not have a reason",
|
|
);
|
|
}
|
|
next(err);
|
|
},
|
|
);
|
|
};
|
|
|
|
if (handler.length === 4) {
|
|
// Preserve the original handler function name. See #146.
|
|
const wrapperObj = {
|
|
[handler.name]: function (err, req, res, next) {
|
|
handleReturn([err, req, res, next]);
|
|
},
|
|
};
|
|
return wrapperObj[handler.name];
|
|
}
|
|
|
|
// Preserve the original handler function name. See #146.
|
|
const wrapperObj = {
|
|
[handler.name]: function (req, res, next) {
|
|
handleReturn([req, res, next]);
|
|
},
|
|
};
|
|
return wrapperObj[handler.name];
|
|
};
|
|
|
|
var wrapMethods = function (instanceToWrap, isRoute) {
|
|
var toConcat = isRoute ? ["all"] : ["use", "all", "param"];
|
|
|
|
var methods = require("methods").concat(toConcat);
|
|
|
|
methods.forEach(function (method) {
|
|
var original = "__" + method;
|
|
instanceToWrap[original] = instanceToWrap[method];
|
|
instanceToWrap[method] = function () {
|
|
// Manipulating arguments directly is discouraged
|
|
var args = new Array(arguments.length);
|
|
for (var i = 0; i < arguments.length; ++i) {
|
|
args[i] = arguments[i];
|
|
}
|
|
|
|
// Grab the first parameter out in case it's a route or array of routes.
|
|
var first = null;
|
|
if (
|
|
"string" === typeof args[0] ||
|
|
args[0] instanceof RegExp ||
|
|
(Array.isArray(args[0]) &&
|
|
("string" === typeof args[0][0] || args[0][0] instanceof RegExp))
|
|
) {
|
|
first = args[0];
|
|
args = args.slice(1);
|
|
}
|
|
|
|
args = flattenDeep(args).map(function (arg) {
|
|
return wrapHandler(arg);
|
|
});
|
|
|
|
// If we have a route path or something, push it in front
|
|
if (first) {
|
|
args.unshift(first);
|
|
}
|
|
|
|
return instanceToWrap[original].apply(this, args);
|
|
};
|
|
});
|
|
|
|
return instanceToWrap;
|
|
};
|
|
|
|
var PromiseRouter = function (path) {
|
|
var me = wrapMethods(new Router(path));
|
|
|
|
me.__route = me.route;
|
|
me.route = function (path) {
|
|
return wrapMethods(me.__route(path), true);
|
|
};
|
|
|
|
return me;
|
|
};
|
|
|
|
PromiseRouter.default = PromiseRouter;
|
|
module.exports = PromiseRouter;
|
|
|