kaneo (minimalist kanban) fork to experiment adding a tangled integration
github.com/usekaneo/kaneo
1export type SlackTextObject = {
2 type: "mrkdwn" | "plain_text";
3 text: string;
4};
5
6export type SlackBlock =
7 | {
8 type: "section";
9 text: SlackTextObject;
10 fields?: SlackTextObject[];
11 }
12 | {
13 type: "context";
14 elements: SlackTextObject[];
15 };
16
17export type SlackMessage = {
18 text: string;
19 blocks?: SlackBlock[];
20};
21
22const SLACK_TIMEOUT_MS = 10_000;
23
24export async function postToSlack(
25 webhookUrl: string,
26 message: SlackMessage,
27): Promise<void> {
28 const controller = new AbortController();
29 const timeoutId = setTimeout(() => controller.abort(), SLACK_TIMEOUT_MS);
30
31 try {
32 const response = await fetch(webhookUrl, {
33 method: "POST",
34 headers: {
35 "Content-Type": "application/json",
36 },
37 body: JSON.stringify(message),
38 signal: controller.signal,
39 });
40
41 if (!response.ok) {
42 const errorText = await response.text();
43 throw new Error(
44 `Slack webhook request failed (${response.status}): ${errorText}`,
45 );
46 }
47 } catch (error) {
48 if (error instanceof Error && error.name === "AbortError") {
49 throw new Error(
50 `Slack webhook request timed out after ${SLACK_TIMEOUT_MS}ms`,
51 );
52 }
53
54 throw error;
55 } finally {
56 clearTimeout(timeoutId);
57 }
58}