Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@contrast/route-coverage

Package Overview
Dependencies
Maintainers
14
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@contrast/route-coverage - npm Package Compare versions

Comparing version 1.6.0 to 1.7.0

2

lib/index.d.ts

@@ -28,3 +28,3 @@ /*

discoveryFinished(): void;
observe(info: Pick<RouteInfo, 'method' | 'url'>): void;
observe(info: Pick<RouteInfo>): void;
}

@@ -31,0 +31,0 @@

@@ -49,3 +49,3 @@ /*

observe(info) {
const route = routeInfo.get(routeIdentifier(info));
const route = info.signature ? info : routeInfo.get(routeIdentifier(info));

@@ -52,0 +52,0 @@ if (!route) {

@@ -28,5 +28,6 @@ /*

];
// eslint-disable-next-line node/no-extraneous-require
const fnInspect = require('@contrast/fn-inspect');
const { createSignature, patchType } = require('../utils/route-info');
const { createSignature, patchType } = require('./../utils/route-info');
/**

@@ -41,23 +42,77 @@ * @param {import('..').Core & {

const routers = new Map();
const signatureMap = new Map();
const { patcher, depHooks, routeCoverage } = core;
function emitRouteCoverage(router, url, method) {
const event = { signature: createSignature(url, method), url, method };
const layers = routers.get(router) || [];
layers.push(event);
routers.set(router, layers);
routeCoverage.discover(event);
function formatUrl(url) {
if (Array.isArray(url)) {
return `/[${url.join(', ')}]`;
} else if (url instanceof RegExp) {
return `/{${url.toString().replace(/(^\/?)|(\/?$)/g, '')}}`;
} else {
return url;
}
}
function handleRouteDiscovery(data, method) {
const [url, fn] = data.args;
if (!url || !fn) {
return;
function getLastLayer(router) {
if (router.stack) {
const len = router.stack.length;
return router.stack[len - 1];
}
if (Array.isArray(url)) {
url.forEach((path) => {
emitRouteCoverage(data.result, path, method);
}
function getLayerHandleMethod(layer) {
let methodName = 'handle';
const __handleData = fnInspect.funcInfo(layer.__handle);
if (__handleData && __handleData.file.includes('express-async-errors')) {
methodName = '__handle';
}
return methodName;
}
function patchHandler(layer, route) {
if (!layer) return;
const handle = getLayerHandleMethod(layer);
patcher.patch(layer, handle, {
name: 'express.Router.handle',
patchType,
post(data) {
const [req] = data.args;
const method = req?.method?.toLowerCase();
const url = `${req.baseUrl}${req._parsedUrl.pathname}`;
const { signature } = signatureMap.get(route.signature);
if (method) routeCoverage.observe({ signature, url, method });
}
});
}
function createRoute(url, method, id) {
const signature = createSignature(url, method);
const route = { signature, url, method, id: id || signature };
signatureMap.set(signature, route);
return route;
}
function discoverRoute({ signature, url, method }) {
routeCoverage.discover({ signature, url, method });
}
function instrumentRoute(router, route) {
if (!router) return;
const layer = getLastLayer(router);
patchHandler(layer, route);
}
function updateRoutes(prefix, router, updatedRouter) {
const routes = routers.get(router);
const updatedLayers = router === updatedRouter
? [] : (routers.get(updatedRouter) || []);
if (routes) {
routes.forEach((route) => {
const { url, method, id } = route;
const newRoute = createRoute(`${prefix}${url}`, method, id);
updatedLayers.push(newRoute);
signatureMap.set(id, newRoute);
});
} else {
emitRouteCoverage(data.result, url, method);
routers.set(router, updatedLayers);
routers.set(updatedRouter, updatedLayers);
}

@@ -71,13 +126,2 @@ }

(express) => {
patcher.patch(express.Router, 'handle', {
name: 'express.Router.handle',
patchType,
post(data) {
// TODO: Can this handle all route observation?
const [req] = data.args;
const method = req?.method?.toLowerCase();
const url = `${req.baseUrl}${req._parsedUrl.pathname}`;
if (method) routeCoverage.observe({ url, method });
}
});

@@ -89,15 +133,19 @@ patcher.patch(express.Router, 'use', {

const [prefix, router] = args;
const layers = routers.get(router);
const updatedLayers = [];
if (layers) {
layers.forEach((layer) => {
const { url, method } = layer;
const updatedUrl = `${prefix}${url}`;
const event = { signature: createSignature(updatedUrl, method), url: updatedUrl, method };
updatedLayers.push(event);
routeCoverage.delete(layer);
routeCoverage.discover(event);
if (typeof prefix === 'string' && prefix !== '/') {
updateRoutes(prefix, router, result);
}
}
});
patcher.patch(express.application, 'use', {
name: 'express.application.use',
patchType,
post({ args }) {
const idx = args.length;
const router = args[idx - 1];
const routes = routers.get(router);
if (routes) {
routes.forEach((route) => {
discoverRoute(route);
});
routers.delete(router);
routers.set(result, updatedLayers);
}

@@ -111,4 +159,8 @@ }

patchType,
post(data) {
handleRouteDiscovery(data, method);
post({ args, result }) {
const [url, fn] = args;
if (!url || !fn) return;
const route = createRoute(formatUrl(url), method);
instrumentRoute(result?._router, route);
discoverRoute(route);
}

@@ -120,4 +172,11 @@ });

patchType,
post(data) {
handleRouteDiscovery(data, method);
post({ args, obj: router }) {
const [url, fn] = args;
if (!url || !fn) return;
const route = createRoute(formatUrl(url), method);
const routes = routers.get(router) || [];
instrumentRoute(router, route);
routes.push(route);
routers.set(router, routes);
}

@@ -124,0 +183,0 @@ });

{
"name": "@contrast/route-coverage",
"version": "1.6.0",
"version": "1.7.0",
"description": "",

@@ -17,4 +17,4 @@ "license": "SEE LICENSE IN LICENSE",

"dependencies": {
"@contrast/common": "1.10.0"
"@contrast/common": "1.11.0"
}
}
SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc