# Gramforge API reference

> Exports of @gramforge/core.

Source: https://gramforge.n.yatsyk.com/docs/core/jsdoc

## Functions

### blockquote

```ts
blockquote(...children: readonly Inline[]): BlockquoteNode
```

### bold

```ts
bold(...children: readonly Inline[]): BoldNode
```

### code

```ts
code(value: string): CodeNode
```

### expandableBlockquote

```ts
expandableBlockquote(...children: readonly Inline[]): ExpandableBlockquoteNode
```

### gram

```ts
gram(strings: TemplateStringsArray, ...values: readonly GramValue[]): RichTextNode[]
```

### italic

```ts
italic(...children: readonly Inline[]): ItalicNode
```

### link

```ts
link(href: string, ...children: readonly Inline[]): LinkNode
```

### mentionUser

```ts
mentionUser(userId: number, label: string): MentionNode
```

### mentionUsername

```ts
mentionUsername(username: string): MentionNode
```

### pre

```ts
pre(value: string, language?: PreLanguage): PreNode
```

### spoiler

```ts
spoiler(...children: readonly Inline[]): SpoilerNode
```

### strikethrough

```ts
strikethrough(...children: readonly Inline[]): StrikethroughNode
```

### text

```ts
text(value: string): TextNode
```

### underline

```ts
underline(...children: readonly Inline[]): UnderlineNode
```

### defineCallbackAction

Validate `actionId` at call time and return an explicitly-typed def.

An invalid `actionId` is a programmer bug (a hardcoded literal that violates
the `/^[a-z0-9]{1,8}$/` budget), not an expected runtime path, so this throws
a descriptive `Error` rather than returning a result DU.

```ts
<TPayload extends Record<string, unknown>>(input: { actionId: string; payloadSchema: z.ZodType<TPayload>; fields: readonly (keyof TPayload & string)[]; }): CallbackActionDef<TPayload>
```

### decodeCallbackData

Decode a `callback_data` string against a namespace. Generic `TPayload` is
the caller's asserted payload type; the actual shape is enforced by the
matched action's zod schema, and the validated result is branded to
`TPayload` only after a successful `safeParse`.

```ts
<TPayload, TActions extends Record<string, AnyCallbackActionDef> = Record<string, AnyCallbackActionDef>>(callbackData: string, namespace: CallbackNamespace<TActions>, deps: CallbackDecodeDeps): Promise<CallbackDecodeResult<TPayload>>
```

### encodeCallbackAction

Encode via a namespace + action key. The key is narrowed to the namespace's
declared action names (a bogus key is a compile-time error, not a runtime
one); payload is a free `TPayload` here — `callbackButton` is the entry point
that ties payload shape to the chosen action.

```ts
<TPayload extends Record<string, unknown>, TActions extends Record<string, AnyCallbackActionDef>>(namespace: CallbackNamespace<TActions>, actionKey: keyof TActions & string, payload: TPayload, deps: CallbackEncodeDeps): Promise<string>
```

### callbackButton

Build one inline button for a bound action + typed payload. `payload` is
statically tied to the action's declared payload shape, so a missing/extra
field is a compile-time error.

```ts
<TPayload extends Record<string, unknown>>(text: string, action: BoundCallbackAction<TPayload>, payload: TPayload, deps: CallbackEncodeDeps): Promise<InlineKeyboardButton>
```

### inlineKeyboard

Shape a list of rows into an `InlineKeyboardMarkup`.

```ts
inlineKeyboard(rows: readonly (readonly InlineKeyboardButton[])[]): InlineKeyboardMarkup
```

### keyboardRow

Shape a list of buttons into a single keyboard row.

```ts
keyboardRow(buttons: readonly InlineKeyboardButton[]): readonly InlineKeyboardButton[]
```

### defineCallbackNamespace

Validate `namespaceId` at call time (programmer bug on failure → throw) and
bind every action to the namespace id.

```ts
<TActions extends Record<string, AnyCallbackActionDef>>(input: { namespaceId: string; actions: TActions; }): CallbackNamespace<TActions>
```

### createInMemoryPointerStore

A non-durable, non-evicting `PointerStore` backed by a `Map`.

