ConversionResult
Both functions return plain JSON-serializable data. Receipts can contain private file IDs, so they are not safe for unrestricted logs.
ConversionResult
Returned by convert():
interface ConversionResult {
readonly blocks: ReadonlyArray<Block>;
readonly text: string;
readonly degradations: ReadonlyArray<Degradation>;
readonly receipts: ReadonlyArray<UploadReceipt>;
}| Field | Meaning |
|---|---|
blocks | Block Kit JSON for chat.postMessage's blocks field. At most 50 blocks; default conversion always passes validateBlocks. |
text | Plain-text rendering for the text field (push notifications, accessibility). Never empty; clamped to Slack's 40,000-character threshold. |
degradations | Fallbacks and truncations, in document order. Empty means no fallback was recorded (known gaps for raw block HTML). |
receipts | Immutable external upload effects, including attempts hidden by later renderer success. Sensitive operational data. |
ConversionMessagesResult
Returned by convertToMessages():
interface ConversionMessagesResult {
readonly messages: ReadonlyArray<ConversionMessage>;
readonly degradations: ReadonlyArray<Degradation>;
readonly receipts: ReadonlyArray<UploadReceipt>;
}
interface ConversionMessage {
readonly blocks: ReadonlyArray<Block>;
readonly text: string;
}Each message is independently postable with its own notification text;
degradations covers the whole conversion. Without overflow: "split" the
array always has exactly one entry.
Degradation
interface Degradation {
readonly nodeType: string;
readonly from: string;
readonly to: string;
readonly reason: string;
readonly path: string;
readonly details?: {
readonly code?: string;
readonly stage?: string;
readonly retryable?: boolean;
readonly rendererId?: string;
};
}| Field | Contents |
|---|---|
nodeType | Markdown node or subsystem that degraded: "heading", "table", "code.mermaid", "message", … |
from | What was attempted: a block form ("header.h5"), a size ("63 body blocks"), or a source value |
to | What was emitted instead: "rich_text.bold", "data_table", "truncated", "omitted", … |
reason | Human-readable explanation, including the limit that applied |
path | Position in the source document. "root[2]" is the third top-level node; "assemble" marks message-level packing |
details | Optional safe renderer metadata; absent for ordinary structural fallbacks |
A level-5 heading, for example (Slack headers stop at 4):
{
"nodeType": "heading",
"from": "header.h5",
"to": "rich_text.bold",
"reason": "Heading level 5 exceeds max 4",
"path": "root[0]"
}Treat reason as display text, not a parseable format.
UploadReceipt
interface UploadReceipt {
readonly kind: "upload";
readonly provider: string;
readonly rendererId?: string;
readonly filename?: string;
readonly phase: "requested" | "allocated" | "uploaded" | "completed" | "shared" | "unknown";
readonly fileId?: string;
readonly shared: boolean;
readonly processing: "not-requested" | "pending" | "verified" | "unverified";
readonly status?: number;
readonly retryAfterMs?: number;
readonly providerCode?: string;
readonly retrySafety: "never" | "safe" | "may-duplicate";
}Receipts are independent from content fallback and survive later renderer success, fallback, and typed errors when known.
Prompt operation/shutdown errors carry a frozen receipts snapshot and a non-rejecting
settledReceipts promise tied to that operation. It resolves after underlying
collaborators settle and may remain pending forever for a never-settling collaborator.
Block
blocks entries are typed by the exported Block union (rich_text,
header, section, image, context, divider, markdown, table,
data_table, data_visualization, and container), matching Slack's wire
format field-for-field. All block and rich text element types are exported for
use in your own code (RichTextBlock, TableBlock, RichTextInline, …).