Как это работает

Ни monkey-patching, ни прокси в рантайме: только точный момент вызова и метаданные Reflect.

Конвейер

DocfyModule.forRoot() отрабатывает синхронно на этапе NestFactory.create(), до вызова SwaggerModule.createDocument(). Через require() он загружает каждый companion-файл документации, тот выполняет docs() и записывает метаданные Reflect прямо в методы контроллера, ровно так же, как это сделал бы синтаксис декораторов TypeScript в момент определения класса.

К моменту, когда SwaggerModule.createDocument() начинает искать метаданные, всё уже на месте. Ни monkey-patching, ни прокси в рантайме не нужны.

Порядок вызовов

Главное про порядок вызовов

onModuleInit и остальные хуки жизненного цикла срабатывают уже после того, как в main.ts вызван SwaggerModule.createDocument(). Любой подход на основе onModuleInit дал бы пустую документацию Swagger. Поэтому nestjs-docfy идёт другим путём и делает синхронный require() внутри forRoot(), который выполняется во время NestFactory.create(), до любого хука и до обращения к SwaggerModule.

CLI: статический анализ

CLI generate использует ts-morph для статического анализа: читает AST TypeScript, не выполняя код проекта. Все пришедшие от пользователя пути и glob-шаблоны проверяются и очищаются перед использованием.