codeflash-internal/js/cf-api/github/slack_util.ts
Kevin Turcios d7a8b8f227
perf: fix CI build + lazy-load heavy libs + parallelize DB queries (#2601)
## Summary
- **Fix CI build failure**: Auth0Client crashes during Next.js
prerendering when env vars aren't set. Returns a no-op stub (`getSession
→ null`) when domain is missing — semantically correct for static
generation
- **Lazy-load markdown libs (~260kb)**: ReactMarkdown, remarkGfm, and
react-syntax-highlighter were eagerly imported in monaco-diff-viewer but
only rendered when user expands "Generated Tests". Extracted into a
dynamic component
- **Parallelize repo detail query**: `getRepositoryById` ran the
activity count sequentially after the repo lookup. Since `repoId` is
already available, all three queries now run in parallel

## Test plan
- [ ] CI `build` check passes (was failing since #2598)
- [ ] Trace page still renders generated tests correctly when expanded
- [ ] Repository detail page loads correctly with activity status
2026-04-13 11:03:05 -05:00

115 lines
3.3 KiB
TypeScript

import { WebClient, ChatPostMessageArguments } from "@slack/web-api"
// Dependencies interface for easier testing
export interface SendSlackMessageDependencies {
WebClient: typeof WebClient
getSlackToken: () => string | undefined
getSlackChannelId: () => string | undefined
console: typeof console
}
// Default dependencies
let dependencies: SendSlackMessageDependencies = {
WebClient,
getSlackToken: () => process.env.SLACK_TOKEN,
getSlackChannelId: () => process.env.SLACK_CHANNEL_ID,
console,
}
// For testing - allow dependency injection
export function setSendSlackMessageDependencies(deps: Partial<SendSlackMessageDependencies>) {
dependencies = { ...dependencies, ...deps }
}
export function resetSendSlackMessageDependencies() {
dependencies = {
WebClient,
getSlackToken: () => process.env.SLACK_TOKEN,
getSlackChannelId: () => process.env.SLACK_CHANNEL_ID,
console,
}
}
// Initialize web client
let web: WebClient | null = null
export function initializeWebClient() {
const SLACK_TOKEN = dependencies.getSlackToken()
const SLACK_CHANNEL_ID = dependencies.getSlackChannelId()
if (!SLACK_TOKEN) {
throw new Error("Missing SLACK_TOKEN")
}
if (!SLACK_CHANNEL_ID) {
throw new Error("Missing SLACK_CHANNEL_ID")
}
web ||= new dependencies.WebClient(SLACK_TOKEN, {})
return web
}
// For testing - allow resetting the web client
export function resetWebClient() {
web = null
}
/**
* Send a message to Slack
*
* @param {string|object} message - Text message or Block Kit message object
* @param {string|null} channel - Channel ID, defaults to SLACK_CHANNEL_ID
* @param {boolean} returnData - Whether to return the full Slack API response
* @returns {Promise<boolean|object>} - True or API response
*/
export const sendSlackMessage = async (
message: any,
channel: string | null = null,
returnData: boolean = false,
): Promise<boolean | object> =>
await new Promise(async (resolve, reject) => {
try {
const webClient = initializeWebClient()
const SLACK_CHANNEL_ID = dependencies.getSlackChannelId()
const channelId = channel || SLACK_CHANNEL_ID
// Configure the message payload depending on the input type
let payload: ChatPostMessageArguments
if (typeof message === "string") {
payload = {
channel: channelId,
text: message,
}
} else if (message && typeof message === "object") {
if (message.blocks) {
payload = {
channel: channelId,
text: message.text || "Notification from CodeFlash",
blocks: message.blocks,
}
} else {
dependencies.console.warn("Object passed to sendSlackMessage without blocks property")
payload = {
channel: channelId,
text: JSON.stringify(message),
}
}
} else {
dependencies.console.error("Invalid message type", typeof message)
payload = {
channel: channelId,
text: "Invalid message",
}
}
// console.log("Sending payload to Slack:", JSON.stringify(payload, null, 2));
const resp = await webClient.chat.postMessage(payload)
resolve(returnData ? resp : true)
} catch (error) {
dependencies.console.error("Error sending Slack message:", error)
resolve(returnData ? { error } : true)
}
})