TEST-ONLY: it holds envelopes in process memory with no persistence, no
eviction, and no cross-process visibility. Do NOT use in production — decode
must survive a process restart, which this store does not.

```ts
createInMemoryPointerStore(): PointerStore
```

### toChatId

```ts
toChatId(value: number): IdResult<ChatId>
```

### toMessageId

```ts
toMessageId(value: number): IdResult<MessageId>
```

### nodeText

The rendered plain text of a single node (its leaves concatenated in order).

```ts
nodeText(node: RichTextNode): string
```

### renderedLength

UTF-16 code-unit length of the rendered text (the unit Telegram counts).

```ts
renderedLength(nodes: readonly RichTextNode[]): number
```

### renderPlainText

The rendered plain text of a node sequence.

```ts
renderPlainText(nodes: readonly RichTextNode[]): string
```

### resetDiagnostics

Test-only: clear the dedup set between tests.

```ts
resetDiagnostics(): void
```

### setDiagnosticHook

```ts
setDiagnosticHook(fn: ((e: DiagnosticEvent) => void) | null): void
```

### warnDegraded

```ts
warnDegraded(context: string, detail: string): void
```

### warnNotImplemented

```ts
warnNotImplemented(category: string, detail: string): void
```

### warnUnexpected

```ts
warnUnexpected(context: string, detail: string, data?: Record<string, unknown>): void
```

### createCaptionText

```ts
createCaptionText(nodes: readonly RichTextNode[]): CaptionTextResult
```

### createMessageText

```ts
createMessageText(nodes: readonly RichTextNode[]): MessageTextResult
```

### messageNodes

Read the validated nodes back out of a branded message/caption value.

```ts
messageNodes(message: MessageText | CaptionText): readonly RichTextNode[]
```

### messageText

Read the rendered plain text back out of a branded message/caption value.

```ts
messageText(message: MessageText | CaptionText): string
```

### collapsible

```ts
collapsible(summary: readonly RichTextNode[], children: readonly RichBlockNode[]): CollapsibleBlock
```

### heading

```ts
heading(level: 1 | 2 | 3 | 4, children: readonly RichTextNode[]): HeadingBlock
```

### math

```ts
math(latex: string): MathBlock
```

### table

```ts
table(header: readonly (readonly RichTextNode[])[], rows: readonly (readonly (readonly RichTextNode[])[])[]): TableBlock
```

### parseRichText

```ts
parseRichText(value: unknown): ParseRichTextResult
```

## Types

### GramValue

A value interpolable into a `gram` template.

```ts
type GramValue = RichTextNode | readonly RichTextNode[] | string
```

### Inline

A child accepted by the builders: a node, or a bare string (wrapped as text).

```ts
type Inline = RichTextNode | string
```

### Brand

```ts
type Brand = Brand<T, B>
```

### CallbackActionDef

A declared callback action: id + payload schema + positional field order.

```ts
type CallbackActionDef = CallbackActionDef<TPayload>
```

### CallbackDecodeDeps

Dependencies a decode call needs. `hmacSecrets` is a `[current, ...previous]`
list verified in order so a caller can grace-period a secret rotation;
passing just `[current]` is the simpler valid default.

```ts
type CallbackDecodeDeps = {
  readonly pointerStore: PointerStore;
  readonly hmacSecrets: readonly Uint8Array[];
  readonly now: () => number;
}
```

### CallbackDecodeResult

The six mutually-exclusive outcomes of decoding a `callback_data` string.

```ts
type CallbackDecodeResult = CallbackDecodeResult<TPayload>
```

### CallbackEncodeDeps

Dependencies an encode call needs: store + signing secret + clock + TTL.

```ts
type CallbackEncodeDeps = {
  readonly pointerStore: PointerStore;
  readonly hmacSecret: Uint8Array;
  readonly now: () => number;
  readonly ttlMs: number;
}
```

### CallbackActionId

A short (1-8 char) action id, part of the compact wire format.

```ts
type CallbackActionId = string & z.BRAND<"CallbackActionId">
```

### CallbackNamespaceId

A short (1-4 char) namespace id, part of the compact wire format.

