express-list-endpoints
Advanced tools
Comparing version 5.0.0 to 6.0.0
@@ -18,2 +18,17 @@ # Changelog | ||
## v6.0.0 - 2021-07-29 | ||
### Deprecated | ||
- **BREAKING CHANGE** Drop support for NodeJS v10 | ||
### Fixed | ||
- Fixed a problem when parsing the property `middlewares` for each endpoint being allocated in `middleware` property instead | ||
### Dev | ||
- Added CI using [GitHub Actions](https://docs.github.com/en/actions) | ||
- Update dev dependencies | ||
- Removed TravisCI from the project | ||
- Refactor code to use new JS methods and improve readability | ||
## v5.0.0 - 2020-07-12 | ||
@@ -20,0 +35,0 @@ |
{ | ||
"name": "express-list-endpoints", | ||
"version": "5.0.0", | ||
"version": "6.0.0", | ||
"description": "A express package to list all registered endoints and its verbs", | ||
@@ -34,13 +34,12 @@ "main": "src/index.js", | ||
"devDependencies": { | ||
"chai": "^4.2.0", | ||
"changelog-version": "^1.0.1", | ||
"eslint": "^7.4.0", | ||
"eslint-config-standard": "^14.1.1", | ||
"eslint-plugin-import": "^2.22.0", | ||
"chai": "^4.3.4", | ||
"changelog-version": "^2.0.0", | ||
"eslint": "^7.31.0", | ||
"eslint-config-standard": "^16.0.3", | ||
"eslint-plugin-import": "^2.23.4", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^4.2.1", | ||
"eslint-plugin-standard": "^4.0.1", | ||
"eslint-plugin-promise": "^5.1.0", | ||
"express": "^4.17.1", | ||
"mocha": "^8.0.1" | ||
"mocha": "^9.0.3" | ||
} | ||
} |
@@ -17,3 +17,3 @@ # Express List Endpoints | ||
app.route('/') | ||
.all(function(req, res) { | ||
.all(function namedMiddleware(req, res) { | ||
// Handle request | ||
@@ -34,10 +34,13 @@ }) | ||
console.log(listEndpoints(app)); | ||
/* It omits the 'all' verbs. | ||
[{ | ||
path: '/', | ||
methods: ['GET', 'POST'] | ||
methods: ['GET', 'POST'], | ||
middlewares: ['namedMiddleware', 'anonymous', 'anonymous'] | ||
}, | ||
{ | ||
path: '/about', | ||
methods: ['GET'] | ||
methods: ['GET'], | ||
middlewares: ['anonymous'] | ||
}] | ||
@@ -44,0 +47,0 @@ */ |
200
src/index.js
@@ -1,9 +0,7 @@ | ||
// var debug = require('debug')('express-list-endpoints') | ||
var regexpExpressRegexp = /^\/\^\\\/(?:(:?[\w\\.-]*(?:\\\/:?[\w\\.-]*)*)|(\(\?:\(\[\^\\\/]\+\?\)\)))\\\/.*/ | ||
// var arrayPathItemRegexp = /\^[^^$]*\\\/\?\(\?=\\\/\|\$\)\|?/ | ||
// var arrayPathsRegexp = /\(\?:((\^[^^$]*\\\/\?\(\?=\\\/\|\$\)\|?)+)\)\/i?/ | ||
var expressRootRegexp = '/^\\/?(?=\\/|$)/i' | ||
var regexpExpressParam = /\(\?:\(\[\^\\\/]\+\?\)\)/g | ||
const regExpToParseExpressPathRegExp = /^\/\^\\\/(?:(:?[\w\\.-]*(?:\\\/:?[\w\\.-]*)*)|(\(\?:\(\[\^\\\/]\+\?\)\)))\\\/.*/ | ||
const regExpToReplaceExpressPathRegExpParams = /\(\?:\(\[\^\\\/]\+\?\)\)/ | ||
const regexpExpressParamRegexp = /\(\?:\(\[\^\\\/]\+\?\)\)/g | ||
var STACK_ITEM_VALID_NAMES = [ | ||
const EXPRESS_ROOT_PATH_REGEXP_VALUE = '/^\\/?(?=\\/|$)/i' | ||
const STACK_ITEM_VALID_NAMES = [ | ||
'router', | ||
@@ -17,11 +15,8 @@ 'bound dispatch', | ||
*/ | ||
var getRouteMethods = function (route) { | ||
var methods = [] | ||
const getRouteMethods = function (route) { | ||
let methods = Object.keys(route.methods) | ||
for (var method in route.methods) { | ||
if (method === '_all') continue | ||
methods = methods.filter((method) => method !== '_all') | ||
methods = methods.map((method) => method.toUpperCase()) | ||
methods.push(method.toUpperCase()) | ||
} | ||
return methods | ||
@@ -31,7 +26,9 @@ } | ||
/** | ||
* Returns the names (or anonymous) of all the middleware attached to the | ||
* Returns the names (or anonymous) of all the middlewares attached to the | ||
* passed route | ||
* @param {Object} route | ||
* @returns {string[]} | ||
*/ | ||
var getRouteMiddleware = function (route) { | ||
return route.stack.map(function (item) { | ||
const getRouteMiddlewares = function (route) { | ||
return route.stack.map((item) => { | ||
return item.handle.name || 'anonymous' | ||
@@ -43,5 +40,7 @@ }) | ||
* Returns true if found regexp related with express params | ||
* @param {string} expressPathRegExp | ||
* @returns {boolean} | ||
*/ | ||
var hasParams = function (pathRegexp) { | ||
return regexpExpressParam.test(pathRegexp) | ||
const hasParams = function (expressPathRegExp) { | ||
return regexpExpressParamRegexp.test(expressPathRegExp) | ||
} | ||
@@ -54,24 +53,24 @@ | ||
*/ | ||
var parseExpressRoute = function (route, basePath) { | ||
var endpoints = [] | ||
const parseExpressRoute = function (route, basePath) { | ||
const paths = [] | ||
if (Array.isArray(route.path)) { | ||
route.path.forEach(function (path) { | ||
var endpoint = { | ||
path: basePath + (basePath && path === '/' ? '' : path), | ||
methods: getRouteMethods(route), | ||
middleware: getRouteMiddleware(route) | ||
} | ||
paths.push(...route.path) | ||
} else { | ||
paths.push(route.path) | ||
} | ||
endpoints.push(endpoint) | ||
}) | ||
} else { | ||
var endpoint = { | ||
path: basePath + (basePath && route.path === '/' ? '' : route.path), | ||
const endpoints = paths.map((path) => { | ||
const completePath = basePath && path === '/' | ||
? basePath | ||
: `${basePath}${path}` | ||
const endpoint = { | ||
path: completePath, | ||
methods: getRouteMethods(route), | ||
middleware: getRouteMiddleware(route) | ||
middlewares: getRouteMiddlewares(route) | ||
} | ||
endpoints.push(endpoint) | ||
} | ||
return endpoint | ||
}) | ||
@@ -81,22 +80,27 @@ return endpoints | ||
var parseExpressPath = function (expressPathRegexp, params) { | ||
var parsedPath = regexpExpressRegexp.exec(expressPathRegexp) | ||
var parsedRegexp = expressPathRegexp | ||
var paramIdx = 0 | ||
/** | ||
* @param {RegExp} expressPathRegExp | ||
* @param {Object[]} params | ||
* @returns {string} | ||
*/ | ||
const parseExpressPath = function (expressPathRegExp, params) { | ||
let expressPathRegExpExec = regExpToParseExpressPathRegExp.exec(expressPathRegExp) | ||
let parsedRegExp = expressPathRegExp.toString() | ||
let paramIndex = 0 | ||
while (hasParams(parsedRegexp)) { | ||
var paramId = ':' + params[paramIdx].name | ||
while (hasParams(parsedRegExp)) { | ||
const paramName = params[paramIndex].name | ||
const paramId = `:${paramName}` | ||
parsedRegexp = parsedRegexp | ||
.toString() | ||
.replace(/\(\?:\(\[\^\\\/]\+\?\)\)/, paramId) | ||
parsedRegExp = parsedRegExp | ||
.replace(regExpToReplaceExpressPathRegExpParams, paramId) | ||
paramIdx++ | ||
paramIndex++ | ||
} | ||
if (parsedRegexp !== expressPathRegexp) { | ||
parsedPath = regexpExpressRegexp.exec(parsedRegexp) | ||
if (parsedRegExp !== expressPathRegExp.toString()) { | ||
expressPathRegExpExec = regExpToParseExpressPathRegExp.exec(parsedRegExp) | ||
} | ||
parsedPath = parsedPath[1].replace(/\\\//g, '/') | ||
const parsedPath = expressPathRegExpExec[1].replace(/\\\//g, '/') | ||
@@ -106,4 +110,10 @@ return parsedPath | ||
var parseEndpoints = function (app, basePath, endpoints) { | ||
var stack = app.stack || (app._router && app._router.stack) | ||
/** | ||
* @param {Object} app | ||
* @param {string} [basePath] | ||
* @param {Object[]} [endpoints] | ||
* @returns {Object[]} | ||
*/ | ||
const parseEndpoints = function (app, basePath, endpoints) { | ||
const stack = app.stack || (app._router && app._router.stack) | ||
@@ -114,3 +124,3 @@ endpoints = endpoints || [] | ||
if (!stack) { | ||
addEndpoints(endpoints, [{ | ||
endpoints = addEndpoints(endpoints, [{ | ||
path: basePath, | ||
@@ -121,21 +131,3 @@ methods: [], | ||
} else { | ||
stack.forEach(function (stackItem) { | ||
if (stackItem.route) { | ||
var newEndpoints = parseExpressRoute(stackItem.route, basePath) | ||
endpoints = addEndpoints(endpoints, newEndpoints) | ||
} else if (STACK_ITEM_VALID_NAMES.indexOf(stackItem.name) > -1) { | ||
if (regexpExpressRegexp.test(stackItem.regexp)) { | ||
var parsedPath = parseExpressPath(stackItem.regexp, stackItem.keys) | ||
parseEndpoints(stackItem.handle, basePath + '/' + parsedPath, endpoints) | ||
} else if (!stackItem.path && stackItem.regexp && stackItem.regexp.toString() !== expressRootRegexp) { | ||
var regEcpPath = ' RegExp(' + stackItem.regexp + ') ' | ||
parseEndpoints(stackItem.handle, basePath + '/' + regEcpPath, endpoints) | ||
} else { | ||
parseEndpoints(stackItem.handle, basePath, endpoints) | ||
} | ||
} | ||
}) | ||
endpoints = parseStack(stack, basePath, endpoints) | ||
} | ||
@@ -151,25 +143,57 @@ | ||
* | ||
* @param {Array} endpoints Array of current endpoints | ||
* @param {Object[]} newEndpoints New endpoints to be added to the array | ||
* @returns {Array} Updated endpoints array | ||
* @param {Object[]} currentEndpoints Array of current endpoints | ||
* @param {Object[]} endpointsToAdd New endpoints to be added to the array | ||
* @returns {Object[]} Updated endpoints array | ||
*/ | ||
var addEndpoints = function (endpoints, newEndpoints) { | ||
newEndpoints.forEach(function (newEndpoint) { | ||
var foundEndpointIdx = endpoints.findIndex(function (item) { | ||
return item.path === newEndpoint.path | ||
}) | ||
const addEndpoints = function (currentEndpoints, endpointsToAdd) { | ||
endpointsToAdd.forEach((newEndpoint) => { | ||
const existingEndpoint = currentEndpoints.find( | ||
(item) => item.path === newEndpoint.path | ||
) | ||
if (foundEndpointIdx > -1) { | ||
var foundEndpoint = endpoints[foundEndpointIdx] | ||
if (existingEndpoint !== undefined) { | ||
const newMethods = newEndpoint.methods.filter( | ||
(method) => !existingEndpoint.methods.includes(method) | ||
) | ||
var newMethods = newEndpoint.methods.filter(function (method) { | ||
return foundEndpoint.methods.indexOf(method) === -1 | ||
}) | ||
foundEndpoint.methods = foundEndpoint.methods.concat(newMethods) | ||
existingEndpoint.methods = existingEndpoint.methods.concat(newMethods) | ||
} else { | ||
endpoints.push(newEndpoint) | ||
currentEndpoints.push(newEndpoint) | ||
} | ||
}) | ||
return currentEndpoints | ||
} | ||
/** | ||
* @param {Object} stack | ||
* @param {string} basePath | ||
* @param {Object[]} endpoints | ||
* @returns {Object[]} | ||
*/ | ||
const parseStack = function (stack, basePath, endpoints) { | ||
stack.forEach((stackItem) => { | ||
if (stackItem.route) { | ||
const newEndpoints = parseExpressRoute(stackItem.route, basePath) | ||
endpoints = addEndpoints(endpoints, newEndpoints) | ||
} else if (STACK_ITEM_VALID_NAMES.includes(stackItem.name)) { | ||
const isExpressPathRegexp = regExpToParseExpressPathRegExp.test(stackItem.regexp) | ||
let newBasePath = basePath | ||
if (isExpressPathRegexp) { | ||
const parsedPath = parseExpressPath(stackItem.regexp, stackItem.keys) | ||
newBasePath += `/${parsedPath}` | ||
} else if (!stackItem.path && stackItem.regexp && stackItem.regexp.toString() !== EXPRESS_ROOT_PATH_REGEXP_VALUE) { | ||
const regExpPath = ` RegExp(${stackItem.regexp}) ` | ||
newBasePath += `/${regExpPath}` | ||
} | ||
endpoints = parseEndpoints(stackItem.handle, newBasePath, endpoints) | ||
} | ||
}) | ||
return endpoints | ||
@@ -182,4 +206,4 @@ } | ||
*/ | ||
var getEndpoints = function (app) { | ||
var endpoints = parseEndpoints(app) | ||
const getEndpoints = function (app) { | ||
const endpoints = parseEndpoints(app) | ||
@@ -186,0 +210,0 @@ return endpoints |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
16843
9
8
165
59
1