Skip to content

Dev Console

@modularityjs/http-dev-console serves a development console at /dev answering the question every debugging session starts with: what actually booted?

Built-in panels:

  • Modules (load order) — every module in the topological order the loader derived.
  • Pools — each pool with its contributed entry keys.
  • Preferences — the winning module per contract token (last-wins already applied).
  • HTTP routes — method/path/controller/handler from decorator metadata (the same source http:route:list reads).

The data comes from AppIntrospection — a frozen snapshot the framework binds into the container on every boot — so the console shows the truth of this process, not a guess from source code.

Wiring

typescript
modules: [
  HttpModule.forRoot({ port: 3000 }),
  HttpFastifyModule,
  HttpDevConsoleModule,
],

Production-safe by default: the page returns 404 unless NODE_ENV !== 'production'. Override deliberately with HttpDevConsoleModule.forRoot({ enabled: true }) when dogfooding a prod-like environment.

Contributing a panel

The console is itself modular — any package or app module can add a section via DevConsolePanelsPool:

typescript
import { Inject, Injectable } from '@modularityjs/di';
import {
  DevConsolePanel,
  DevConsolePanelsPool,
  escapeHtml,
  renderTable,
} from '@modularityjs/http-dev-console';

@Injectable()
export class QueueDepthsPanel extends DevConsolePanel {
  readonly id = 'queue-depths';
  readonly title = 'Queue depths';

  constructor(@Inject(QueueService) private readonly queue: QueueService) {
    super();
  }

  async render(): Promise<string> {
    const depths = await this.queue.depths();
    return renderTable(
      ['Queue', 'Pending'],
      depths.map((d) => [escapeHtml(d.name), String(d.pending)]),
    );
  }
}
typescript
pools: [
  { pool: DevConsolePanelsPool, key: 'queue-depths', useClass: QueueDepthsPanel },
],

render() returns an HTML fragment (escape dynamic text with the exported escapeHtml; renderTable is provided for the common shape). A panel that throws renders its error message in place — one broken panel never takes the console down.