npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

nestjs-telega

v1.0.0-rc.2

Published

Telegram bot module for NestJS

Readme

NestJS Telega

npm npm downloads GitHub last commit

NestJS Telega integrates telegraf-hardened with NestJS. It provides a NestJS module, decorators for Telegram updates, scenes and wizards, plus integration with guards, interceptors, filters and pipes.

This main branch prepares the next default release line. The stable Telegraf implementation is maintained in the telegraf branch and published under the npm dist-tag telegraf.

Features

  • Telegraf-hardened update handlers declared with NestJS decorators.
  • Multiple independently configured bots in one application.
  • Base scenes and wizard scenes.
  • NestJS guards, interceptors, exception filters and pipes in handlers.
  • Typed parameter decorators and listener return values.
  • Telegraf-hardened middleware before and after discovered handlers.
  • Explicit @Update() listener phases and priorities for reliable fallbacks.

Install the stable Telegraf line

npm install nestjs-telega@telegraf telegraf
yarn add nestjs-telega@telegraf telegraf

Always include @telegraf for the current Telegraf-based release line. telegraf is a peer dependency and must be installed by the application.

Install the next default line

The code in main uses telegraf-hardened and requires Node.js 18 or newer:

npm install nestjs-telega telegraf-hardened
yarn add nestjs-telega telegraf-hardened

Quick start

The example below applies to the next telegraf-hardened release line.

Register the module in the root NestJS module. By default, the bot starts with long polling when the application is initialized.

import { Module } from '@nestjs/common';
import { TelegrafModule } from 'nestjs-telega';

import { BotUpdate } from './bot.update';

@Module({
  imports: [
    TelegrafModule.forRoot({
      token: process.env.TELEGRAM_BOT_TOKEN!,
    }),
  ],
  providers: [BotUpdate],
})
export class AppModule {}

Create an update handler with Tg* decorators:

import { TgCommand, TgCtx, TgStart, TgUpdate } from 'nestjs-telega';
import type { Context } from 'telegraf-hardened';

@TgUpdate()
export class BotUpdate {
  @TgStart()
  onStart(): string {
    return 'Welcome!';
  }

  @TgCommand('chatid')
  onChatId(@TgCtx() ctx: Context): string {
    return `Your chat id is ${ctx.chat?.id}`;
  }
}

A string returned by a listener is sent as a reply. Handlers may also return a TelegrafListenerResult when a reply needs extra options or when handling callback and inline-query results.

The unprefixed names (@Update(), @Command(), @Ctx() and others) remain available as aliases. Prefer Tg* names in applications that use decorators from multiple bot transports.

Configuration

TelegrafModule.forRoot() accepts a TelegrafModuleOptions object. Important options include:

  • token — Telegram bot token from BotFather.
  • botName — unique name for a bot in a multi-bot application.
  • options — options passed to the Telegraf constructor.
  • launchOptions — telegraf-hardened launch configuration; use false in tests to avoid starting the bot.
  • include — Nest modules containing handlers for this bot.
  • middlewaresBefore and middlewaresAfter — telegraf-hardened middleware around discovered handlers.
  • replyOptions — default reply options for listener return values.
  • listenerDiagnostics — optional callback with the actual ordered update-listener registrations, suitable for safe startup diagnostics.

Listener order and fallbacks

@Update() handlers without ordering decorators keep their discovery order. For an explicit cross-module order, use @TgListenerPriority() (smaller values are registered first) and @TgListenerPhase('fallback') (registered after all normal handlers):

import {
  Next,
  On,
  TgListenerPhase,
  TgListenerPriority,
  TgUpdate,
} from 'nestjs-telega';

@TgUpdate()
export class PrivateMessagesUpdate {
  @TgListenerPriority(-10)
  @On('text')
  async handleKnownText(@Next() next: () => Promise<void>): Promise<void> {
    await next();
  }

  @TgListenerPhase('fallback')
  @On('text')
  onUnhandledText(): string {
    return 'I do not understand this message yet.';
  }
}

The phase and priority only control registration order; a matching earlier handler must still call next() for a fallback to receive the update. The unprefixed @ListenerPhase() and @ListenerPriority() aliases are available. See the listener order guide for diagnostics and full semantics.

Use forRootAsync() when configuration comes from another Nest provider:

import { Module } from '@nestjs/common';
import { ConfigModule, ConfigService } from '@nestjs/config';
import { TelegrafModule } from 'nestjs-telega';

@Module({
  imports: [
    ConfigModule.forRoot(),
    TelegrafModule.forRootAsync({
      inject: [ConfigService],
      useFactory: (config: ConfigService) => ({
        token: config.getOrThrow<string>('TELEGRAM_BOT_TOKEN'),
      }),
    }),
  ],
})
export class AppModule {}

Multiple bots

Call forRoot() or forRootAsync() once for each bot and give every additional bot a unique botName. Inject a specific instance with @TgInjectBot(botName) or access the registry with @TgInjectAllBots().

The complete sample demonstrates a default bot, two named bots, scenes, a wizard, middleware and bot injection.

Documentation and support