perf: slim slack provider helper tests

This commit is contained in:
Peter Steinberger
2026-04-23 20:35:34 +01:00
parent f40f8a60cc
commit fd581b849d
6 changed files with 291 additions and 262 deletions

View File

@@ -0,0 +1,244 @@
import type { SlackChannelResolution } from "../resolve-channels.js";
import type { SlackUserResolution } from "../resolve-users.js";
import { formatUnknownError, waitForSlackSocketDisconnect } from "./reconnect-policy.js";
type SlackAppConstructor = typeof import("@slack/bolt").App;
type SlackHttpReceiverConstructor = typeof import("@slack/bolt").HTTPReceiver;
type SlackSocketModeReceiverConstructor = typeof import("@slack/bolt").SocketModeReceiver;
export type SlackBoltResolvedExports = {
App: SlackAppConstructor;
HTTPReceiver: SlackHttpReceiverConstructor;
SocketModeReceiver: SlackSocketModeReceiverConstructor;
};
type SlackSocketShutdownClient = {
shuttingDown?: boolean;
};
type Constructor = abstract new (...args: never[]) => unknown;
function isConstructorFunction<
// oxlint-disable-next-line typescript/no-unnecessary-type-parameters -- Constructor guard preserves the requested concrete Slack constructor type.
T extends Constructor,
>(value: unknown): value is T {
return typeof value === "function";
}
function resolveSlackBoltModule(value: unknown): SlackBoltResolvedExports | null {
if (!value || typeof value !== "object") {
return null;
}
const app = Reflect.get(value, "App");
const httpReceiver = Reflect.get(value, "HTTPReceiver");
const socketModeReceiver = Reflect.get(value, "SocketModeReceiver");
if (
!isConstructorFunction<SlackAppConstructor>(app) ||
!isConstructorFunction<SlackHttpReceiverConstructor>(httpReceiver) ||
!isConstructorFunction<SlackSocketModeReceiverConstructor>(socketModeReceiver)
) {
return null;
}
return {
App: app,
HTTPReceiver: httpReceiver,
SocketModeReceiver: socketModeReceiver,
};
}
export function resolveSlackBoltInterop(params: {
defaultImport: unknown;
namespaceImport: unknown;
}): SlackBoltResolvedExports {
const { defaultImport, namespaceImport } = params;
const nestedDefault =
defaultImport && typeof defaultImport === "object"
? Reflect.get(defaultImport, "default")
: undefined;
const namespaceDefault =
namespaceImport && typeof namespaceImport === "object"
? Reflect.get(namespaceImport, "default")
: undefined;
const namespaceReceiver =
namespaceImport && typeof namespaceImport === "object"
? Reflect.get(namespaceImport, "HTTPReceiver")
: undefined;
const namespaceSocketModeReceiver =
namespaceImport && typeof namespaceImport === "object"
? Reflect.get(namespaceImport, "SocketModeReceiver")
: undefined;
const directModule =
resolveSlackBoltModule(defaultImport) ??
resolveSlackBoltModule(nestedDefault) ??
resolveSlackBoltModule(namespaceDefault) ??
resolveSlackBoltModule(namespaceImport);
if (directModule) {
return directModule;
}
if (
isConstructorFunction<SlackAppConstructor>(defaultImport) &&
isConstructorFunction<SlackHttpReceiverConstructor>(namespaceReceiver) &&
isConstructorFunction<SlackSocketModeReceiverConstructor>(namespaceSocketModeReceiver)
) {
return {
App: defaultImport,
HTTPReceiver: namespaceReceiver,
SocketModeReceiver: namespaceSocketModeReceiver,
};
}
throw new TypeError("Unable to resolve @slack/bolt App/HTTPReceiver exports");
}
export function publishSlackConnectedStatus(setStatus?: (next: Record<string, unknown>) => void) {
if (!setStatus) {
return;
}
const now = Date.now();
setStatus({
connected: true,
lastConnectedAt: now,
healthState: "healthy",
lastError: null,
});
}
export function publishSlackDisconnectedStatus(
setStatus?: (next: Record<string, unknown>) => void,
error?: unknown,
) {
if (!setStatus) {
return;
}
const at = Date.now();
const message = error ? formatUnknownError(error) : undefined;
setStatus({
connected: false,
healthState: "disconnected",
lastDisconnect: message ? { at, error: message } : { at },
lastError: message ?? null,
});
}
export function createSlackBoltApp(params: {
interop: SlackBoltResolvedExports;
slackMode: "socket" | "http";
botToken: string;
appToken?: string;
signingSecret?: string;
slackWebhookPath: string;
clientOptions: Record<string, unknown>;
}) {
const receiver =
params.slackMode === "socket"
? new params.interop.SocketModeReceiver({
appToken: params.appToken ?? "",
autoReconnectEnabled: false,
installerOptions: {
clientOptions: params.clientOptions,
},
})
: new params.interop.HTTPReceiver({
signingSecret: params.signingSecret ?? "",
endpoints: params.slackWebhookPath,
});
const app = new params.interop.App({
token: params.botToken,
receiver,
clientOptions: params.clientOptions,
});
return { app, receiver };
}
export function createSlackSocketDisconnectWaiter(app: unknown, abortSignal?: AbortSignal) {
const waiterAbortController = new AbortController();
const relayAbort = () => waiterAbortController.abort();
abortSignal?.addEventListener("abort", relayAbort, { once: true });
return {
promise: waitForSlackSocketDisconnect(app, waiterAbortController.signal),
cancel: () => {
waiterAbortController.abort();
abortSignal?.removeEventListener("abort", relayAbort);
},
complete: () => {
abortSignal?.removeEventListener("abort", relayAbort);
},
};
}
export async function startSlackSocketAndWaitForDisconnect(params: {
app: { start: () => unknown };
abortSignal?: AbortSignal;
onStarted?: () => void;
}) {
const disconnectWaiter = createSlackSocketDisconnectWaiter(params.app, params.abortSignal);
try {
await Promise.resolve(params.app.start());
if (params.abortSignal?.aborted) {
disconnectWaiter.cancel();
return null;
}
params.onStarted?.();
const disconnect = await disconnectWaiter.promise;
disconnectWaiter.complete();
return disconnect;
} catch (err) {
disconnectWaiter.cancel();
throw err;
}
}
export function resolveSlackSocketShutdownClient(
app: unknown,
): SlackSocketShutdownClient | undefined {
if (!app || typeof app !== "object") {
return undefined;
}
const receiver = Reflect.get(app, "receiver");
if (!receiver || typeof receiver !== "object") {
return undefined;
}
const client = Reflect.get(receiver, "client");
if (!client || typeof client !== "object") {
return undefined;
}
return client as SlackSocketShutdownClient;
}
export async function gracefulStopSlackApp(app: { stop: () => unknown }) {
const socketClient = resolveSlackSocketShutdownClient(app);
if (socketClient) {
socketClient.shuttingDown = true;
}
await Promise.resolve(app.stop()).catch(() => undefined);
}
function formatSlackResolvedLabel(params: {
input: string;
id: string;
name?: string;
extra?: string[];
}): string {
const extras = params.extra?.filter(Boolean) ?? [];
const suffix =
extras.length > 0 ? ` (id:${params.id}, ${extras.join(", ")})` : ` (id:${params.id})`;
return `${params.input}${params.name ?? params.id}${suffix}`;
}
export function formatSlackChannelResolved(entry: SlackChannelResolution): string {
const id = entry.id ?? entry.input;
return formatSlackResolvedLabel({
input: entry.input,
id,
name: entry.name,
extra: entry.archived ? ["archived"] : [],
});
}
export function formatSlackUserResolved(entry: SlackUserResolution): string {
const id = entry.id ?? entry.input;
return formatSlackResolvedLabel({
input: entry.input,
id,
name: entry.name,
extra: entry.note ? [entry.note] : [],
});
}

