r/expressjs • u/127001-sweet-127001 • 2h ago
The Express middleware import cycle that a middleware-only check misses
A middleware needs an app setting. It imports your exported app, and now the source dependencies look like this:
app.ts -> routes/orders.ts
-> middleware/tenant-context.ts -> app.tsAll the files in middleware/ can look fine when checked in isolation. The cycle leaves that folder and comes back through the router.
This is a useful detail when writing a cycle test with my library, ArchUnitTS:
import { projectFiles } from 'archunit';
const violations = await projectFiles('tsconfig.json')
.inFolder('src/**')
.should()
.haveNoCycles()
.check();
expect(violations).toEqual([]);Use a scope that contains the whole chain. With that example, src/middleware/** alone passes because this check looks for cycles within the selected files. src/** reports the three-file cycle.
For middleware that needs the current Express app, req.app is already available. Using req.app.get('tenantConfig') inside the middleware lets you remove the singleton import. Passing the particular dependency into a middleware factory is another option. The app can still import the router and register the middleware; that forward wiring is fine.
One fewer reason for middleware to know about bootstrap code
The check follows static imports, not the order Express runs middleware. This API is available in archunit 2.5.5 on npm, free and open source.
