Gramforge

Transport Fetch API reference

Exports of @gramforge/transport-fetch. Back to the module

Functions

albumSizeError

function

Runtime backstop for the compile-time {@link MediaGroupItems} tuple: a value that reaches `sendMediaGroup` via a cast or an `unknown`-typed JSON decode is length-checked here. Returns a `badRequest` `DeliveryResult` when out of the 2-10 range, or `null` when the size is valid.

albumSizeError(items: readonly MediaGroupItem[]): DeliveryResult<never> | null

createBotClient

function

Build a {@link BotClient} bound to a token + `fetch`.

createBotClient(config: BotClientConfig): BotClient

mapDelivery

function

Map the success value of a {@link DeliveryResult} while preserving every error variant unchanged. Used to adapt one method's result type to another (e.g. an `EditMessageResult` down to a `TelegramMessage`) without a cast and without dropping the typed-error branches.

<A, B>(result: DeliveryResult<A>, transform: (value: A) => B): DeliveryResult<B>

toWireEntities

function

Project a whole rendered entity list to wire objects.

toWireEntities(entities: readonly MessageEntity[]): readonly WireEntity[]

toWireEntity

function

Project one rendered {@link MessageEntity} to its Bot API wire object.

toWireEntity(entity: MessageEntity): WireEntity

toInlineMessageId

function

Brand a raw string as an {@link InlineMessageId}.

toInlineMessageId(value: string): InlineMessageId

toRetryAfter

function

Brand a raw seconds number as a {@link RetryAfter}. Called only on a value already zod-parsed from the wire `parameters.retry_after` field.

toRetryAfter(seconds: number): RetryAfter

createLiveMessage

function

Construct a {@link LiveMessage} over an injected {@link LiveMessagePort}. Uses the ambient `setTimeout`/`clearTimeout`/`Date.now` (mockable by fake timers in tests); it never sleeps on a 429.

createLiveMessage(port: LiveMessagePort, options: LiveMessageOptions): LiveMessage

isMessageNotModified

function

The single, tested predicate for Telegram's "message is not modified" reply. There is no dedicated error code, so this matches the `description` wording (isolated here so a future Bot API rewording is a one-line fix).

isMessageNotModified(result: DeliveryResult<unknown>): boolean

parseWireResponse

function

THE wire boundary: read a `Response`'s JSON, `safeParse` the Bot API envelope, then `safeParse` the success `result` against `dataSchema`. A `res.json()` rejection becomes `networkError`; an unrecognized 200 body becomes `serverError`; an `ok: false` body maps to its typed error variant. Never throws, never returns unparsed data.

<T>(res: Response, dataSchema: WireSchema<T>): Promise<DeliveryResult<T>>

Types

FetchLike

type

The `fetch` implementation a client calls — global `fetch` by default.

type FetchLike = { (input: RequestInfo | URL, init?: RequestInit): Promise<Response>; (input: string | URL | Request, init?: RequestInit): Promise<Response>; }

MediaGroupItems

type

A 2-to-10-item album, enforced at COMPILE TIME by an explicit tuple-length union: 0/1 items and 11+ items fail to type-check (spec `bot-api-transport`, "Album size out of range is a compile-time error"). A runtime guard in `sendMediaGroup` backstops values that arrive via a cast.

type MediaGroupItems = | readonly [MediaGroupItem, MediaGroupItem]
  | readonly [MediaGroupItem, MediaGroupItem, MediaGroupItem]
  | readonly [MediaGroupItem, MediaGroupItem, MediaGroupItem, MediaGroupItem]
  | readonly [MediaGroupItem, MediaGroupItem, MediaGroupItem, MediaGroupItem, MediaGroupItem]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]
  | readonly [
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
      MediaGroupItem,
    ]

MediaSource

type

How a media item's file is referenced (no raw multipart upload here).

type MediaSource = | { readonly kind: "fileId"; readonly fileId: string }
  | { readonly kind: "url"; readonly url: string }

WebAppInlineResult

type

The inline result passed to `answerWebAppQuery`.

type WebAppInlineResult = WebAppInlineResultArticle