```ts
type CallbackNamespaceId = string & z.BRAND<"CallbackNamespaceId">
```

### CallbackToken

A fixed 22-char base64url (128-bit) pointer-store token.

```ts
type CallbackToken = string & z.BRAND<"CallbackToken">
```

### InlineKeyboardButton

The minimal Bot API inline button shape `core` produces.

```ts
type InlineKeyboardButton = {
  readonly text: string;
  readonly callback_data: string;
}
```

### InlineKeyboardMarkup

A grid of button rows, ready to drop into `reply_markup`.

```ts
type InlineKeyboardMarkup = {
  readonly inline_keyboard: readonly (readonly InlineKeyboardButton[])[];
}
```

### BoundCallbackAction

An action bound to its namespace — self-contained for encoding.

```ts
type BoundCallbackAction = BoundCallbackAction<TPayload>
```

### CallbackNamespace

A compile-time registry of bound actions keyed by declaration name.

```ts
type CallbackNamespace = CallbackNamespace<TActions>
```

### PointerEnvelope

The signed-at-rest record a pointer token resolves to. `notAfter` is embedded
here (not on the wire) and checked post-lookup so a still-resolvable token for
a button that should be considered dead decodes as `expired`, not `ok`.

```ts
type PointerEnvelope = {
  readonly namespaceId: CallbackNamespaceId;
  readonly actionId: CallbackActionId;
  /** `JSON.stringify` of the zod-validated payload. */
  readonly payloadJson: string;
  /** Epoch ms; caller-chosen TTL horizon. */
  readonly notAfter: number;
}
```

### PointerStore

Caller-supplied storage for spillover envelopes. `put` overwrite is a caller
bug (tokens are 128-bit random, collision is cryptographically negligible),
not something the codec guards against.

```ts
type PointerStore = {
  put(token: CallbackToken, envelope: PointerEnvelope): Promise<void>;
  get(token: CallbackToken): Promise<PointerEnvelope | undefined>;
}
```

### ChatId

A Telegram chat identifier (may be negative for groups/channels).

```ts
type ChatId = Brand<number, "ChatId">
```

### IdResult

```ts
type IdResult = IdResult<T>
```

### MessageId

A Telegram message identifier within a chat.

```ts
type MessageId = Brand<number, "MessageId">
```

### DiagnosticKind

Runtime diagnostics — the house alternative to deferred-work comments.

Three functions: `warnNotImplemented`, `warnDegraded`, `warnUnexpected`.
Each fires once per stable key (except `warnUnexpected`, which always fires),
is greppable, and can be piped into a UI panel via {@link setDiagnosticHook}.

Usage:
  warnDegraded("MyModule.fallback", "linear interp — cubic deferred, spec:120-140");
  warnNotImplemented("MyModule.featureX", "spec §4 not yet lowered");
  warnUnexpected("MyModule.parse", "expected number, got string", { value });

```ts
type DiagnosticKind = "not-implemented" | "degraded" | "unexpected"
```

### CaptionTextResult

```ts
type CaptionTextResult = | { kind: "ok"; value: CaptionText }
  | { kind: "too-long"; limit: typeof CAPTION_TEXT_LIMIT; actual: number }
```

### MessageTextResult

```ts
type MessageTextResult = | { kind: "ok"; value: MessageText }
  | { kind: "too-long"; limit: typeof MESSAGE_TEXT_LIMIT; actual: number }
```

### RichBlockNode

```ts
type RichBlockNode = HeadingBlock | MathBlock | TableBlock | CollapsibleBlock
```

### BlockquoteChild

Nodes permitted directly inside a blockquote (excludes both blockquote variants).

```ts
type BlockquoteChild = | TextNode
  | CodeNode
  | PreNode
  | BoldNode
  | ItalicNode
  | UnderlineNode
  | StrikethroughNode
  | SpoilerNode
  | LinkNode
  | MentionNode
```

### MentionTarget

Mention target: by

```ts
type MentionTarget = | { readonly kind: "username"; readonly username: string }
  | { readonly kind: "user-id"; readonly userId: number; readonly label: string }
```

### ParseRichTextResult