View File

@@ -1,10 +1,10 @@
import { describe, expect, it } from "vitest";
import { __testing } from "./provider.js";
import { formatSlackChannelResolved, formatSlackUserResolved } from "./provider-support.js";
describe("slack allowlist log formatting", () => {
it("prints channel names alongside ids", () => {
expect(
__testing.formatSlackChannelResolved({
formatSlackChannelResolved({
input: "C0AQXEG6QFJ",
resolved: true,
id: "C0AQXEG6QFJ",
@@ -15,7 +15,7 @@ describe("slack allowlist log formatting", () => {
it("prints user names alongside ids", () => {
expect(
__testing.formatSlackUserResolved({
formatSlackUserResolved({
input: "U090HHQ029J",
resolved: true,
id: "U090HHQ029J",

View File

@@ -1,5 +1,5 @@
import { describe, it, expect } from "vitest";
import { isNonRecoverableSlackAuthError } from "./provider.js";
import { isNonRecoverableSlackAuthError } from "./reconnect-policy.js";
describe("isNonRecoverableSlackAuthError", () => {
it.each([

View File

@@ -1,5 +1,5 @@
import { describe, expect, it } from "vitest";
import { __testing } from "./provider.js";
import { createSlackBoltApp, resolveSlackBoltInterop } from "./provider-support.js";
describe("resolveSlackBoltInterop", () => {
function FakeApp() {}
@@ -7,7 +7,7 @@ describe("resolveSlackBoltInterop", () => {
function FakeSocketModeReceiver() {}
it("uses the default import when it already exposes named exports", () => {
const resolved = __testing.resolveSlackBoltInterop({
const resolved = resolveSlackBoltInterop({
defaultImport: {
App: FakeApp,
HTTPReceiver: FakeHTTPReceiver,
@@ -24,7 +24,7 @@ describe("resolveSlackBoltInterop", () => {
});
it("uses nested default export when the default import is a wrapper object", () => {
const resolved = __testing.resolveSlackBoltInterop({
const resolved = resolveSlackBoltInterop({
defaultImport: {
default: {
App: FakeApp,
@@ -43,7 +43,7 @@ describe("resolveSlackBoltInterop", () => {
});
it("uses the namespace receiver when the default import is the App constructor itself", () => {
const resolved = __testing.resolveSlackBoltInterop({
const resolved = resolveSlackBoltInterop({
defaultImport: FakeApp,
namespaceImport: {
HTTPReceiver: FakeHTTPReceiver,
@@ -59,7 +59,7 @@ describe("resolveSlackBoltInterop", () => {
});
it("uses namespace.default when it exposes named exports", () => {
const resolved = __testing.resolveSlackBoltInterop({
const resolved = resolveSlackBoltInterop({
defaultImport: undefined,
namespaceImport: {
default: {
@@ -78,7 +78,7 @@ describe("resolveSlackBoltInterop", () => {
});
it("falls back to the namespace import when it exposes named exports", () => {
const resolved = __testing.resolveSlackBoltInterop({
const resolved = resolveSlackBoltInterop({
defaultImport: undefined,
namespaceImport: {
App: FakeApp,
@@ -96,7 +96,7 @@ describe("resolveSlackBoltInterop", () => {
it("throws when the module cannot be resolved", () => {
expect(() =>
__testing.resolveSlackBoltInterop({
resolveSlackBoltInterop({
defaultImport: null,
namespaceImport: {},
}),
@@ -131,7 +131,7 @@ describe("createSlackBoltApp", () => {
it("uses SocketModeReceiver with OpenClaw-owned reconnects and shared client options", () => {
const clientOptions = { teamId: "T1" };
const { app, receiver } = __testing.createSlackBoltApp({
const { app, receiver } = createSlackBoltApp({
interop: {
App: FakeApp as never,
HTTPReceiver: FakeHTTPReceiver as never,
@@ -162,7 +162,7 @@ describe("createSlackBoltApp", () => {
it("uses HTTPReceiver for webhook mode", () => {
const clientOptions = { teamId: "T1" };
const { app, receiver } = __testing.createSlackBoltApp({
const { app, receiver } = createSlackBoltApp({
interop: {
App: FakeApp as never,
HTTPReceiver: FakeHTTPReceiver as never,

View File

@@ -1,5 +1,11 @@
import { describe, expect, it, vi } from "vitest";
import { __testing } from "./provider.js";
import {
gracefulStopSlackApp,
publishSlackConnectedStatus,
publishSlackDisconnectedStatus,
startSlackSocketAndWaitForDisconnect,
} from "./provider-support.js";
import { waitForSlackSocketDisconnect } from "./reconnect-policy.js";
class FakeEmitter {
private listeners = new Map<string, Set<(...args: unknown[]) => void>>();
@@ -29,7 +35,7 @@ describe("slack socket reconnect helpers", () => {
it("marks socket mode healthy without seeding event liveness on connect", () => {
const setStatus = vi.fn();
__testing.publishSlackConnectedStatus(setStatus);
publishSlackConnectedStatus(setStatus);
expect(setStatus).toHaveBeenCalledTimes(1);
expect(setStatus).toHaveBeenCalledWith(
@@ -49,7 +55,7 @@ describe("slack socket reconnect helpers", () => {
const setStatus = vi.fn();
const err = new Error("dns down");
__testing.publishSlackDisconnectedStatus(setStatus, err);
publishSlackDisconnectedStatus(setStatus, err);
expect(setStatus).toHaveBeenCalledTimes(1);
expect(setStatus).toHaveBeenCalledWith({
@@ -66,7 +72,7 @@ describe("slack socket reconnect helpers", () => {
it("marks socket mode disconnected without error when the socket closes cleanly", () => {
const setStatus = vi.fn();
__testing.publishSlackDisconnectedStatus(setStatus);
publishSlackDisconnectedStatus(setStatus);
expect(setStatus).toHaveBeenCalledTimes(1);
expect(setStatus).toHaveBeenCalledWith({
@@ -83,7 +89,7 @@ describe("slack socket reconnect helpers", () => {
const client = new FakeEmitter();
const app = { receiver: { client } };
const waiter = __testing.waitForSlackSocketDisconnect(app as never);
const waiter = waitForSlackSocketDisconnect(app as never);
client.emit("disconnected");
await expect(waiter).resolves.toEqual({ event: "disconnect" });
@@ -94,7 +100,7 @@ describe("slack socket reconnect helpers", () => {
const app = { receiver: { client } };
const err = new Error("dns down");
const waiter = __testing.waitForSlackSocketDisconnect(app as never);
const waiter = waitForSlackSocketDisconnect(app as never);
client.emit("error", err);
await expect(waiter).resolves.toEqual({ event: "error", error: err });
@@ -111,7 +117,7 @@ describe("slack socket reconnect helpers", () => {
const onStarted = vi.fn();
await expect(
__testing.startSlackSocketAndWaitForDisconnect({
startSlackSocketAndWaitForDisconnect({
app: app as never,
onStarted,
}),
@@ -130,7 +136,7 @@ describe("slack socket reconnect helpers", () => {
const err = new Error("status sink failed");
await expect(
__testing.startSlackSocketAndWaitForDisconnect({
startSlackSocketAndWaitForDisconnect({
app: app as never,
onStarted: () => {
throw err;
@@ -148,7 +154,7 @@ describe("slack socket reconnect helpers", () => {
const app = { receiver: { client } };
const err = new Error("invalid_auth");
const waiter = __testing.waitForSlackSocketDisconnect(app as never);
const waiter = waitForSlackSocketDisconnect(app as never);
client.emit("unable_to_socket_mode_start", err);
await expect(waiter).resolves.toEqual({
@@ -165,7 +171,7 @@ describe("slack socket reconnect helpers", () => {
}),
};
await __testing.gracefulStopSlackApp(app);
await gracefulStopSlackApp(app);
expect(app.stop).toHaveBeenCalledTimes(1);
expect(app.receiver.client.shuttingDown).toBe(true);

View File

@@ -27,8 +27,8 @@ import { resolveSlackWebClientOptions } from "../client.js";
import { isSlackExecApprovalClientEnabled } from "../exec-approvals.js";
import { normalizeSlackWebhookPath, registerSlackHttpHandler } from "../http/index.js";
import { SLACK_TEXT_LIMIT } from "../limits.js";
import { resolveSlackChannelAllowlist, type SlackChannelResolution } from "../resolve-channels.js";
import { resolveSlackUserAllowlist, type SlackUserResolution } from "../resolve-users.js";
import { resolveSlackChannelAllowlist } from "../resolve-channels.js";
import { resolveSlackUserAllowlist } from "../resolve-users.js";
import { resolveSlackAppToken, resolveSlackBotToken } from "../token.js";
import { normalizeAllowList } from "./allow-list.js";
import { resolveSlackSlashCommandConfig } from "./commands.js";
@@ -42,6 +42,19 @@ import {
import { createSlackMonitorContext } from "./context.js";
import { registerSlackMonitorEvents } from "./events.js";
import { createSlackMessageHandler } from "./message-handler.js";
import {
createSlackBoltApp,
createSlackSocketDisconnectWaiter,
formatSlackChannelResolved,
formatSlackUserResolved,
gracefulStopSlackApp,
publishSlackConnectedStatus,
publishSlackDisconnectedStatus,
resolveSlackBoltInterop,
resolveSlackSocketShutdownClient,
startSlackSocketAndWaitForDisconnect,
type SlackBoltResolvedExports,
} from "./provider-support.js";
import {
formatUnknownError,
getSocketEmitter,
@@ -53,90 +66,6 @@ import { resolveTextChunkLimit } from "./reply.runtime.js";
import { registerSlackMonitorSlashCommands } from "./slash.js";
import type { MonitorSlackOpts } from "./types.js";
type SlackAppConstructor = typeof import("@slack/bolt").App;
type SlackHttpReceiverConstructor = typeof import("@slack/bolt").HTTPReceiver;
type SlackSocketModeReceiverConstructor = typeof import("@slack/bolt").SocketModeReceiver;
type SlackBoltResolvedExports = {
App: SlackAppConstructor;
HTTPReceiver: SlackHttpReceiverConstructor;
SocketModeReceiver: SlackSocketModeReceiverConstructor;
};
type SlackSocketShutdownClient = {
shuttingDown?: boolean;
};
type Constructor = abstract new (...args: never[]) => unknown;
function isConstructorFunction<
// oxlint-disable-next-line typescript/no-unnecessary-type-parameters -- Constructor guard preserves the requested concrete Slack constructor type.
T extends Constructor,
>(value: unknown): value is T {
return typeof value === "function";
}
function resolveSlackBoltModule(value: unknown): SlackBoltResolvedExports | null {
if (!value || typeof value !== "object") {
return null;
}
const app = Reflect.get(value, "App");
const httpReceiver = Reflect.get(value, "HTTPReceiver");
const socketModeReceiver = Reflect.get(value, "SocketModeReceiver");
if (
!isConstructorFunction<SlackAppConstructor>(app) ||
!isConstructorFunction<SlackHttpReceiverConstructor>(httpReceiver) ||
!isConstructorFunction<SlackSocketModeReceiverConstructor>(socketModeReceiver)
) {
return null;
}
return {
App: app,
HTTPReceiver: httpReceiver,
SocketModeReceiver: socketModeReceiver,
};
}
function resolveSlackBoltInterop(params: {
defaultImport: unknown;
namespaceImport: unknown;
}): SlackBoltResolvedExports {
const { defaultImport, namespaceImport } = params;
const nestedDefault =
defaultImport && typeof defaultImport === "object"
? Reflect.get(defaultImport, "default")
: undefined;
const namespaceDefault =
namespaceImport && typeof namespaceImport === "object"
? Reflect.get(namespaceImport, "default")
: undefined;
const namespaceReceiver =
namespaceImport && typeof namespaceImport === "object"
? Reflect.get(namespaceImport, "HTTPReceiver")
: undefined;
const namespaceSocketModeReceiver =
namespaceImport && typeof namespaceImport === "object"
? Reflect.get(namespaceImport, "SocketModeReceiver")
: undefined;
const directModule =
resolveSlackBoltModule(defaultImport) ??
resolveSlackBoltModule(nestedDefault) ??
resolveSlackBoltModule(namespaceDefault) ??
resolveSlackBoltModule(namespaceImport);
if (directModule) {
return directModule;
}
if (
isConstructorFunction<SlackAppConstructor>(defaultImport) &&
isConstructorFunction<SlackHttpReceiverConstructor>(namespaceReceiver) &&
isConstructorFunction<SlackSocketModeReceiverConstructor>(namespaceSocketModeReceiver)
) {
return {
App: defaultImport,
HTTPReceiver: namespaceReceiver,
SocketModeReceiver: namespaceSocketModeReceiver,
};
}
throw new TypeError("Unable to resolve @slack/bolt App/HTTPReceiver exports");
}
let slackBoltInterop: SlackBoltResolvedExports | undefined;
function getSlackBoltInterop(): SlackBoltResolvedExports {
@@ -161,158 +90,6 @@ function parseApiAppIdFromAppToken(raw?: string) {
return match?.[1]?.toUpperCase();
}
function publishSlackConnectedStatus(setStatus?: (next: Record<string, unknown>) => void) {
if (!setStatus) {
return;
}
const now = Date.now();
setStatus({
connected: true,
lastConnectedAt: now,
healthState: "healthy",
lastError: null,
});
}
function publishSlackDisconnectedStatus(
setStatus?: (next: Record<string, unknown>) => void,
error?: unknown,
) {
if (!setStatus) {
return;
}
const at = Date.now();
const message = error ? formatUnknownError(error) : undefined;
setStatus({
connected: false,
healthState: "disconnected",
lastDisconnect: message ? { at, error: message } : { at },
lastError: message ?? null,
});
}
function createSlackBoltApp(params: {
interop: SlackBoltResolvedExports;
slackMode: "socket" | "http";
botToken: string;
appToken?: string;
signingSecret?: string;
slackWebhookPath: string;
clientOptions: Record<string, unknown>;
}) {
const receiver =
params.slackMode === "socket"
? new params.interop.SocketModeReceiver({
appToken: params.appToken ?? "",
autoReconnectEnabled: false,
installerOptions: {
clientOptions: params.clientOptions,
},
})
: new params.interop.HTTPReceiver({
signingSecret: params.signingSecret ?? "",
endpoints: params.slackWebhookPath,
});
const app = new params.interop.App({
token: params.botToken,
receiver,
clientOptions: params.clientOptions,
});
return { app, receiver };
}
function createSlackSocketDisconnectWaiter(app: unknown, abortSignal?: AbortSignal) {
const waiterAbortController = new AbortController();
const relayAbort = () => waiterAbortController.abort();
abortSignal?.addEventListener("abort", relayAbort, { once: true });
return {
promise: waitForSlackSocketDisconnect(app, waiterAbortController.signal),
cancel: () => {
waiterAbortController.abort();
abortSignal?.removeEventListener("abort", relayAbort);
},
complete: () => {
abortSignal?.removeEventListener("abort", relayAbort);
},
};
}
async function startSlackSocketAndWaitForDisconnect(params: {
app: { start: () => unknown };
abortSignal?: AbortSignal;
onStarted?: () => void;
}) {
const disconnectWaiter = createSlackSocketDisconnectWaiter(params.app, params.abortSignal);
try {
await Promise.resolve(params.app.start());
if (params.abortSignal?.aborted) {
disconnectWaiter.cancel();
return null;
}
params.onStarted?.();
const disconnect = await disconnectWaiter.promise;
disconnectWaiter.complete();
return disconnect;
} catch (err) {
disconnectWaiter.cancel();
throw err;
}
}
function resolveSlackSocketShutdownClient(app: unknown): SlackSocketShutdownClient | undefined {
if (!app || typeof app !== "object") {
return undefined;
}
const receiver = Reflect.get(app, "receiver");
if (!receiver || typeof receiver !== "object") {
return undefined;
}
const client = Reflect.get(receiver, "client");
if (!client || typeof client !== "object") {
return undefined;
}
return client as SlackSocketShutdownClient;
}
async function gracefulStopSlackApp(app: { stop: () => unknown }) {
const socketClient = resolveSlackSocketShutdownClient(app);
if (socketClient) {
socketClient.shuttingDown = true;
}
await Promise.resolve(app.stop()).catch(() => undefined);
}
function formatSlackResolvedLabel(params: {
input: string;
id: string;
name?: string;
extra?: string[];
}): string {
const extras = params.extra?.filter(Boolean) ?? [];
const suffix =
extras.length > 0 ? ` (id:${params.id}, ${extras.join(", ")})` : ` (id:${params.id})`;
return `${params.input}${params.name ?? params.id}${suffix}`;
}
function formatSlackChannelResolved(entry: SlackChannelResolution): string {
const id = entry.id ?? entry.input;
return formatSlackResolvedLabel({
input: entry.input,
id,
name: entry.name,
extra: entry.archived ? ["archived"] : [],
});
}
function formatSlackUserResolved(entry: SlackUserResolution): string {
const id = entry.id ?? entry.input;
return formatSlackResolvedLabel({
input: entry.input,
id,
name: entry.name,
extra: entry.note ? [entry.note] : [],
});
}
export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
const cfg = opts.config ?? loadConfig();
const runtime: RuntimeEnv = opts.runtime ?? createNonExitingRuntime();
@@ -428,7 +205,9 @@ export async function monitorSlackProvider(opts: MonitorSlackOpts = {}) {
const slackHttpHandler =
slackMode === "http" && receiver
? async (req: IncomingMessage, res: ServerResponse) => {
const httpReceiver = receiver as InstanceType<SlackHttpReceiverConstructor>;
const httpReceiver = receiver as {
requestListener: (req: IncomingMessage, res: ServerResponse) => unknown;
};
const guard = installRequestBodyLimitGuard(req, res, {
maxBytes: SLACK_WEBHOOK_MAX_BODY_BYTES,
timeoutMs: SLACK_WEBHOOK_BODY_TIMEOUT_MS,