DeliveryResult

type

Outcome of a single Bot API call. `ok` carries the method's parsed result; every other variant is a typed, non-throwing failure.

type DeliveryResult = DeliveryResult<T>

WireEntity

type

A Bot API `MessageEntity` object as it appears on the wire.

type WireEntity = {
  readonly type: string;
  readonly offset: number;
  readonly length: number;
  readonly url?: string;
  readonly language?: string;
  readonly user?: { readonly id: number };
}

InlineMessageId

type

The opaque id of an inline message (from an inline query / web-app result).

type InlineMessageId = Brand<string, "InlineMessageId">

RetryAfter

type

Seconds a caller must wait before retrying, from a 429 `retry_after`.

type RetryAfter = Brand<number, "RetryAfter">

EditTarget

type

Which message an `editMessageText` targets.

type EditTarget = | { readonly kind: "chatMessage"; readonly chatId: ChatId; readonly messageId: MessageId }
  | { readonly kind: "inlineMessage"; readonly inlineMessageId: InlineMessageId }

KnownOrUnknown

type

Presence of a value, modeled as a DU rather than `T | undefined`.

type KnownOrUnknown = KnownOrUnknown<T>

EditMessageResult

type

Result of an `editMessageText` call. A chat-message edit returns the updated `Message`; an inline-message edit returns the wire literal `true` (there is no message object) — modeled as an explicit DU, never `Message | undefined`.

type EditMessageResult = | { readonly kind: "edited"; readonly message: TelegramMessage }
  | { readonly kind: "inlineEdited" }

Interfaces

AnswerCallbackQueryArgs

interface

Arguments for `answerCallbackQuery`.

interface AnswerCallbackQueryArgs

callbackQueryId

property
callbackQueryId: string

text

property
text: string

showAlert

property
showAlert: boolean

AnswerWebAppQueryArgs

interface

Arguments for `answerWebAppQuery`.

interface AnswerWebAppQueryArgs

webAppQueryId

property
webAppQueryId: string

result

property
result: WebAppInlineResultArticle

BotClient

interface

The raw Bot API client surface.

interface BotClient

sendMessage

method
sendMessage(args: SendMessageArgs): Promise<DeliveryResult<TelegramMessage>>

sendPhoto

method
sendPhoto(args: SendPhotoArgs): Promise<DeliveryResult<TelegramMessage>>

editMessageText

method
editMessageText(args: EditMessageTextArgs): Promise<DeliveryResult<EditMessageResult>>

sendMediaGroup

method
sendMediaGroup(args: SendMediaGroupArgs): Promise<DeliveryResult<readonly TelegramMessage[]>>

answerCallbackQuery

method
answerCallbackQuery(args: AnswerCallbackQueryArgs): Promise<DeliveryResult<true>>

answerWebAppQuery

method
answerWebAppQuery(args: AnswerWebAppQueryArgs): Promise<DeliveryResult<SentWebAppMessage>>

liveMessage

method

A create-once/edit-many live-progress message in `chatId`.

liveMessage(args: LiveMessageArgs): LiveMessage

BotClientConfig

interface

Configuration for {@link createBotClient}.

interface BotClientConfig

token

property

The bot token (the `bot<token>` path segment is added internally).

token: string

fetch

property

Override the `fetch` used (tests inject a fake); defaults to `globalThis.fetch`.

fetch: { (input: RequestInfo | URL, init?: RequestInit): Promise<Response>; (input: string | URL | Request, init?: RequestInit): Promise<Response>; }

baseUrl

property

Override the API origin; defaults to `https://api.telegram.org`.

baseUrl: string

EditMessageTextArgs

interface

Arguments for `editMessageText` (chat-message or inline-message target).

interface EditMessageTextArgs

target

property
target: EditTarget

message

property
message: MessageText

replyMarkup

property
replyMarkup: InlineKeyboardMarkup

LiveMessageArgs

interface

Arguments for {@link BotClient.liveMessage}.

interface LiveMessageArgs

chatId

property
chatId: ChatId

minEditIntervalMs

property
minEditIntervalMs: number

MediaGroupItem

interface