```ts
type ParseRichTextResult = | { kind: "ok"; value: RichTextNode[] }
  | { kind: "invalid"; message: string }
```

### PreLanguage

Language tag for a `pre` block, modeled as a discriminated union (no `.optional`).

```ts
type PreLanguage = | { readonly kind: "known"; readonly value: string }
  | { readonly kind: "unknown" }
```

### RichTextNode

```ts
type RichTextNode = | TextNode
  | CodeNode
  | PreNode
  | BoldNode
  | ItalicNode
  | UnderlineNode
  | StrikethroughNode
  | SpoilerNode
  | LinkNode
  | MentionNode
  | BlockquoteNode
  | ExpandableBlockquoteNode
```

## Interfaces

### DiagnosticEvent

```ts
interface DiagnosticEvent
```

- `kind: DiagnosticKind`
- `category: string`
- `detail: string`
- `stack: string`
- `data: Record<string, unknown>`
- `timestamp: number`

### CaptionText

A RichText document proven to fit within the 1024-code-unit caption limit.

```ts
interface CaptionText
```

- `[CAPTION_TEXT_BRAND]: true`
- `nodes: readonly RichTextNode[]`
- `text: string`

### MessageText

A RichText document proven to fit within the 4096-code-unit message limit.

```ts
interface MessageText
```

- `[MESSAGE_TEXT_BRAND]: true`
- `nodes: readonly RichTextNode[]`
- `text: string`

### CollapsibleBlock

```ts
interface CollapsibleBlock
```

- `kind: "collapsible"`
- `summary: readonly RichTextNode[]`
- `children: readonly RichBlockNode[]`

### HeadingBlock

```ts
interface HeadingBlock
```

- `kind: "heading"`
- `level: 1 | 2 | 3 | 4`
- `children: readonly RichTextNode[]`

### MathBlock

```ts
interface MathBlock
```

- `kind: "math"`
- `latex: string`

### TableBlock

```ts
interface TableBlock
```

- `kind: "table"`
- `header: readonly (readonly RichTextNode[])[]`
- `rows: readonly (readonly (readonly RichTextNode[])[])[]`

### BlockquoteNode

```ts
interface BlockquoteNode
```

- `kind: "blockquote"`
- `children: readonly BlockquoteChild[]`

### BoldNode

```ts
interface BoldNode
```

- `kind: "bold"`
- `children: readonly RichTextNode[]`

### CodeNode

```ts
interface CodeNode
```

- `kind: "code"`
- `value: string`

### ExpandableBlockquoteNode

```ts
interface ExpandableBlockquoteNode
```

- `kind: "expandable-blockquote"`
- `children: readonly BlockquoteChild[]`

### ItalicNode

```ts
interface ItalicNode
```

- `kind: "italic"`
- `children: readonly RichTextNode[]`

### LinkNode

```ts
interface LinkNode
```

- `kind: "link"`
- `href: string`
- `children: readonly RichTextNode[]`

### MentionNode

```ts
interface MentionNode
```

- `kind: "mention"`
- `target: MentionTarget`

### PreNode

```ts
interface PreNode
```

- `kind: "pre"`
- `language: PreLanguage`
- `children: readonly TextNode[]`

### SpoilerNode

```ts
interface SpoilerNode
```

- `kind: "spoiler"`
- `children: readonly RichTextNode[]`

### StrikethroughNode

```ts
interface StrikethroughNode
```

- `kind: "strikethrough"`
- `children: readonly RichTextNode[]`

### TextNode

```ts
interface TextNode
```

- `kind: "text"`
- `value: string`

### UnderlineNode

```ts
interface UnderlineNode
```

- `kind: "underline"`
- `children: readonly RichTextNode[]`

## Constants

### CALLBACK_DATA_MAX_BYTES

Hard Bot API ceiling on `callback_data`, in UTF-8 bytes (Bot API 10.1).

```ts
const CALLBACK_DATA_MAX_BYTES: 64
```

### CallbackActionIdSchema

```ts
const CallbackActionIdSchema: z.ZodType<CallbackActionId, z.ZodTypeDef, string>
```

### CallbackNamespaceIdSchema

```ts
const CallbackNamespaceIdSchema: z.ZodType<CallbackNamespaceId, z.ZodTypeDef, string>
```

