@yaebal/commands

one registry for command handlers and the Telegram / command menu — define each command once, then wire the handlers and push the menu from the same source of truth.

install

terminal
pnpm add @yaebal/commands

usage

create a registry with commands(), chain .add() calls to define each command, then call bot.install(cmd.plugin()) to register the handlers and cmd.register(bot.api) to push the menu to Telegram.

bot.ts
import { Bot } from "@yaebal/core";
import { commands } from "@yaebal/commands";

const bot = new Bot(process.env.BOT_TOKEN!);

const cmd = commands()
  .add("start", "start the bot", async (ctx) => {
    await ctx.reply("welcome!");
  })
  .add("help", "show help", async (ctx) => {
    await ctx.reply("available commands: /start, /help");
  });

// wire handlers onto the bot
bot.install(cmd.plugin());

// push the /command menu to Telegram
await cmd.register(bot.api);

bot.start();

localised menus

pass a languageCode to register() to push a language-specific menu. call it multiple times for different locales.

bot.ts
// push a localised menu for Russian users
await cmd.register(bot.api, { languageCode: "ru" });

api

exportsignaturedescription
commands() => CommandsRegistrycreate a new commands registry
CommandsRegistryinterfacethe object returned by commands()
BotCommandinterface\{ command: string; description: string \} — the shape used by setMyCommands

CommandsRegistry

methodsignaturedescription
add(name, description, ...handlers) => CommandsRegistrydefine a command — chainable
list() => BotCommand[]return the \{ command, description \}[] array for inspection or manual use
plugin() => Plugin<Context, Record<never, never>>returns a plugin that registers every command's handler on the composer — pass to bot.install()
register(api, options?) => Promise<unknown>calls setMyCommands via the Telegram API with the command list

register options

fieldtypedescription
languageCodestringIETF language tag passed as language_code to setMyCommands

list() and plugin() separately

list.ts
const cmd = commands()
  .add("start", "go", () => {})
  .add("help", "help", () => {});

cmd.list();
// [
//   { command: "start", description: "go" },
//   { command: "help", description: "help" },
// ]
composer.ts
import { Composer } from "@yaebal/core";

// install on a plain Composer as well as on Bot
const composer = new Composer().install(cmd.plugin());
registration order is insertion order. commands appear in the Telegram menu in the order they were added with .add().

bot.install(), not bot.use(). the plugin is installed via bot.install(cmd.plugin()). calling bot.use(cmd.plugin()) will not work — install is the correct method for plugins in yaebal.

handlers and menu are decoupled. plugin() only wires handlers; register() only pushes the menu. you can call them independently — for example, skip register() during local development to avoid overwriting the live menu.