Analyzer::Javascript::RouterMountScanner
Inherits Analyzer::Javascript::ExpressConstants < Reference < Object
RouterMountScanner handles the two-pass scanning process for Express router mounts. It scans JavaScript/TypeScript files to discover router mount patterns like: app.use('/api', userRouter) router.use('/v1', require('./routes')) and stores the prefix information in CodeLocator for cross-file resolution.
Constants
restify-router: usersRouter.applyRoutes(server, '/users') and the
nested router.add('/v1', v1Router).
const api = Router()\n .use(items) and export default Router().use('/api', api): the .use( links of a chain on a fresh
router have no name. in front of them for the scans above. The
chain's head names the caller: the bound variable, or, for an
export default chain, the module itself ("" falls back to the
file's own prefix).
The handler is the last argument: onRequest(app) / onRequest({ region }, app).
app.lazyUse = function lazyUse(mountPath, requireFn) { app.use(mountPath, …) }
and the arrow form: a method whose definition hands its first parameter
to .use(…) as the mount path. A call to it is a mount, read the same
way .use('/p', child) is. Read off the definition, so no wrapper name
is assumed.
A Glue manifest lists its plugins as data, not .register( calls:
registrations: [{ plugin: { register: './api' }, options: { routes } }]
(Glue 4) or register: { plugins: [{ plugin: '../lib', routes }] }.
Hapi nests the prefix under routes, on the options or per plugin item.
Hono <chain>.route('/prefix', ChildApp) mounts. Registers the
prefix on the child's file when ChildApp is an imported router,
regardless of (or in the absence of) a named caller.
A module that is nothing but module.exports = require('./app') (or
export { default } from './app') exports what ./app exports, so
its prefix belongs on ./app, where the routes and mounts are.
Mount-call verbs scanned for literal prefixes (.use('/p', r) /
.route('/p', app)). Compiled once per verb — interpolated regex
literals would otherwise be rebuilt (full PCRE2 compile) on every
scan_literal_mount_calls invocation.
Rules::JS on five of seven axes — same nest kinds, same three quote
characters, same per-kind depth counters, same clamp, same
Escape::InQuotes. It diverges on strip and empties only, and only
because the hand-rolled body it replaces never stripped and kept its
interior empties: Rules::JS strips and drops every empty part.
Both divergences are invisible to the single caller — the loop in
parse_destructured_names does item.strip and skips the result when it
is empty — so this is faithfulness to the replaced body, not a behavior
requirement. File-local because no other splitter in the tree wants this
combination, and promoting a preset for one caller whose two distinctive
axes are unobservable would be misleading.
Constructors
framework is the analyzer that owns this scan — the same Symbol its
route pass hands to JSRouteExtractor.other_shared_extractor_framework?.
Both Express and Hono run a scanner over every JS/TS file in the tree,
and every prefix they resolve lands in one process-wide CodeLocator
table keyed by file. Without the symbol there is no way to tell "this
file is mine" from "this file belongs to Koa", so a koa-router module
picked up a / mount from the Express scanner and its routes were
emitted a second time at the bare path.