### CallbackTokenSchema

```ts
const CallbackTokenSchema: z.ZodType<CallbackToken, z.ZodTypeDef, string>
```

### InlineKeyboardButtonSchema

```ts
const InlineKeyboardButtonSchema: z.ZodType<InlineKeyboardButton, z.ZodTypeDef, InlineKeyboardButton>
```

### InlineKeyboardMarkupSchema

```ts
const InlineKeyboardMarkupSchema: z.ZodType<InlineKeyboardMarkup, z.ZodTypeDef, InlineKeyboardMarkup>
```

### CAPTION_TEXT_LIMIT

```ts
const CAPTION_TEXT_LIMIT: 1024
```

### MESSAGE_TEXT_LIMIT

```ts
const MESSAGE_TEXT_LIMIT: 4096
```

### CollapsibleBlockSchema

```ts
const CollapsibleBlockSchema: z.ZodType<CollapsibleBlock, z.ZodTypeDef, CollapsibleBlock>
```

### HeadingBlockSchema

```ts
const HeadingBlockSchema: z.ZodType<HeadingBlock, z.ZodTypeDef, HeadingBlock>
```

### MathBlockSchema

```ts
const MathBlockSchema: z.ZodType<MathBlock, z.ZodTypeDef, MathBlock>
```

### RichBlockNodeSchema

```ts
const RichBlockNodeSchema: z.ZodType<RichBlockNode, z.ZodTypeDef, RichBlockNode>
```

### TableBlockSchema

```ts
const TableBlockSchema: z.ZodType<TableBlock, z.ZodTypeDef, TableBlock>
```

### BlockquoteChildSchema

The blockquote child union: every node kind except the two blockquote variants.

```ts
const BlockquoteChildSchema: z.ZodType<BlockquoteChild, z.ZodTypeDef, BlockquoteChild>
```

### BlockquoteNodeSchema

```ts
const BlockquoteNodeSchema: z.ZodType<BlockquoteNode, z.ZodTypeDef, BlockquoteNode>
```

### BoldNodeSchema

```ts
const BoldNodeSchema: z.ZodType<BoldNode, z.ZodTypeDef, BoldNode>
```

### CodeNodeSchema

```ts
const CodeNodeSchema: z.ZodType<CodeNode, z.ZodTypeDef, CodeNode>
```

### ExpandableBlockquoteNodeSchema

```ts
const ExpandableBlockquoteNodeSchema: z.ZodType<ExpandableBlockquoteNode, z.ZodTypeDef, ExpandableBlockquoteNode>
```

### ItalicNodeSchema

```ts
const ItalicNodeSchema: z.ZodType<ItalicNode, z.ZodTypeDef, ItalicNode>
```

### LinkNodeSchema

```ts
const LinkNodeSchema: z.ZodType<LinkNode, z.ZodTypeDef, LinkNode>
```

### MentionNodeSchema

```ts
const MentionNodeSchema: z.ZodType<MentionNode, z.ZodTypeDef, MentionNode>
```

### PreNodeSchema

```ts
const PreNodeSchema: z.ZodType<PreNode, z.ZodTypeDef, PreNode>
```

### RichTextNodeSchema

```ts
const RichTextNodeSchema: z.ZodType<RichTextNode, z.ZodTypeDef, RichTextNode>
```

### RichTextSchema

```ts
const RichTextSchema: z.ZodType<RichTextNode[], z.ZodTypeDef, RichTextNode[]>
```

### SpoilerNodeSchema

```ts
const SpoilerNodeSchema: z.ZodType<SpoilerNode, z.ZodTypeDef, SpoilerNode>
```

### StrikethroughNodeSchema

```ts
const StrikethroughNodeSchema: z.ZodType<StrikethroughNode, z.ZodTypeDef, StrikethroughNode>
```

### TextNodeSchema

```ts
const TextNodeSchema: z.ZodType<TextNode, z.ZodTypeDef, TextNode>
```

### UnderlineNodeSchema

```ts
const UnderlineNodeSchema: z.ZodType<UnderlineNode, z.ZodTypeDef, UnderlineNode>
```
