0

I am trying to create a function that would determine the dependents and dependencies of a given route's middleware in Express. The goal is to figure out how separated my routes are so that I can begin to think about the best place to begin a migration to a more microservice-based architecture.

Right now, I've figured out that I can access a list of middleware functions through Express' app._router.router._stack object, from which I can dig into bound and routed dispatchers for a stack of middleware. Below is the output of a function I have written to that utilizes a bunch of classes to traverse the app object to get a list of middleware functions.

The problem is that for anonymous functions (eg. those defined as methods on a controller), I cannot figure out a way to find the files these functions actually live in. That prevents me from easily accessing their dependencies and dependents, which I need for figuring out the function's scope and its relation to others.

expressMap.js output:

MIDDLEWARE: 

Layer {
  handle: [Function: router] {
    params: {},
    _params: [],
    caseSensitive: undefined,
    mergeParams: undefined,
    strict: undefined,
    stack: [ [Layer], [Layer] ]
  },
  name: 'router',
  params: undefined,
  path: undefined,
  keys: [],
  regexp: /^\/api\/?(?=\/|$)/i { fast_star: false, fast_slash: false },
  route: undefined
}


MIDDLEWARE HANDLERS STACK: 

/
/more-characters


FUNCTION DEFINTIONS IN ROUTE /: 

(req, res, next) => {
  console.log("inside getCharacters filecontroller")
  fsCallback.readFile(path.resolve(__dirname, '../data/characters.json'),
    'UTF-8', 
    (err, chars) => {
      if (err) return next(createErr({
          method: 'getCharacters',
          type: 'reading file',
          err,
        }));
      const parsedData = JSON.parse(chars);
      res.locals.characters = parsedData.results;
      return next();
    });
} 

(req, res, next) => {
    res.status(200).set('Content-Type', 'text/plain').json({characters : res.locals.characters})
} 

//// Note: skipping /more-characters route for space ////

I think I am basically asking for a way of creating some sort of control flow graph for Express (though ideally, one that is more agnostic would be great) that can link the routes I use to the functions they rely on in their specific context.

I initially approached this problem by making the expressMap.js function whose output is shown above, and while I could reliably list out all my middleware functions as objects and grab their definitions, I could not figure out how to get their filepaths.

I have been looking into creating some pseudo-CFG with a convoluted traversal of the Abstract Syntax Trees of my entire directory, but I can't frame the task well enough (or like, efficiently/elegantly enough) in my mind to get started. One of the main sticking points for me here is tracking calls between files (eg. going from app.use in server.js, to some get method in /apiRouter.js, to some randomController.middleware in randomController.js.

The hacky solution I feel would be "search for an exact match of the text of the function definition in the directory, and then return the file it is found in," but I feel there has has to be a better way.

Any help is greatly appreciated!

  • It might be better to use something that examines the source and builds you a dependency graph / call tree. – jfriend00 Feb 10 '23 at 19:35
  • Thanks for the response!! I was trying to figure out something that did that but I didn't find a good batteries-included solution for call trees. Do you have any ideas? It's been difficult to search for. A dependency graph would be useful, but would need a good amount of functionality built on top of it, as afaik most of the ones Ive seen are meant for mapping file-to-file dependencies and not anything more granular. – user21175741 Feb 10 '23 at 21:26

0 Answers0