Relocate the ~6k-file docs tree from the repo root into plugins/document-navigator/docs/ so the plugin is self-contained and portable. docs/superpowers/ (specs and plans) stays at the repo root. Moved via cp+rm rather than git mv because directory rename() fails with EPERM on this WSL /mnt DrvFs mount; git rename-detection pairs the identical-content files at commit time. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@suaveplan/telegram-client - Telegram Bot API client — send/edit/delete messages, media, inline + custom keyboards, typed errors, injectable fetch + clock, OTel instrumented
Telegram Bot API client: send/edit/delete messages, six media variants,
inline + custom keyboards, typed errors, injectable fetch + clock, and
OpenTelemetry counters/histograms on every code path. Runtime-agnostic
(works in Bun, Node, Deno, browsers).
Documentation tree
- telegram-bot-client —
TelegramBotClientis the public, runtime-agnostic Telegram Bot API client. It wraps the handful of Bot API endpoints…- telegram-bot-client —
TelegramBotClientis the public, runtime-agnostic Telegram Bot API client. It wraps the handful of Bot API endpoints…
- telegram-bot-client —
- errors — Defines the namespaced, frozen error-code registry and the typed
TelegramClientErrorclass used by every runtime fail…- telegram-client-error — Defines the namespaced, frozen error-code registry and the typed
TelegramClientErrorclass used by every runtime fail…
- telegram-client-error — Defines the namespaced, frozen error-code registry and the typed
- types — Defines the Zod schema that validates
TelegramBotConfigat the public construction boundary ofTelegramBotClient. T…- telegram-bot-config — Defines the Zod schema that validates
TelegramBotConfigat the public construction boundary ofTelegramBotClient. T…
- telegram-bot-config — Defines the Zod schema that validates
- build-bodies — Pure, side-effect-free helpers that translate the camelCase public message / reply-markup shape used by callers into th…
- classify-error — Pure helpers that turn an outgoing-protocol failure (HTTP status + Telegram
description+ parsed body) into a stable…
Installation
bun add @suaveplan/telegram-client
Quick Start
import { createTelegramBotClient } from "@suaveplan/telegram-client";
const bot = createTelegramBotClient({ token: process.env.TELEGRAM_TOKEN! });
const sent = await bot.sendMessage({
chatId: 12345,
text: "Hello",
parseMode: "HTML",
});
console.log(sent.messageId);
Modules
| Module | Path | Description |
|---|---|---|
| Client | src/core/telegram-bot-client/telegram-bot-client.md | TelegramBotClient class, factory, OTel metrics |
| Body Builders | src/utils/build-bodies.md | Pure camelCase → snake_case translators |
| Error Classifier | src/utils/classify-error.md | Pure status + retry-after classifier |
| Errors | src/errors/telegram-client-error.md | Code registry + typed error class |
| Config Schema | src/types/telegram-bot-config.md | Zod validation at the boundary |
| Types | src/types/telegram-client.types.md | Public type surface |
Subpath Exports
import { createTelegramBotClient } from "@suaveplan/telegram-client";
import {
TELEGRAM_CLIENT_CODES,
TelegramClientError,
} from "@suaveplan/telegram-client/errors";
import type { TelegramMessage } from "@suaveplan/telegram-client/types";
Error Codes
| Code | When |
|---|---|
TELEGRAM_CLIENT.CONFIG_MISSING |
Config rejected by Zod schema (missing token, invalid URL, etc.) |
TELEGRAM_CLIENT.TIMEOUT |
Request aborted before completion |
TELEGRAM_CLIENT.AUTH_ERROR |
Telegram returned HTTP 401 |
TELEGRAM_CLIENT.RATE_LIMITED |
Telegram returned HTTP 429 (context.retryAfterMs set if parseable) |
TELEGRAM_CLIENT.CHAT_NOT_FOUND |
HTTP 404, or HTTP 400 with chat not found / channel not found |
TELEGRAM_CLIENT.BOT_BLOCKED |
HTTP 403 with bot was blocked / user is deactivated |
TELEGRAM_CLIENT.FORBIDDEN |
Other HTTP 403, or HTTP 400 with not enough rights / forbidden |
TELEGRAM_CLIENT.API_ERROR |
Catch-all for unclassified Telegram failures |
OTel Instruments
- Counter
telegram_client.request.total— keyed by{ method, outcome } - Histogram
telegram_client.request.duration_ms— keyed by{ method, outcome } outcome ∈ { "success", "error", "timeout" }
Call resetTelegramClientMetrics() from tests after replacing the global
MeterProvider so each test sees a fresh meter.
Verification
- Tests use injected
fetch/clock— no mocks, no network. - 100% istanbul coverage on touched modules.