NestJS Profiler
API Reference

nest-profiler-commander

Types and API of the nest-commander CLI collector.

CommandInfo

Payload of a command profile's entrypoint.data (entrypoint type: 'command'). The module registers a command entrypoint type, so the profiler renders a dedicated Commands table and a Command detail tab for these profiles.

Prop

Type

Public exports

import { CommanderCollectorModule } from '@eleven-labs/nest-profiler-commander';
import { CommandProfiler } from '@eleven-labs/nest-profiler-commander';
import { COMMAND_ENTRYPOINT_TYPE } from '@eleven-labs/nest-profiler-commander';

import type { CommanderCollectorModuleOptions } from '@eleven-labs/nest-profiler-commander';
import type { CommandInfo } from '@eleven-labs/nest-profiler-commander';

Enabling and disabling

CommanderCollectorModule.forRoot() takes no required options. Gate it per environment with Nest's ConditionalModule so it loads only when the profiler is on — the same pattern used for every profiler module:

import { ConditionalModule } from '@nestjs/config';

const isProfilerEnabled = (env: NodeJS.ProcessEnv) => env['PROFILER_ENABLED'] === 'true'

ConditionalModule.registerWhen(CommanderCollectorModule.forRoot(), isProfilerEnabled),

Setup

Register the module in the module you bootstrap with CommandFactory:

cli.module.ts
import { Module } from '@nestjs/common';
import { ProfilerModule } from '@eleven-labs/nest-profiler';
import { ConditionalModule } from '@nestjs/config';
import { CommanderCollectorModule } from '@eleven-labs/nest-profiler-commander';
import { AppCommand } from './app.command';

const isProfilerEnabled = (env: NodeJS.ProcessEnv) => env['PROFILER_ENABLED'] === 'true';

@Module({
  imports: [ConditionalModule.registerWhen(CommanderCollectorModule.forRoot(), isProfilerEnabled)],
  providers: [AppCommand],
})
export class CliModule {}

Wire the core ProfilerModule (with storageType: 'file' so the CLI and HTTP server share profiles) once at the CLI root — see Enabling and disabling the profiler. If a command injects ProfilerService directly, also register its ProfilerNoopModule fallback.

cli.ts
import { CommandFactory } from 'nest-commander';
import { CliModule } from './cli.module';

async function bootstrap(): Promise<void> {
  await CommandFactory.run(CliModule, { logger: ['error', 'warn'] });
}

void bootstrap();

Every provider that extends nest-commander's CommandRunner is wrapped automatically - you do not change your command classes.

There is no forRootAsync by design: the collector has no runtime-resolved options (its only knob, enabled, is a synchronous build-time decision), so toggle it per environment with ConditionalModule.registerWhen(...).

Prerequisite: nest-commander installed, and a cross-process storage adapter if you want to inspect command profiles from the HTTP app's web profiler at /_profiler. The CLI and the server are separate processes, so they must share the backing store - use storageType: 'file' (or a Redis/DB adapter). In-memory storage is per-process and can never surface command profiles in a separate web server; the profiler logs a warning when you profile a command against an in-memory store.

How a command profile is shaped

A command has no HTTP request/response. The profiler synthesises a profile whose entrypoint is { type: 'command', data: CommandInfo }:

FieldValue
entrypoint.typecommand
entrypoint.data.nameThe command name (e.g. content:sync)
entrypoint.data.argumentsThe positional arguments
entrypoint.data.exitCode0 on success, 1 when the command threw
response.statusCode200 on success, 500 when the command threw

The command name, arguments, options, and exit code are kept on entrypoint.data. Because the command body runs inside the profiler's CLS context, profile-scoped collectors (HTTP client, cache, database, …) capture the work the command performs and contribute their own panels.

Powered & maintained by

On this page