A single album item. Its caption presence is a DU, never `undefined`.

interface MediaGroupItem

type

property
type: "photo" | "video" | "document" | "audio"

source

property
source: MediaSource

caption

property
caption: { readonly kind: "known"; readonly value: CaptionText; } | { readonly kind: "unknown"; }

SendMediaGroupArgs

interface

Arguments for `sendMediaGroup`.

interface SendMediaGroupArgs

chatId

property
chatId: ChatId

items

property
items: MediaGroupItems

SendMessageArgs

interface

Arguments for `sendMessage`.

interface SendMessageArgs

chatId

property
chatId: ChatId

message

property
message: MessageText

replyMarkup

property
replyMarkup: InlineKeyboardMarkup

SendPhotoArgs

interface

Arguments for `sendPhoto` — a single photo (by `file_id` or public URL) with an optional {@link CaptionText}. Telegram fetches a `url` photo itself, so it must be a publicly reachable absolute URL (not a relative path).

interface SendPhotoArgs

chatId

property
chatId: ChatId

photo

property
photo: MediaSource

caption

property
caption: CaptionText

replyMarkup

property
replyMarkup: InlineKeyboardMarkup

WebAppInlineResultArticle

interface

The `answerWebAppQuery` inline-result subset this change ships (design Open Question, resolved): only an `article` result whose body is a rendered `MessageText` — the shape the mini-app "send to a chat" composer flow needs. Photo/video/other `InlineQueryResult` variants are added when `miniapp` lands as new DU members (non-breaking).

interface WebAppInlineResultArticle

kind

property
kind: "article"

id

property
id: string

title

property
title: string

message

property
message: MessageText

LiveMessage

interface

A live-progress message handle.

interface LiveMessage

update

method

Record the latest text and schedule a debounced flush (synchronous).

update(text: string): void

flush

method

Force an immediate write of the pending text now, bypassing the debounce.

flush(): Promise<DeliveryResult<TelegramMessage>>

finish

method

Write `finalText` once immediately and close the instance.

finish(finalText: string): Promise<DeliveryResult<TelegramMessage>>

LiveMessageOptions

interface

Options for {@link createLiveMessage}.

interface LiveMessageOptions

minEditIntervalMs

property

Minimum spacing between issued edits, in milliseconds.

minEditIntervalMs: number

LiveMessagePort

interface

The transport seam `LiveMessage` drives: a `send` that establishes the target message and an `edit` that updates it, both returning a {@link DeliveryResult}. `transport-fetch` and `transport-grammy` each supply their own implementation.

interface LiveMessagePort

send

method
send(text: string): Promise<DeliveryResult<TelegramMessage>>

edit

method
edit(target: EditTarget, text: string): Promise<DeliveryResult<TelegramMessage>>

SentWebAppMessage

interface

The confirmation returned by `answerWebAppQuery`: a `SentWebAppMessage` whose `inline_message_id` is present only when the message can later be edited.

interface SentWebAppMessage

inlineMessageId

property
inlineMessageId: { readonly kind: "known"; readonly value: string; } | { readonly kind: "unknown"; }

TelegramMessage

interface

A Telegram `Message`, projected to the branded ids the transport exposes.

interface TelegramMessage

messageId

property
messageId: MessageId

chatId

property
chatId: ChatId

date

property
date: number

Constants

EditMessageResultSchema

const

{@link EditMessageResult} response schema.

const EditMessageResultSchema: WireSchema<EditMessageResult>

SentWebAppMessageSchema

const

{@link SentWebAppMessage} response schema.

const SentWebAppMessageSchema: WireSchema<SentWebAppMessage>

TelegramMessageArraySchema

const

An array of {@link TelegramMessage}s, as `sendMediaGroup` returns.

const TelegramMessageArraySchema: WireSchema<readonly TelegramMessage[]>

TelegramMessageSchema

const

{@link TelegramMessage} response schema.

const TelegramMessageSchema: WireSchema<TelegramMessage>

TrueResultSchema

const

The `answerCallbackQuery` result — the Bot API returns the literal `true`.

const TrueResultSchema: WireSchema<true>