@vercel/slack-bolt 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +39 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +39 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -122,7 +122,7 @@ declare class VercelReceiver implements Receiver {
|
|
|
122
122
|
private handleSlackEvent;
|
|
123
123
|
private verifyRequest;
|
|
124
124
|
private createSlackReceiverEvent;
|
|
125
|
-
|
|
125
|
+
handleError(error: unknown): Response;
|
|
126
126
|
private createScopedLogger;
|
|
127
127
|
}
|
|
128
128
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -122,7 +122,7 @@ declare class VercelReceiver implements Receiver {
|
|
|
122
122
|
private handleSlackEvent;
|
|
123
123
|
private verifyRequest;
|
|
124
124
|
private createSlackReceiverEvent;
|
|
125
|
-
|
|
125
|
+
handleError(error: unknown): Response;
|
|
126
126
|
private createScopedLogger;
|
|
127
127
|
}
|
|
128
128
|
/**
|
package/dist/index.js
CHANGED
|
@@ -82,11 +82,12 @@ var RequestParsingError = class extends VercelReceiverError {
|
|
|
82
82
|
}
|
|
83
83
|
};
|
|
84
84
|
function getStatusCode(error) {
|
|
85
|
+
var _a;
|
|
85
86
|
if (error instanceof VercelReceiverError) {
|
|
86
87
|
return error.statusCode;
|
|
87
88
|
}
|
|
88
|
-
if (error && typeof error === "object"
|
|
89
|
-
const errorName =
|
|
89
|
+
if (error && typeof error === "object") {
|
|
90
|
+
const errorName = ((_a = error.constructor) == null ? void 0 : _a.name) || error.name;
|
|
90
91
|
switch (errorName) {
|
|
91
92
|
case "ReceiverAuthenticityError":
|
|
92
93
|
return 401;
|
|
@@ -109,8 +110,11 @@ function getErrorMessage(error) {
|
|
|
109
110
|
return ERROR_MESSAGES.INTERNAL_SERVER_ERROR;
|
|
110
111
|
}
|
|
111
112
|
function getErrorType(error) {
|
|
112
|
-
|
|
113
|
-
|
|
113
|
+
var _a, _b;
|
|
114
|
+
if (error && typeof error === "object") {
|
|
115
|
+
const ctorName = (_a = error.constructor) == null ? void 0 : _a.name;
|
|
116
|
+
const nameProp = error.name;
|
|
117
|
+
const errorName = (_b = ctorName != null ? ctorName : nameProp) != null ? _b : ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;
|
|
114
118
|
return errorName === "Error" ? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR : errorName;
|
|
115
119
|
}
|
|
116
120
|
return ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;
|
|
@@ -303,7 +307,11 @@ var VercelReceiver = class {
|
|
|
303
307
|
ack: ackFn,
|
|
304
308
|
request: req
|
|
305
309
|
});
|
|
306
|
-
functions.waitUntil(
|
|
310
|
+
functions.waitUntil(
|
|
311
|
+
this.app.processEvent(event).catch((error) => {
|
|
312
|
+
return this.handleError(error);
|
|
313
|
+
})
|
|
314
|
+
);
|
|
307
315
|
try {
|
|
308
316
|
return yield responsePromise;
|
|
309
317
|
} catch (error) {
|
|
@@ -324,15 +332,21 @@ var VercelReceiver = class {
|
|
|
324
332
|
ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_TIMESTAMP_HEADER)
|
|
325
333
|
);
|
|
326
334
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
335
|
+
try {
|
|
336
|
+
bolt.verifySlackRequest({
|
|
337
|
+
signingSecret: this.signingSecret,
|
|
338
|
+
body,
|
|
339
|
+
headers: {
|
|
340
|
+
"x-slack-signature": signature,
|
|
341
|
+
"x-slack-request-timestamp": Number.parseInt(timestamp, 10)
|
|
342
|
+
},
|
|
343
|
+
logger: this.logger
|
|
344
|
+
});
|
|
345
|
+
} catch (error) {
|
|
346
|
+
throw new bolt.ReceiverAuthenticityError(
|
|
347
|
+
error instanceof Error ? error.message : "Failed to verify request signature"
|
|
348
|
+
);
|
|
349
|
+
}
|
|
336
350
|
}
|
|
337
351
|
createSlackReceiverEvent({
|
|
338
352
|
body,
|
|
@@ -352,12 +366,19 @@ var VercelReceiver = class {
|
|
|
352
366
|
};
|
|
353
367
|
}
|
|
354
368
|
handleError(error) {
|
|
369
|
+
const errorMessage = getErrorMessage(error);
|
|
370
|
+
const errorType = getErrorType(error);
|
|
371
|
+
const errorStatusCode = getStatusCode(error);
|
|
372
|
+
this.logger.error(error);
|
|
355
373
|
return new Response(
|
|
356
374
|
JSON.stringify({
|
|
357
|
-
error:
|
|
358
|
-
type:
|
|
375
|
+
error: errorMessage,
|
|
376
|
+
type: errorType
|
|
359
377
|
}),
|
|
360
|
-
{
|
|
378
|
+
{
|
|
379
|
+
status: errorStatusCode,
|
|
380
|
+
headers: { "content-type": "application/json" }
|
|
381
|
+
}
|
|
361
382
|
);
|
|
362
383
|
}
|
|
363
384
|
createScopedLogger(logger, logLevel) {
|
|
@@ -403,7 +424,7 @@ function createHandler(app, receiver) {
|
|
|
403
424
|
error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,
|
|
404
425
|
type: ERROR_MESSAGES.TYPES.HANDLER_ERROR
|
|
405
426
|
}),
|
|
406
|
-
{ status: 500 }
|
|
427
|
+
{ status: 500, headers: { "content-type": "application/json" } }
|
|
407
428
|
);
|
|
408
429
|
}
|
|
409
430
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/index.ts"],"names":["logger","LogLevel","ConsoleLogger","ReceiverMultipleAckError","body","waitUntil","ReceiverAuthenticityError","verifySlackRequest"],"mappings":"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","file":"index.js","sourcesContent":["// Error messages constants\nexport const ERROR_MESSAGES = {\n // VercelReceiver errors\n SIGNING_SECRET_REQUIRED:\n \"SLACK_SIGNING_SECRET is required for VercelReceiver\",\n APP_NOT_INITIALIZED: \"App not initialized\",\n REQUEST_TIMEOUT: \"Request timeout\",\n EVENT_NOT_ACKNOWLEDGED: \"Event not acknowledged within timeout period\",\n\n // Header validation errors\n MISSING_REQUIRED_HEADER: (header: string) =>\n `Missing required header: ${header}`,\n\n // Generic fallback errors\n REQUEST_VERIFICATION_FAILED: \"Request verification failed\",\n INTERNAL_SERVER_ERROR: \"Internal server error\",\n INTERNAL_SERVER_ERROR_HANDLER: \"Internal Server Error\",\n ACKNOWLEDGMENT_ERROR: \"Error in acknowledgment handler\",\n CREATE_HANDLER_ERROR: \"Error in createHandler:\",\n\n // Error type names\n TYPES: {\n VERCEL_RECEIVER_ERROR: \"VercelReceiverError\",\n SIGNATURE_VERIFICATION_ERROR: \"SignatureVerificationError\",\n REQUEST_PARSING_ERROR: \"RequestParsingError\",\n UNEXPECTED_ERROR: \"UnexpectedError\",\n HANDLER_ERROR: \"HandlerError\",\n },\n} as const;\n\nexport class VercelReceiverError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number = 500,\n ) {\n super(message);\n this.name = ERROR_MESSAGES.TYPES.VERCEL_RECEIVER_ERROR;\n }\n}\n\nexport class RequestParsingError extends VercelReceiverError {\n constructor(message: string = \"Failed to parse request\") {\n super(message, 400);\n this.name = ERROR_MESSAGES.TYPES.REQUEST_PARSING_ERROR;\n }\n}\n\n/**\n * Determines the appropriate HTTP status code for a given error.\n * @param error The error to get status code for\n * @returns HTTP status code\n */\nexport function getStatusCode(error: unknown): number {\n if (error instanceof VercelReceiverError) {\n return error.statusCode;\n }\n\n // External error types from @slack/bolt\n if (error && typeof error === \"object\" && \"name\" in error) {\n const errorName = String(error.name);\n switch (errorName) {\n case \"ReceiverAuthenticityError\":\n return 401;\n case \"ReceiverMultipleAckError\":\n return 500;\n case \"RequestParsingError\":\n return 400;\n case \"SignatureVerificationError\":\n return 400;\n default:\n return 500;\n }\n }\n\n return 500;\n}\n\n/**\n * Gets the error message for response.\n * @param error The error to get message for\n * @returns Error message string\n */\nexport function getErrorMessage(error: unknown): string {\n if (error && typeof error === \"object\" && \"message\" in error) {\n return String(error.message);\n }\n return ERROR_MESSAGES.INTERNAL_SERVER_ERROR;\n}\n\n/**\n * Gets the error type for response.\n * @param error The error to get type for\n * @returns Error type string\n */\nexport function getErrorType(error: unknown): string {\n if (error && typeof error === \"object\" && \"name\" in error) {\n const errorName = String(error.name);\n // Use \"UnexpectedError\" for generic Error instances, otherwise use the actual name\n return errorName === \"Error\"\n ? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR\n : errorName;\n }\n return ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;\n}\n","import {\n type AckFn,\n type App,\n type Receiver,\n ReceiverAuthenticityError,\n type ReceiverEvent,\n ReceiverMultipleAckError,\n type StringIndexed,\n verifySlackRequest,\n} from \"@slack/bolt\";\nimport { ConsoleLogger, type Logger, LogLevel } from \"@slack/logger\";\nimport { waitUntil } from \"@vercel/functions\";\nimport {\n ERROR_MESSAGES,\n getErrorMessage,\n getErrorType,\n getStatusCode,\n RequestParsingError,\n VercelReceiverError,\n} from \"./errors\";\n\n// Types\n/**\n * A function to handle the request from the Slack app.\n * @param req - The request from the Slack app.\n * @returns A response object.\n */\nexport type VercelHandler = (req: Request) => Promise<Response>;\n\n/**\n * Configuration options for the VercelReceiver.\n * @property signingSecret - The signing secret for the Slack app.\n * @property signatureVerification - If true, verifies the Slack request signature.\n * @property logger - The logger to use for the VercelReceiver.\n * @property logLevel - The log level to use for the VercelReceiver.\n * @property customPropertiesExtractor - A function to extract custom properties from the request.\n */\nexport interface VercelReceiverOptions {\n /**\n * The signing secret for the Slack app.\n * @default process.env.SLACK_SIGNING_SECRET\n */\n signingSecret?: string;\n /**\n * If true, verifies the Slack request signature.\n * @default true\n */\n signatureVerification?: boolean;\n /**\n * The logger to use for the VercelReceiver.\n * @default new ConsoleLogger()\n */\n logger?: Logger;\n /**\n * The log level to use for the VercelReceiver.\n * @default LogLevel.INFO\n */\n logLevel?: LogLevel;\n /**\n * A function to extract custom properties from incoming events.\n * @default undefined\n * @returns An object with custom properties.\n */\n customPropertiesExtractor?: (req: Request) => StringIndexed;\n /**\n * The timeout in milliseconds for event acknowledgment.\n * @default 3001\n */\n ackTimeoutMs?: number;\n}\n\nconst LOG_PREFIX = \"[@vercel/slack-bolt]\";\nconst ACK_TIMEOUT_MS = 3001;\nconst SLACK_RETRY_NUM_HEADER = \"x-slack-retry-num\";\nconst SLACK_RETRY_REASON_HEADER = \"x-slack-retry-reason\";\nconst SLACK_TIMESTAMP_HEADER = \"x-slack-request-timestamp\";\nconst SLACK_SIGNATURE_HEADER = \"x-slack-signature\";\n\n/**\n * A Slack Bolt receiver implementation designed for Vercel's serverless environment.\n * Handles Slack events, interactions, and slash commands with automatic request verification,\n * background processing, and timeout management.\n *\n * @example\n * ```typescript\n * import { App } from '@slack/bolt';\n * import { VercelReceiver, createHandler } from '@vercel/slack-bolt';\n *\n * const receiver = new VercelReceiver();\n *\n * const app = new App({\n * receiver,\n * token: process.env.SLACK_BOT_TOKEN,\n * signingSecret: process.env.SLACK_SIGNING_SECRET,\n * });\n * ```\n *\n */\nexport class VercelReceiver implements Receiver {\n private readonly signingSecret: string;\n private readonly signatureVerification: boolean;\n private readonly logger: Logger;\n private readonly customPropertiesExtractor?: (req: Request) => StringIndexed;\n private readonly ackTimeoutMs: number;\n private app?: App;\n\n /**\n * Gets the logger instance used by this receiver.\n * @returns The logger instance\n */\n public getLogger(): Logger {\n return this.logger;\n }\n\n /**\n * Creates a new VercelReceiver instance.\n *\n * @param options - Configuration options for the receiver\n * @throws {VercelReceiverError} When signing secret is not provided\n *\n * @example\n * ```typescript\n * const receiver = new VercelReceiver();\n * ```\n */\n public constructor({\n signingSecret = process.env.SLACK_SIGNING_SECRET,\n signatureVerification = true,\n logger,\n logLevel = LogLevel.INFO,\n customPropertiesExtractor,\n ackTimeoutMs = ACK_TIMEOUT_MS,\n }: VercelReceiverOptions = {}) {\n if (!signingSecret) {\n throw new VercelReceiverError(ERROR_MESSAGES.SIGNING_SECRET_REQUIRED);\n }\n\n this.signingSecret = signingSecret;\n this.signatureVerification = signatureVerification;\n this.logger = this.createScopedLogger(\n logger ?? new ConsoleLogger(),\n logLevel,\n );\n this.customPropertiesExtractor = customPropertiesExtractor;\n this.ackTimeoutMs = ackTimeoutMs;\n\n this.logger.debug(\"VercelReceiver initialized\");\n }\n\n /**\n * Initializes the receiver with a Slack Bolt app instance.\n * This method is called automatically by the Bolt framework.\n *\n * @param app - The Slack Bolt app instance\n */\n public init(app: App): void {\n this.app = app;\n this.logger.debug(\"App initialized in VercelReceiver\");\n }\n\n /**\n * Starts the receiver and returns a handler function for processing requests.\n * This method is called automatically by the Bolt framework.\n *\n * @returns A handler function that processes incoming Slack requests\n */\n public async start(): Promise<VercelHandler> {\n this.logger.debug(\"VercelReceiver started\");\n return this.toHandler();\n }\n\n /**\n * Stops the receiver. This method is called automatically by the Bolt framework.\n */\n public async stop(): Promise<void> {\n this.logger.debug(\"VercelReceiver stopped\");\n }\n\n /**\n * Creates a handler function that processes incoming Slack requests.\n * This is the main entry point for handling Slack events in Vercel.\n * It is called automatically by the Bolt framework in the start() method.\n *\n * @returns A handler function compatible with Vercel's function signature\n */\n public toHandler(): VercelHandler {\n return async (req: Request): Promise<Response> => {\n try {\n const rawBody = await req.text();\n\n if (this.signatureVerification) {\n this.verifyRequest(req, rawBody);\n }\n\n const body = await this.parseRequestBody(req, rawBody);\n\n if (body.type === \"url_verification\") {\n this.logger.debug(\"Handling URL verification challenge\");\n return Response.json({ challenge: body.challenge });\n }\n\n return await this.handleSlackEvent(req, body);\n } catch (error) {\n return this.handleError(error);\n }\n };\n }\n\n private async parseRequestBody(\n req: Request,\n rawBody: string,\n ): Promise<StringIndexed> {\n const contentType = req.headers.get(\"content-type\");\n\n try {\n if (contentType === \"application/x-www-form-urlencoded\") {\n const parsedBody: StringIndexed = {};\n const params = new URLSearchParams(rawBody);\n\n for (const [key, value] of params.entries()) {\n parsedBody[key] = value;\n }\n\n if (typeof parsedBody.payload === \"string\") {\n return JSON.parse(parsedBody.payload);\n }\n return parsedBody;\n }\n if (contentType === \"application/json\") {\n return JSON.parse(rawBody);\n }\n\n this.logger.warn(`Unexpected content-type detected: ${contentType}`);\n\n return JSON.parse(rawBody);\n } catch (e) {\n throw new RequestParsingError(\n `Failed to parse body as JSON data for content-type: ${contentType}. Error: ${\n e instanceof Error ? e.message : String(e)\n }`,\n );\n }\n }\n\n private async handleSlackEvent(\n req: Request,\n body: StringIndexed,\n ): Promise<Response> {\n if (!this.app) {\n throw new VercelReceiverError(ERROR_MESSAGES.APP_NOT_INITIALIZED, 500);\n }\n\n let isAcknowledged = false;\n let responseResolver: (value: Response) => void;\n let responseRejecter: (error: Error) => void;\n\n const responsePromise = new Promise<Response>((resolve, reject) => {\n responseResolver = resolve;\n responseRejecter = reject;\n });\n\n // Slack requires an acknowledgment from your app within 3 seconds\n const timeoutId = setTimeout(() => {\n if (!isAcknowledged) {\n this.logger.error(ERROR_MESSAGES.EVENT_NOT_ACKNOWLEDGED);\n const error = new VercelReceiverError(\n ERROR_MESSAGES.REQUEST_TIMEOUT,\n 408,\n );\n responseRejecter(error);\n }\n }, this.ackTimeoutMs);\n\n // Create acknowledgment function\n const ackFn: AckFn<StringIndexed> = async (responseBody) => {\n this.logger.debug(`ack() call begins (body: ${responseBody})`);\n if (isAcknowledged) {\n throw new ReceiverMultipleAckError();\n }\n\n isAcknowledged = true;\n clearTimeout(timeoutId);\n\n try {\n let body: string | undefined;\n if (typeof responseBody === \"undefined\") {\n body = undefined;\n } else if (typeof responseBody === \"string\") {\n body = responseBody;\n } else {\n body = JSON.stringify(responseBody);\n }\n const response = new Response(body, {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n responseResolver(response);\n } catch (error) {\n this.logger.error(ERROR_MESSAGES.ACKNOWLEDGMENT_ERROR, error);\n responseRejecter(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n };\n\n const event = this.createSlackReceiverEvent({\n body,\n headers: req.headers,\n ack: ackFn,\n request: req,\n });\n\n // Process event in background using waitUntil from Vercel Functions\n // https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#waituntil\n waitUntil(this.app.processEvent(event));\n\n try {\n return await responsePromise;\n } catch (error) {\n return this.handleError(error);\n }\n }\n\n private verifyRequest(req: Request, body: string): void {\n const timestamp = req.headers.get(SLACK_TIMESTAMP_HEADER);\n const signature = req.headers.get(SLACK_SIGNATURE_HEADER);\n\n if (!signature) {\n throw new ReceiverAuthenticityError(\n ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_SIGNATURE_HEADER),\n );\n }\n\n if (!timestamp) {\n throw new ReceiverAuthenticityError(\n ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_TIMESTAMP_HEADER),\n );\n }\n\n verifySlackRequest({\n signingSecret: this.signingSecret,\n body,\n headers: {\n \"x-slack-signature\": signature,\n \"x-slack-request-timestamp\": Number.parseInt(timestamp, 10),\n },\n logger: this.logger,\n });\n }\n\n private createSlackReceiverEvent({\n body,\n headers,\n ack,\n request,\n }: {\n body: StringIndexed;\n headers: Headers;\n ack: AckFn<StringIndexed>;\n request: Request;\n }): ReceiverEvent {\n const customProperties = this.customPropertiesExtractor\n ? this.customPropertiesExtractor(request)\n : {};\n\n const retryNum = headers.get(SLACK_RETRY_NUM_HEADER) || \"0\";\n\n const retryReason = headers.get(SLACK_RETRY_REASON_HEADER) || \"\";\n\n return {\n body,\n ack,\n retryNum: Number(retryNum),\n retryReason,\n customProperties,\n };\n }\n\n private handleError(error: unknown): Response {\n return new Response(\n JSON.stringify({\n error: getErrorMessage(error),\n type: getErrorType(error),\n }),\n { status: getStatusCode(error) },\n );\n }\n\n private createScopedLogger(logger: Logger, logLevel: LogLevel): Logger {\n logger.setLevel(logLevel);\n\n return {\n ...logger,\n error: (...args) => logger.error?.(LOG_PREFIX, ...args),\n warn: (...args) => logger.warn?.(LOG_PREFIX, ...args),\n info: (...args) => logger.info?.(LOG_PREFIX, ...args),\n debug: (...args) => logger.debug?.(LOG_PREFIX, ...args),\n setLevel: logger.setLevel,\n getLevel: logger.getLevel,\n };\n }\n}\n\n/**\n * Creates a Vercel-compatible handler function for a Slack Bolt app.\n * This is the recommended way to create handlers for deployment on Vercel.\n *\n * @param {App} app - The initialized Slack Bolt app instance.\n * @param {VercelReceiver} receiver - The VercelReceiver instance.\n * @returns {VercelHandler} A handler function compatible with Vercel's function signature.\n *\n * @example\n * ```typescript\n * // api/events.ts\n * import { createHandler } from '@vercel/slack-bolt';\n * import { app, receiver } from '../app';\n *\n * const handler = createHandler(app, receiver);\n *\n * export const POST = async (req: Request) => {\n * return handler(req);\n * };\n * ```\n *\n * @throws {Error} If app initialization fails.\n * @throws {VercelReceiverError} If request processing fails.\n */\nexport function createHandler(\n app: App,\n receiver: VercelReceiver,\n): VercelHandler {\n let initPromise: Promise<void> | null = null;\n\n return async (req: Request) => {\n try {\n if (!initPromise) {\n initPromise = app.init();\n }\n await initPromise;\n\n receiver.init(app);\n const handler = await receiver.start();\n return handler(req);\n } catch (error) {\n const logger = receiver.getLogger();\n logger.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);\n return new Response(\n JSON.stringify({\n error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,\n type: ERROR_MESSAGES.TYPES.HANDLER_ERROR,\n }),\n { status: 500 },\n );\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/index.ts"],"names":["logger","LogLevel","ConsoleLogger","ReceiverMultipleAckError","body","waitUntil","ReceiverAuthenticityError","verifySlackRequest"],"mappings":"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","file":"index.js","sourcesContent":["// Error messages constants\nexport const ERROR_MESSAGES = {\n // VercelReceiver errors\n SIGNING_SECRET_REQUIRED:\n \"SLACK_SIGNING_SECRET is required for VercelReceiver\",\n APP_NOT_INITIALIZED: \"App not initialized\",\n REQUEST_TIMEOUT: \"Request timeout\",\n EVENT_NOT_ACKNOWLEDGED: \"Event not acknowledged within timeout period\",\n\n // Header validation errors\n MISSING_REQUIRED_HEADER: (header: string) =>\n `Missing required header: ${header}`,\n\n // Generic fallback errors\n REQUEST_VERIFICATION_FAILED: \"Request verification failed\",\n INTERNAL_SERVER_ERROR: \"Internal server error\",\n INTERNAL_SERVER_ERROR_HANDLER: \"Internal Server Error\",\n ACKNOWLEDGMENT_ERROR: \"Error in acknowledgment handler\",\n CREATE_HANDLER_ERROR: \"Error in createHandler:\",\n\n // Error type names\n TYPES: {\n VERCEL_RECEIVER_ERROR: \"VercelReceiverError\",\n SIGNATURE_VERIFICATION_ERROR: \"SignatureVerificationError\",\n REQUEST_PARSING_ERROR: \"RequestParsingError\",\n UNEXPECTED_ERROR: \"UnexpectedError\",\n HANDLER_ERROR: \"HandlerError\",\n },\n} as const;\n\nexport class VercelReceiverError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number = 500,\n ) {\n super(message);\n this.name = ERROR_MESSAGES.TYPES.VERCEL_RECEIVER_ERROR;\n }\n}\n\nexport class RequestParsingError extends VercelReceiverError {\n constructor(message: string = \"Failed to parse request\") {\n super(message, 400);\n this.name = ERROR_MESSAGES.TYPES.REQUEST_PARSING_ERROR;\n }\n}\n\n/**\n * Determines the appropriate HTTP status code for a given error.\n * @param error The error to get status code for\n * @returns HTTP status code\n */\nexport function getStatusCode(error: unknown): number {\n if (error instanceof VercelReceiverError) {\n return error.statusCode;\n }\n\n // External error types from @slack/bolt\n if (error && typeof error === \"object\") {\n const errorName =\n error.constructor?.name || (error as { name?: string }).name;\n switch (errorName) {\n case \"ReceiverAuthenticityError\":\n return 401;\n case \"ReceiverMultipleAckError\":\n return 500;\n case \"RequestParsingError\":\n return 400;\n case \"SignatureVerificationError\":\n return 400;\n default:\n return 500;\n }\n }\n\n return 500;\n}\n\n/**\n * Gets the error message for response.\n * @param error The error to get message for\n * @returns Error message string\n */\nexport function getErrorMessage(error: unknown): string {\n if (error && typeof error === \"object\" && \"message\" in error) {\n return String(error.message);\n }\n return ERROR_MESSAGES.INTERNAL_SERVER_ERROR;\n}\n\n/**\n * Gets the error type for response.\n * @param error The error to get type for\n * @returns Error type string\n */\nexport function getErrorType(error: unknown): string {\n if (error && typeof error === \"object\") {\n const ctorName = (error as { constructor?: { name?: string } }).constructor\n ?.name;\n const nameProp = (error as { name?: string }).name;\n const errorName =\n ctorName ?? nameProp ?? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;\n // Use \"UnexpectedError\" for generic Error instances, otherwise use the actual name\n return errorName === \"Error\"\n ? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR\n : errorName;\n }\n return ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;\n}\n","import {\n type AckFn,\n type App,\n type Receiver,\n ReceiverAuthenticityError,\n type ReceiverEvent,\n ReceiverMultipleAckError,\n type StringIndexed,\n verifySlackRequest,\n} from \"@slack/bolt\";\nimport { ConsoleLogger, type Logger, LogLevel } from \"@slack/logger\";\nimport { waitUntil } from \"@vercel/functions\";\nimport {\n ERROR_MESSAGES,\n getErrorMessage,\n getErrorType,\n getStatusCode,\n RequestParsingError,\n VercelReceiverError,\n} from \"./errors\";\n\n// Types\n/**\n * A function to handle the request from the Slack app.\n * @param req - The request from the Slack app.\n * @returns A response object.\n */\nexport type VercelHandler = (req: Request) => Promise<Response>;\n\n/**\n * Configuration options for the VercelReceiver.\n * @property signingSecret - The signing secret for the Slack app.\n * @property signatureVerification - If true, verifies the Slack request signature.\n * @property logger - The logger to use for the VercelReceiver.\n * @property logLevel - The log level to use for the VercelReceiver.\n * @property customPropertiesExtractor - A function to extract custom properties from the request.\n */\nexport interface VercelReceiverOptions {\n /**\n * The signing secret for the Slack app.\n * @default process.env.SLACK_SIGNING_SECRET\n */\n signingSecret?: string;\n /**\n * If true, verifies the Slack request signature.\n * @default true\n */\n signatureVerification?: boolean;\n /**\n * The logger to use for the VercelReceiver.\n * @default new ConsoleLogger()\n */\n logger?: Logger;\n /**\n * The log level to use for the VercelReceiver.\n * @default LogLevel.INFO\n */\n logLevel?: LogLevel;\n /**\n * A function to extract custom properties from incoming events.\n * @default undefined\n * @returns An object with custom properties.\n */\n customPropertiesExtractor?: (req: Request) => StringIndexed;\n /**\n * The timeout in milliseconds for event acknowledgment.\n * @default 3001\n */\n ackTimeoutMs?: number;\n}\n\nconst LOG_PREFIX = \"[@vercel/slack-bolt]\";\nconst ACK_TIMEOUT_MS = 3001;\nconst SLACK_RETRY_NUM_HEADER = \"x-slack-retry-num\";\nconst SLACK_RETRY_REASON_HEADER = \"x-slack-retry-reason\";\nconst SLACK_TIMESTAMP_HEADER = \"x-slack-request-timestamp\";\nconst SLACK_SIGNATURE_HEADER = \"x-slack-signature\";\n\n/**\n * A Slack Bolt receiver implementation designed for Vercel's serverless environment.\n * Handles Slack events, interactions, and slash commands with automatic request verification,\n * background processing, and timeout management.\n *\n * @example\n * ```typescript\n * import { App } from '@slack/bolt';\n * import { VercelReceiver, createHandler } from '@vercel/slack-bolt';\n *\n * const receiver = new VercelReceiver();\n *\n * const app = new App({\n * receiver,\n * token: process.env.SLACK_BOT_TOKEN,\n * signingSecret: process.env.SLACK_SIGNING_SECRET,\n * });\n * ```\n *\n */\nexport class VercelReceiver implements Receiver {\n private readonly signingSecret: string;\n private readonly signatureVerification: boolean;\n private readonly logger: Logger;\n private readonly customPropertiesExtractor?: (req: Request) => StringIndexed;\n private readonly ackTimeoutMs: number;\n private app?: App;\n\n /**\n * Gets the logger instance used by this receiver.\n * @returns The logger instance\n */\n public getLogger(): Logger {\n return this.logger;\n }\n\n /**\n * Creates a new VercelReceiver instance.\n *\n * @param options - Configuration options for the receiver\n * @throws {VercelReceiverError} When signing secret is not provided\n *\n * @example\n * ```typescript\n * const receiver = new VercelReceiver();\n * ```\n */\n public constructor({\n signingSecret = process.env.SLACK_SIGNING_SECRET,\n signatureVerification = true,\n logger,\n logLevel = LogLevel.INFO,\n customPropertiesExtractor,\n ackTimeoutMs = ACK_TIMEOUT_MS,\n }: VercelReceiverOptions = {}) {\n if (!signingSecret) {\n throw new VercelReceiverError(ERROR_MESSAGES.SIGNING_SECRET_REQUIRED);\n }\n\n this.signingSecret = signingSecret;\n this.signatureVerification = signatureVerification;\n this.logger = this.createScopedLogger(\n logger ?? new ConsoleLogger(),\n logLevel,\n );\n this.customPropertiesExtractor = customPropertiesExtractor;\n this.ackTimeoutMs = ackTimeoutMs;\n\n this.logger.debug(\"VercelReceiver initialized\");\n }\n\n /**\n * Initializes the receiver with a Slack Bolt app instance.\n * This method is called automatically by the Bolt framework.\n *\n * @param app - The Slack Bolt app instance\n */\n public init(app: App): void {\n this.app = app;\n this.logger.debug(\"App initialized in VercelReceiver\");\n }\n\n /**\n * Starts the receiver and returns a handler function for processing requests.\n * This method is called automatically by the Bolt framework.\n *\n * @returns A handler function that processes incoming Slack requests\n */\n public async start(): Promise<VercelHandler> {\n this.logger.debug(\"VercelReceiver started\");\n return this.toHandler();\n }\n\n /**\n * Stops the receiver. This method is called automatically by the Bolt framework.\n */\n public async stop(): Promise<void> {\n this.logger.debug(\"VercelReceiver stopped\");\n }\n\n /**\n * Creates a handler function that processes incoming Slack requests.\n * This is the main entry point for handling Slack events in Vercel.\n * It is called automatically by the Bolt framework in the start() method.\n *\n * @returns A handler function compatible with Vercel's function signature\n */\n public toHandler(): VercelHandler {\n return async (req: Request): Promise<Response> => {\n try {\n const rawBody = await req.text();\n\n if (this.signatureVerification) {\n this.verifyRequest(req, rawBody);\n }\n\n const body = await this.parseRequestBody(req, rawBody);\n\n if (body.type === \"url_verification\") {\n this.logger.debug(\"Handling URL verification challenge\");\n return Response.json({ challenge: body.challenge });\n }\n\n return await this.handleSlackEvent(req, body);\n } catch (error) {\n return this.handleError(error);\n }\n };\n }\n\n private async parseRequestBody(\n req: Request,\n rawBody: string,\n ): Promise<StringIndexed> {\n const contentType = req.headers.get(\"content-type\");\n\n try {\n if (contentType === \"application/x-www-form-urlencoded\") {\n const parsedBody: StringIndexed = {};\n const params = new URLSearchParams(rawBody);\n\n for (const [key, value] of params.entries()) {\n parsedBody[key] = value;\n }\n\n if (typeof parsedBody.payload === \"string\") {\n return JSON.parse(parsedBody.payload);\n }\n return parsedBody;\n }\n if (contentType === \"application/json\") {\n return JSON.parse(rawBody);\n }\n\n this.logger.warn(`Unexpected content-type detected: ${contentType}`);\n\n return JSON.parse(rawBody);\n } catch (e) {\n throw new RequestParsingError(\n `Failed to parse body as JSON data for content-type: ${contentType}. Error: ${\n e instanceof Error ? e.message : String(e)\n }`,\n );\n }\n }\n\n private async handleSlackEvent(\n req: Request,\n body: StringIndexed,\n ): Promise<Response> {\n if (!this.app) {\n throw new VercelReceiverError(ERROR_MESSAGES.APP_NOT_INITIALIZED, 500);\n }\n\n let isAcknowledged = false;\n let responseResolver: (value: Response) => void;\n let responseRejecter: (error: Error) => void;\n\n const responsePromise = new Promise<Response>((resolve, reject) => {\n responseResolver = resolve;\n responseRejecter = reject;\n });\n\n // Slack requires an acknowledgment from your app within 3 seconds\n const timeoutId = setTimeout(() => {\n if (!isAcknowledged) {\n this.logger.error(ERROR_MESSAGES.EVENT_NOT_ACKNOWLEDGED);\n const error = new VercelReceiverError(\n ERROR_MESSAGES.REQUEST_TIMEOUT,\n 408,\n );\n responseRejecter(error);\n }\n }, this.ackTimeoutMs);\n\n // Create acknowledgment function\n const ackFn: AckFn<StringIndexed> = async (responseBody) => {\n this.logger.debug(`ack() call begins (body: ${responseBody})`);\n if (isAcknowledged) {\n throw new ReceiverMultipleAckError();\n }\n\n isAcknowledged = true;\n clearTimeout(timeoutId);\n\n try {\n let body: string | undefined;\n if (typeof responseBody === \"undefined\") {\n body = undefined;\n } else if (typeof responseBody === \"string\") {\n body = responseBody;\n } else {\n body = JSON.stringify(responseBody);\n }\n const response = new Response(body, {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n responseResolver(response);\n } catch (error) {\n this.logger.error(ERROR_MESSAGES.ACKNOWLEDGMENT_ERROR, error);\n responseRejecter(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n };\n\n const event = this.createSlackReceiverEvent({\n body,\n headers: req.headers,\n ack: ackFn,\n request: req,\n });\n\n // Process event in background using waitUntil from Vercel Functions\n // https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#waituntil\n waitUntil(\n this.app.processEvent(event).catch((error) => {\n return this.handleError(error);\n }),\n );\n\n try {\n return await responsePromise;\n } catch (error) {\n return this.handleError(error);\n }\n }\n\n private verifyRequest(req: Request, body: string): void {\n const timestamp = req.headers.get(SLACK_TIMESTAMP_HEADER);\n const signature = req.headers.get(SLACK_SIGNATURE_HEADER);\n\n if (!signature) {\n throw new ReceiverAuthenticityError(\n ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_SIGNATURE_HEADER),\n );\n }\n\n if (!timestamp) {\n throw new ReceiverAuthenticityError(\n ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_TIMESTAMP_HEADER),\n );\n }\n\n try {\n verifySlackRequest({\n signingSecret: this.signingSecret,\n body,\n headers: {\n \"x-slack-signature\": signature,\n \"x-slack-request-timestamp\": Number.parseInt(timestamp, 10),\n },\n logger: this.logger,\n });\n } catch (error) {\n throw new ReceiverAuthenticityError(\n error instanceof Error\n ? error.message\n : \"Failed to verify request signature\",\n );\n }\n }\n\n private createSlackReceiverEvent({\n body,\n headers,\n ack,\n request,\n }: {\n body: StringIndexed;\n headers: Headers;\n ack: AckFn<StringIndexed>;\n request: Request;\n }): ReceiverEvent {\n const customProperties = this.customPropertiesExtractor\n ? this.customPropertiesExtractor(request)\n : {};\n\n const retryNum = headers.get(SLACK_RETRY_NUM_HEADER) || \"0\";\n\n const retryReason = headers.get(SLACK_RETRY_REASON_HEADER) || \"\";\n\n return {\n body,\n ack,\n retryNum: Number(retryNum),\n retryReason,\n customProperties,\n };\n }\n\n public handleError(error: unknown): Response {\n const errorMessage = getErrorMessage(error);\n const errorType = getErrorType(error);\n const errorStatusCode = getStatusCode(error);\n\n this.logger.error(error);\n return new Response(\n JSON.stringify({\n error: errorMessage,\n type: errorType,\n }),\n {\n status: errorStatusCode,\n headers: { \"content-type\": \"application/json\" },\n },\n );\n }\n\n private createScopedLogger(logger: Logger, logLevel: LogLevel): Logger {\n logger.setLevel(logLevel);\n\n return {\n ...logger,\n error: (...args) => logger.error?.(LOG_PREFIX, ...args),\n warn: (...args) => logger.warn?.(LOG_PREFIX, ...args),\n info: (...args) => logger.info?.(LOG_PREFIX, ...args),\n debug: (...args) => logger.debug?.(LOG_PREFIX, ...args),\n setLevel: logger.setLevel,\n getLevel: logger.getLevel,\n };\n }\n}\n\n/**\n * Creates a Vercel-compatible handler function for a Slack Bolt app.\n * This is the recommended way to create handlers for deployment on Vercel.\n *\n * @param {App} app - The initialized Slack Bolt app instance.\n * @param {VercelReceiver} receiver - The VercelReceiver instance.\n * @returns {VercelHandler} A handler function compatible with Vercel's function signature.\n *\n * @example\n * ```typescript\n * // api/events.ts\n * import { createHandler } from '@vercel/slack-bolt';\n * import { app, receiver } from '../app';\n *\n * const handler = createHandler(app, receiver);\n *\n * export const POST = async (req: Request) => {\n * return handler(req);\n * };\n * ```\n *\n * @throws {Error} If app initialization fails.\n * @throws {VercelReceiverError} If request processing fails.\n */\nexport function createHandler(\n app: App,\n receiver: VercelReceiver,\n): VercelHandler {\n let initPromise: Promise<void> | null = null;\n\n return async (req: Request) => {\n try {\n if (!initPromise) {\n initPromise = app.init();\n }\n await initPromise;\n\n receiver.init(app);\n const handler = await receiver.start();\n return handler(req);\n } catch (error) {\n const logger = receiver.getLogger();\n logger.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);\n return new Response(\n JSON.stringify({\n error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,\n type: ERROR_MESSAGES.TYPES.HANDLER_ERROR,\n }),\n { status: 500, headers: { \"content-type\": \"application/json\" } },\n );\n }\n };\n}\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -80,11 +80,12 @@ var RequestParsingError = class extends VercelReceiverError {
|
|
|
80
80
|
}
|
|
81
81
|
};
|
|
82
82
|
function getStatusCode(error) {
|
|
83
|
+
var _a;
|
|
83
84
|
if (error instanceof VercelReceiverError) {
|
|
84
85
|
return error.statusCode;
|
|
85
86
|
}
|
|
86
|
-
if (error && typeof error === "object"
|
|
87
|
-
const errorName =
|
|
87
|
+
if (error && typeof error === "object") {
|
|
88
|
+
const errorName = ((_a = error.constructor) == null ? void 0 : _a.name) || error.name;
|
|
88
89
|
switch (errorName) {
|
|
89
90
|
case "ReceiverAuthenticityError":
|
|
90
91
|
return 401;
|
|
@@ -107,8 +108,11 @@ function getErrorMessage(error) {
|
|
|
107
108
|
return ERROR_MESSAGES.INTERNAL_SERVER_ERROR;
|
|
108
109
|
}
|
|
109
110
|
function getErrorType(error) {
|
|
110
|
-
|
|
111
|
-
|
|
111
|
+
var _a, _b;
|
|
112
|
+
if (error && typeof error === "object") {
|
|
113
|
+
const ctorName = (_a = error.constructor) == null ? void 0 : _a.name;
|
|
114
|
+
const nameProp = error.name;
|
|
115
|
+
const errorName = (_b = ctorName != null ? ctorName : nameProp) != null ? _b : ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;
|
|
112
116
|
return errorName === "Error" ? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR : errorName;
|
|
113
117
|
}
|
|
114
118
|
return ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;
|
|
@@ -301,7 +305,11 @@ var VercelReceiver = class {
|
|
|
301
305
|
ack: ackFn,
|
|
302
306
|
request: req
|
|
303
307
|
});
|
|
304
|
-
waitUntil(
|
|
308
|
+
waitUntil(
|
|
309
|
+
this.app.processEvent(event).catch((error) => {
|
|
310
|
+
return this.handleError(error);
|
|
311
|
+
})
|
|
312
|
+
);
|
|
305
313
|
try {
|
|
306
314
|
return yield responsePromise;
|
|
307
315
|
} catch (error) {
|
|
@@ -322,15 +330,21 @@ var VercelReceiver = class {
|
|
|
322
330
|
ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_TIMESTAMP_HEADER)
|
|
323
331
|
);
|
|
324
332
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
333
|
+
try {
|
|
334
|
+
verifySlackRequest({
|
|
335
|
+
signingSecret: this.signingSecret,
|
|
336
|
+
body,
|
|
337
|
+
headers: {
|
|
338
|
+
"x-slack-signature": signature,
|
|
339
|
+
"x-slack-request-timestamp": Number.parseInt(timestamp, 10)
|
|
340
|
+
},
|
|
341
|
+
logger: this.logger
|
|
342
|
+
});
|
|
343
|
+
} catch (error) {
|
|
344
|
+
throw new ReceiverAuthenticityError(
|
|
345
|
+
error instanceof Error ? error.message : "Failed to verify request signature"
|
|
346
|
+
);
|
|
347
|
+
}
|
|
334
348
|
}
|
|
335
349
|
createSlackReceiverEvent({
|
|
336
350
|
body,
|
|
@@ -350,12 +364,19 @@ var VercelReceiver = class {
|
|
|
350
364
|
};
|
|
351
365
|
}
|
|
352
366
|
handleError(error) {
|
|
367
|
+
const errorMessage = getErrorMessage(error);
|
|
368
|
+
const errorType = getErrorType(error);
|
|
369
|
+
const errorStatusCode = getStatusCode(error);
|
|
370
|
+
this.logger.error(error);
|
|
353
371
|
return new Response(
|
|
354
372
|
JSON.stringify({
|
|
355
|
-
error:
|
|
356
|
-
type:
|
|
373
|
+
error: errorMessage,
|
|
374
|
+
type: errorType
|
|
357
375
|
}),
|
|
358
|
-
{
|
|
376
|
+
{
|
|
377
|
+
status: errorStatusCode,
|
|
378
|
+
headers: { "content-type": "application/json" }
|
|
379
|
+
}
|
|
359
380
|
);
|
|
360
381
|
}
|
|
361
382
|
createScopedLogger(logger, logLevel) {
|
|
@@ -401,7 +422,7 @@ function createHandler(app, receiver) {
|
|
|
401
422
|
error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,
|
|
402
423
|
type: ERROR_MESSAGES.TYPES.HANDLER_ERROR
|
|
403
424
|
}),
|
|
404
|
-
{ status: 500 }
|
|
425
|
+
{ status: 500, headers: { "content-type": "application/json" } }
|
|
405
426
|
);
|
|
406
427
|
}
|
|
407
428
|
});
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/index.ts"],"names":["body"],"mappings":"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","file":"index.mjs","sourcesContent":["// Error messages constants\nexport const ERROR_MESSAGES = {\n // VercelReceiver errors\n SIGNING_SECRET_REQUIRED:\n \"SLACK_SIGNING_SECRET is required for VercelReceiver\",\n APP_NOT_INITIALIZED: \"App not initialized\",\n REQUEST_TIMEOUT: \"Request timeout\",\n EVENT_NOT_ACKNOWLEDGED: \"Event not acknowledged within timeout period\",\n\n // Header validation errors\n MISSING_REQUIRED_HEADER: (header: string) =>\n `Missing required header: ${header}`,\n\n // Generic fallback errors\n REQUEST_VERIFICATION_FAILED: \"Request verification failed\",\n INTERNAL_SERVER_ERROR: \"Internal server error\",\n INTERNAL_SERVER_ERROR_HANDLER: \"Internal Server Error\",\n ACKNOWLEDGMENT_ERROR: \"Error in acknowledgment handler\",\n CREATE_HANDLER_ERROR: \"Error in createHandler:\",\n\n // Error type names\n TYPES: {\n VERCEL_RECEIVER_ERROR: \"VercelReceiverError\",\n SIGNATURE_VERIFICATION_ERROR: \"SignatureVerificationError\",\n REQUEST_PARSING_ERROR: \"RequestParsingError\",\n UNEXPECTED_ERROR: \"UnexpectedError\",\n HANDLER_ERROR: \"HandlerError\",\n },\n} as const;\n\nexport class VercelReceiverError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number = 500,\n ) {\n super(message);\n this.name = ERROR_MESSAGES.TYPES.VERCEL_RECEIVER_ERROR;\n }\n}\n\nexport class RequestParsingError extends VercelReceiverError {\n constructor(message: string = \"Failed to parse request\") {\n super(message, 400);\n this.name = ERROR_MESSAGES.TYPES.REQUEST_PARSING_ERROR;\n }\n}\n\n/**\n * Determines the appropriate HTTP status code for a given error.\n * @param error The error to get status code for\n * @returns HTTP status code\n */\nexport function getStatusCode(error: unknown): number {\n if (error instanceof VercelReceiverError) {\n return error.statusCode;\n }\n\n // External error types from @slack/bolt\n if (error && typeof error === \"object\" && \"name\" in error) {\n const errorName = String(error.name);\n switch (errorName) {\n case \"ReceiverAuthenticityError\":\n return 401;\n case \"ReceiverMultipleAckError\":\n return 500;\n case \"RequestParsingError\":\n return 400;\n case \"SignatureVerificationError\":\n return 400;\n default:\n return 500;\n }\n }\n\n return 500;\n}\n\n/**\n * Gets the error message for response.\n * @param error The error to get message for\n * @returns Error message string\n */\nexport function getErrorMessage(error: unknown): string {\n if (error && typeof error === \"object\" && \"message\" in error) {\n return String(error.message);\n }\n return ERROR_MESSAGES.INTERNAL_SERVER_ERROR;\n}\n\n/**\n * Gets the error type for response.\n * @param error The error to get type for\n * @returns Error type string\n */\nexport function getErrorType(error: unknown): string {\n if (error && typeof error === \"object\" && \"name\" in error) {\n const errorName = String(error.name);\n // Use \"UnexpectedError\" for generic Error instances, otherwise use the actual name\n return errorName === \"Error\"\n ? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR\n : errorName;\n }\n return ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;\n}\n","import {\n type AckFn,\n type App,\n type Receiver,\n ReceiverAuthenticityError,\n type ReceiverEvent,\n ReceiverMultipleAckError,\n type StringIndexed,\n verifySlackRequest,\n} from \"@slack/bolt\";\nimport { ConsoleLogger, type Logger, LogLevel } from \"@slack/logger\";\nimport { waitUntil } from \"@vercel/functions\";\nimport {\n ERROR_MESSAGES,\n getErrorMessage,\n getErrorType,\n getStatusCode,\n RequestParsingError,\n VercelReceiverError,\n} from \"./errors\";\n\n// Types\n/**\n * A function to handle the request from the Slack app.\n * @param req - The request from the Slack app.\n * @returns A response object.\n */\nexport type VercelHandler = (req: Request) => Promise<Response>;\n\n/**\n * Configuration options for the VercelReceiver.\n * @property signingSecret - The signing secret for the Slack app.\n * @property signatureVerification - If true, verifies the Slack request signature.\n * @property logger - The logger to use for the VercelReceiver.\n * @property logLevel - The log level to use for the VercelReceiver.\n * @property customPropertiesExtractor - A function to extract custom properties from the request.\n */\nexport interface VercelReceiverOptions {\n /**\n * The signing secret for the Slack app.\n * @default process.env.SLACK_SIGNING_SECRET\n */\n signingSecret?: string;\n /**\n * If true, verifies the Slack request signature.\n * @default true\n */\n signatureVerification?: boolean;\n /**\n * The logger to use for the VercelReceiver.\n * @default new ConsoleLogger()\n */\n logger?: Logger;\n /**\n * The log level to use for the VercelReceiver.\n * @default LogLevel.INFO\n */\n logLevel?: LogLevel;\n /**\n * A function to extract custom properties from incoming events.\n * @default undefined\n * @returns An object with custom properties.\n */\n customPropertiesExtractor?: (req: Request) => StringIndexed;\n /**\n * The timeout in milliseconds for event acknowledgment.\n * @default 3001\n */\n ackTimeoutMs?: number;\n}\n\nconst LOG_PREFIX = \"[@vercel/slack-bolt]\";\nconst ACK_TIMEOUT_MS = 3001;\nconst SLACK_RETRY_NUM_HEADER = \"x-slack-retry-num\";\nconst SLACK_RETRY_REASON_HEADER = \"x-slack-retry-reason\";\nconst SLACK_TIMESTAMP_HEADER = \"x-slack-request-timestamp\";\nconst SLACK_SIGNATURE_HEADER = \"x-slack-signature\";\n\n/**\n * A Slack Bolt receiver implementation designed for Vercel's serverless environment.\n * Handles Slack events, interactions, and slash commands with automatic request verification,\n * background processing, and timeout management.\n *\n * @example\n * ```typescript\n * import { App } from '@slack/bolt';\n * import { VercelReceiver, createHandler } from '@vercel/slack-bolt';\n *\n * const receiver = new VercelReceiver();\n *\n * const app = new App({\n * receiver,\n * token: process.env.SLACK_BOT_TOKEN,\n * signingSecret: process.env.SLACK_SIGNING_SECRET,\n * });\n * ```\n *\n */\nexport class VercelReceiver implements Receiver {\n private readonly signingSecret: string;\n private readonly signatureVerification: boolean;\n private readonly logger: Logger;\n private readonly customPropertiesExtractor?: (req: Request) => StringIndexed;\n private readonly ackTimeoutMs: number;\n private app?: App;\n\n /**\n * Gets the logger instance used by this receiver.\n * @returns The logger instance\n */\n public getLogger(): Logger {\n return this.logger;\n }\n\n /**\n * Creates a new VercelReceiver instance.\n *\n * @param options - Configuration options for the receiver\n * @throws {VercelReceiverError} When signing secret is not provided\n *\n * @example\n * ```typescript\n * const receiver = new VercelReceiver();\n * ```\n */\n public constructor({\n signingSecret = process.env.SLACK_SIGNING_SECRET,\n signatureVerification = true,\n logger,\n logLevel = LogLevel.INFO,\n customPropertiesExtractor,\n ackTimeoutMs = ACK_TIMEOUT_MS,\n }: VercelReceiverOptions = {}) {\n if (!signingSecret) {\n throw new VercelReceiverError(ERROR_MESSAGES.SIGNING_SECRET_REQUIRED);\n }\n\n this.signingSecret = signingSecret;\n this.signatureVerification = signatureVerification;\n this.logger = this.createScopedLogger(\n logger ?? new ConsoleLogger(),\n logLevel,\n );\n this.customPropertiesExtractor = customPropertiesExtractor;\n this.ackTimeoutMs = ackTimeoutMs;\n\n this.logger.debug(\"VercelReceiver initialized\");\n }\n\n /**\n * Initializes the receiver with a Slack Bolt app instance.\n * This method is called automatically by the Bolt framework.\n *\n * @param app - The Slack Bolt app instance\n */\n public init(app: App): void {\n this.app = app;\n this.logger.debug(\"App initialized in VercelReceiver\");\n }\n\n /**\n * Starts the receiver and returns a handler function for processing requests.\n * This method is called automatically by the Bolt framework.\n *\n * @returns A handler function that processes incoming Slack requests\n */\n public async start(): Promise<VercelHandler> {\n this.logger.debug(\"VercelReceiver started\");\n return this.toHandler();\n }\n\n /**\n * Stops the receiver. This method is called automatically by the Bolt framework.\n */\n public async stop(): Promise<void> {\n this.logger.debug(\"VercelReceiver stopped\");\n }\n\n /**\n * Creates a handler function that processes incoming Slack requests.\n * This is the main entry point for handling Slack events in Vercel.\n * It is called automatically by the Bolt framework in the start() method.\n *\n * @returns A handler function compatible with Vercel's function signature\n */\n public toHandler(): VercelHandler {\n return async (req: Request): Promise<Response> => {\n try {\n const rawBody = await req.text();\n\n if (this.signatureVerification) {\n this.verifyRequest(req, rawBody);\n }\n\n const body = await this.parseRequestBody(req, rawBody);\n\n if (body.type === \"url_verification\") {\n this.logger.debug(\"Handling URL verification challenge\");\n return Response.json({ challenge: body.challenge });\n }\n\n return await this.handleSlackEvent(req, body);\n } catch (error) {\n return this.handleError(error);\n }\n };\n }\n\n private async parseRequestBody(\n req: Request,\n rawBody: string,\n ): Promise<StringIndexed> {\n const contentType = req.headers.get(\"content-type\");\n\n try {\n if (contentType === \"application/x-www-form-urlencoded\") {\n const parsedBody: StringIndexed = {};\n const params = new URLSearchParams(rawBody);\n\n for (const [key, value] of params.entries()) {\n parsedBody[key] = value;\n }\n\n if (typeof parsedBody.payload === \"string\") {\n return JSON.parse(parsedBody.payload);\n }\n return parsedBody;\n }\n if (contentType === \"application/json\") {\n return JSON.parse(rawBody);\n }\n\n this.logger.warn(`Unexpected content-type detected: ${contentType}`);\n\n return JSON.parse(rawBody);\n } catch (e) {\n throw new RequestParsingError(\n `Failed to parse body as JSON data for content-type: ${contentType}. Error: ${\n e instanceof Error ? e.message : String(e)\n }`,\n );\n }\n }\n\n private async handleSlackEvent(\n req: Request,\n body: StringIndexed,\n ): Promise<Response> {\n if (!this.app) {\n throw new VercelReceiverError(ERROR_MESSAGES.APP_NOT_INITIALIZED, 500);\n }\n\n let isAcknowledged = false;\n let responseResolver: (value: Response) => void;\n let responseRejecter: (error: Error) => void;\n\n const responsePromise = new Promise<Response>((resolve, reject) => {\n responseResolver = resolve;\n responseRejecter = reject;\n });\n\n // Slack requires an acknowledgment from your app within 3 seconds\n const timeoutId = setTimeout(() => {\n if (!isAcknowledged) {\n this.logger.error(ERROR_MESSAGES.EVENT_NOT_ACKNOWLEDGED);\n const error = new VercelReceiverError(\n ERROR_MESSAGES.REQUEST_TIMEOUT,\n 408,\n );\n responseRejecter(error);\n }\n }, this.ackTimeoutMs);\n\n // Create acknowledgment function\n const ackFn: AckFn<StringIndexed> = async (responseBody) => {\n this.logger.debug(`ack() call begins (body: ${responseBody})`);\n if (isAcknowledged) {\n throw new ReceiverMultipleAckError();\n }\n\n isAcknowledged = true;\n clearTimeout(timeoutId);\n\n try {\n let body: string | undefined;\n if (typeof responseBody === \"undefined\") {\n body = undefined;\n } else if (typeof responseBody === \"string\") {\n body = responseBody;\n } else {\n body = JSON.stringify(responseBody);\n }\n const response = new Response(body, {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n responseResolver(response);\n } catch (error) {\n this.logger.error(ERROR_MESSAGES.ACKNOWLEDGMENT_ERROR, error);\n responseRejecter(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n };\n\n const event = this.createSlackReceiverEvent({\n body,\n headers: req.headers,\n ack: ackFn,\n request: req,\n });\n\n // Process event in background using waitUntil from Vercel Functions\n // https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#waituntil\n waitUntil(this.app.processEvent(event));\n\n try {\n return await responsePromise;\n } catch (error) {\n return this.handleError(error);\n }\n }\n\n private verifyRequest(req: Request, body: string): void {\n const timestamp = req.headers.get(SLACK_TIMESTAMP_HEADER);\n const signature = req.headers.get(SLACK_SIGNATURE_HEADER);\n\n if (!signature) {\n throw new ReceiverAuthenticityError(\n ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_SIGNATURE_HEADER),\n );\n }\n\n if (!timestamp) {\n throw new ReceiverAuthenticityError(\n ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_TIMESTAMP_HEADER),\n );\n }\n\n verifySlackRequest({\n signingSecret: this.signingSecret,\n body,\n headers: {\n \"x-slack-signature\": signature,\n \"x-slack-request-timestamp\": Number.parseInt(timestamp, 10),\n },\n logger: this.logger,\n });\n }\n\n private createSlackReceiverEvent({\n body,\n headers,\n ack,\n request,\n }: {\n body: StringIndexed;\n headers: Headers;\n ack: AckFn<StringIndexed>;\n request: Request;\n }): ReceiverEvent {\n const customProperties = this.customPropertiesExtractor\n ? this.customPropertiesExtractor(request)\n : {};\n\n const retryNum = headers.get(SLACK_RETRY_NUM_HEADER) || \"0\";\n\n const retryReason = headers.get(SLACK_RETRY_REASON_HEADER) || \"\";\n\n return {\n body,\n ack,\n retryNum: Number(retryNum),\n retryReason,\n customProperties,\n };\n }\n\n private handleError(error: unknown): Response {\n return new Response(\n JSON.stringify({\n error: getErrorMessage(error),\n type: getErrorType(error),\n }),\n { status: getStatusCode(error) },\n );\n }\n\n private createScopedLogger(logger: Logger, logLevel: LogLevel): Logger {\n logger.setLevel(logLevel);\n\n return {\n ...logger,\n error: (...args) => logger.error?.(LOG_PREFIX, ...args),\n warn: (...args) => logger.warn?.(LOG_PREFIX, ...args),\n info: (...args) => logger.info?.(LOG_PREFIX, ...args),\n debug: (...args) => logger.debug?.(LOG_PREFIX, ...args),\n setLevel: logger.setLevel,\n getLevel: logger.getLevel,\n };\n }\n}\n\n/**\n * Creates a Vercel-compatible handler function for a Slack Bolt app.\n * This is the recommended way to create handlers for deployment on Vercel.\n *\n * @param {App} app - The initialized Slack Bolt app instance.\n * @param {VercelReceiver} receiver - The VercelReceiver instance.\n * @returns {VercelHandler} A handler function compatible with Vercel's function signature.\n *\n * @example\n * ```typescript\n * // api/events.ts\n * import { createHandler } from '@vercel/slack-bolt';\n * import { app, receiver } from '../app';\n *\n * const handler = createHandler(app, receiver);\n *\n * export const POST = async (req: Request) => {\n * return handler(req);\n * };\n * ```\n *\n * @throws {Error} If app initialization fails.\n * @throws {VercelReceiverError} If request processing fails.\n */\nexport function createHandler(\n app: App,\n receiver: VercelReceiver,\n): VercelHandler {\n let initPromise: Promise<void> | null = null;\n\n return async (req: Request) => {\n try {\n if (!initPromise) {\n initPromise = app.init();\n }\n await initPromise;\n\n receiver.init(app);\n const handler = await receiver.start();\n return handler(req);\n } catch (error) {\n const logger = receiver.getLogger();\n logger.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);\n return new Response(\n JSON.stringify({\n error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,\n type: ERROR_MESSAGES.TYPES.HANDLER_ERROR,\n }),\n { status: 500 },\n );\n }\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/index.ts"],"names":["body"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACO,IAAM,cAAA,GAAiB;AAAA;AAAA,EAE5B,uBAAA,EACE,qDAAA;AAAA,EACF,mBAAA,EAAqB,qBAAA;AAAA,EACrB,eAAA,EAAiB,iBAAA;AAAA,EACjB,sBAAA,EAAwB,8CAAA;AAAA;AAAA,EAGxB,uBAAA,EAAyB,CAAC,MAAA,KACxB,CAAA,yBAAA,EAA4B,MAAM,CAAA,CAAA;AAAA;AAAA,EAGpC,2BAAA,EAA6B,6BAAA;AAAA,EAC7B,qBAAA,EAAuB,uBAAA;AAAA,EACvB,6BAAA,EAA+B,uBAAA;AAAA,EAC/B,oBAAA,EAAsB,iCAAA;AAAA,EACtB,oBAAA,EAAsB,yBAAA;AAAA;AAAA,EAGtB,KAAA,EAAO;AAAA,IACL,qBAAA,EAAuB,qBAAA;AAAA,IACvB,4BAAA,EAA8B,4BAAA;AAAA,IAC9B,qBAAA,EAAuB,qBAAA;AAAA,IACvB,gBAAA,EAAkB,iBAAA;AAAA,IAClB,aAAA,EAAe;AAAA;AAEnB,CAAA;AAEO,IAAM,mBAAA,GAAN,cAAkC,KAAA,CAAM;AAAA,EAC7C,WAAA,CACE,OAAA,EACgB,UAAA,GAAqB,GAAA,EACrC;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AAFG,IAAA,IAAA,CAAA,UAAA,GAAA,UAAA;AAGhB,IAAA,IAAA,CAAK,IAAA,GAAO,eAAe,KAAA,CAAM,qBAAA;AAAA,EACnC;AACF,CAAA;AAEO,IAAM,mBAAA,GAAN,cAAkC,mBAAA,CAAoB;AAAA,EAC3D,WAAA,CAAY,UAAkB,yBAAA,EAA2B;AACvD,IAAA,KAAA,CAAM,SAAS,GAAG,CAAA;AAClB,IAAA,IAAA,CAAK,IAAA,GAAO,eAAe,KAAA,CAAM,qBAAA;AAAA,EACnC;AACF,CAAA;AAOO,SAAS,cAAc,KAAA,EAAwB;AApDtD,EAAA,IAAA,EAAA;AAqDE,EAAA,IAAI,iBAAiB,mBAAA,EAAqB;AACxC,IAAA,OAAO,KAAA,CAAM,UAAA;AAAA,EACf;AAGA,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACtC,IAAA,MAAM,SAAA,GAAA,CAAA,CACJ,EAAA,GAAA,KAAA,CAAM,WAAA,KAAN,IAAA,GAAA,MAAA,GAAA,EAAA,CAAmB,SAAS,KAAA,CAA4B,IAAA;AAC1D,IAAA,QAAQ,SAAA;AAAW,MACjB,KAAK,2BAAA;AACH,QAAA,OAAO,GAAA;AAAA,MACT,KAAK,0BAAA;AACH,QAAA,OAAO,GAAA;AAAA,MACT,KAAK,qBAAA;AACH,QAAA,OAAO,GAAA;AAAA,MACT,KAAK,4BAAA;AACH,QAAA,OAAO,GAAA;AAAA,MACT;AACE,QAAA,OAAO,GAAA;AAAA;AACX,EACF;AAEA,EAAA,OAAO,GAAA;AACT;AAOO,SAAS,gBAAgB,KAAA,EAAwB;AACtD,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,IAAY,aAAa,KAAA,EAAO;AAC5D,IAAA,OAAO,MAAA,CAAO,MAAM,OAAO,CAAA;AAAA,EAC7B;AACA,EAAA,OAAO,cAAA,CAAe,qBAAA;AACxB;AAOO,SAAS,aAAa,KAAA,EAAwB;AA/FrD,EAAA,IAAA,EAAA,EAAA,EAAA;AAgGE,EAAA,IAAI,KAAA,IAAS,OAAO,KAAA,KAAU,QAAA,EAAU;AACtC,IAAA,MAAM,QAAA,GAAA,CAAY,EAAA,GAAA,KAAA,CAA8C,WAAA,KAA9C,IAAA,GAAA,MAAA,GAAA,EAAA,CACd,IAAA;AACJ,IAAA,MAAM,WAAY,KAAA,CAA4B,IAAA;AAC9C,IAAA,MAAM,SAAA,GAAA,CACJ,EAAA,GAAA,QAAA,IAAA,IAAA,GAAA,QAAA,GAAY,QAAA,KAAZ,IAAA,GAAA,EAAA,GAAwB,eAAe,KAAA,CAAM,gBAAA;AAE/C,IAAA,OAAO,SAAA,KAAc,OAAA,GACjB,cAAA,CAAe,KAAA,CAAM,gBAAA,GACrB,SAAA;AAAA,EACN;AACA,EAAA,OAAO,eAAe,KAAA,CAAM,gBAAA;AAC9B;;;ACrCA,IAAM,UAAA,GAAa,sBAAA;AACnB,IAAM,cAAA,GAAiB,IAAA;AACvB,IAAM,sBAAA,GAAyB,mBAAA;AAC/B,IAAM,yBAAA,GAA4B,sBAAA;AAClC,IAAM,sBAAA,GAAyB,2BAAA;AAC/B,IAAM,sBAAA,GAAyB,mBAAA;AAsBxB,IAAM,iBAAN,MAAyC;AAAA;AAAA;AAAA;AAAA;AAAA,EAYvC,SAAA,GAAoB;AACzB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaO,WAAA,CAAY;AAAA,IACjB,aAAA,GAAgB,QAAQ,GAAA,CAAI,oBAAA;AAAA,IAC5B,qBAAA,GAAwB,IAAA;AAAA,IACxB,MAAA;AAAA,IACA,WAAW,QAAA,CAAS,IAAA;AAAA,IACpB,yBAAA;AAAA,IACA,YAAA,GAAe;AAAA,GACjB,GAA2B,EAAC,EAAG;AAC7B,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA,MAAM,IAAI,mBAAA,CAAoB,cAAA,CAAe,uBAAuB,CAAA;AAAA,IACtE;AAEA,IAAA,IAAA,CAAK,aAAA,GAAgB,aAAA;AACrB,IAAA,IAAA,CAAK,qBAAA,GAAwB,qBAAA;AAC7B,IAAA,IAAA,CAAK,SAAS,IAAA,CAAK,kBAAA;AAAA,MACjB,MAAA,IAAA,IAAA,GAAA,MAAA,GAAU,IAAI,aAAA,EAAc;AAAA,MAC5B;AAAA,KACF;AACA,IAAA,IAAA,CAAK,yBAAA,GAA4B,yBAAA;AACjC,IAAA,IAAA,CAAK,YAAA,GAAe,YAAA;AAEpB,IAAA,IAAA,CAAK,MAAA,CAAO,MAAM,4BAA4B,CAAA;AAAA,EAChD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQO,KAAK,GAAA,EAAgB;AAC1B,IAAA,IAAA,CAAK,GAAA,GAAM,GAAA;AACX,IAAA,IAAA,CAAK,MAAA,CAAO,MAAM,mCAAmC,CAAA;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQa,KAAA,GAAgC;AAAA,IAAA,OAAA,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAC3C,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,wBAAwB,CAAA;AAC1C,MAAA,OAAO,KAAK,SAAA,EAAU;AAAA,IACxB,CAAA,CAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA,EAKa,IAAA,GAAsB;AAAA,IAAA,OAAA,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AACjC,MAAA,IAAA,CAAK,MAAA,CAAO,MAAM,wBAAwB,CAAA;AAAA,IAC5C,CAAA,CAAA;AAAA,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASO,SAAA,GAA2B;AAChC,IAAA,OAAO,CAAO,GAAA,KAAoC,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAChD,MAAA,IAAI;AACF,QAAA,MAAM,OAAA,GAAU,MAAM,GAAA,CAAI,IAAA,EAAK;AAE/B,QAAA,IAAI,KAAK,qBAAA,EAAuB;AAC9B,UAAA,IAAA,CAAK,aAAA,CAAc,KAAK,OAAO,CAAA;AAAA,QACjC;AAEA,QAAA,MAAM,IAAA,GAAO,MAAM,IAAA,CAAK,gBAAA,CAAiB,KAAK,OAAO,CAAA;AAErD,QAAA,IAAI,IAAA,CAAK,SAAS,kBAAA,EAAoB;AACpC,UAAA,IAAA,CAAK,MAAA,CAAO,MAAM,qCAAqC,CAAA;AACvD,UAAA,OAAO,SAAS,IAAA,CAAK,EAAE,SAAA,EAAW,IAAA,CAAK,WAAW,CAAA;AAAA,QACpD;AAEA,QAAA,OAAO,MAAM,IAAA,CAAK,gBAAA,CAAiB,GAAA,EAAK,IAAI,CAAA;AAAA,MAC9C,SAAS,KAAA,EAAO;AACd,QAAA,OAAO,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,MAC/B;AAAA,IACF,CAAA,CAAA;AAAA,EACF;AAAA,EAEc,gBAAA,CACZ,KACA,OAAA,EACwB;AAAA,IAAA,OAAA,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AACxB,MAAA,MAAM,WAAA,GAAc,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,cAAc,CAAA;AAElD,MAAA,IAAI;AACF,QAAA,IAAI,gBAAgB,mCAAA,EAAqC;AACvD,UAAA,MAAM,aAA4B,EAAC;AACnC,UAAA,MAAM,MAAA,GAAS,IAAI,eAAA,CAAgB,OAAO,CAAA;AAE1C,UAAA,KAAA,MAAW,CAAC,GAAA,EAAK,KAAK,CAAA,IAAK,MAAA,CAAO,SAAQ,EAAG;AAC3C,YAAA,UAAA,CAAW,GAAG,CAAA,GAAI,KAAA;AAAA,UACpB;AAEA,UAAA,IAAI,OAAO,UAAA,CAAW,OAAA,KAAY,QAAA,EAAU;AAC1C,YAAA,OAAO,IAAA,CAAK,KAAA,CAAM,UAAA,CAAW,OAAO,CAAA;AAAA,UACtC;AACA,UAAA,OAAO,UAAA;AAAA,QACT;AACA,QAAA,IAAI,gBAAgB,kBAAA,EAAoB;AACtC,UAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,QAC3B;AAEA,QAAA,IAAA,CAAK,MAAA,CAAO,IAAA,CAAK,CAAA,kCAAA,EAAqC,WAAW,CAAA,CAAE,CAAA;AAEnE,QAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,MAC3B,SAAS,CAAA,EAAG;AACV,QAAA,MAAM,IAAI,mBAAA;AAAA,UACR,CAAA,oDAAA,EAAuD,WAAW,CAAA,SAAA,EAChE,CAAA,YAAa,QAAQ,CAAA,CAAE,OAAA,GAAU,MAAA,CAAO,CAAC,CAC3C,CAAA;AAAA,SACF;AAAA,MACF;AAAA,IACF,CAAA,CAAA;AAAA,EAAA;AAAA,EAEc,gBAAA,CACZ,KACA,IAAA,EACmB;AAAA,IAAA,OAAA,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AACnB,MAAA,IAAI,CAAC,KAAK,GAAA,EAAK;AACb,QAAA,MAAM,IAAI,mBAAA,CAAoB,cAAA,CAAe,mBAAA,EAAqB,GAAG,CAAA;AAAA,MACvE;AAEA,MAAA,IAAI,cAAA,GAAiB,KAAA;AACrB,MAAA,IAAI,gBAAA;AACJ,MAAA,IAAI,gBAAA;AAEJ,MAAA,MAAM,eAAA,GAAkB,IAAI,OAAA,CAAkB,CAAC,SAAS,MAAA,KAAW;AACjE,QAAA,gBAAA,GAAmB,OAAA;AACnB,QAAA,gBAAA,GAAmB,MAAA;AAAA,MACrB,CAAC,CAAA;AAGD,MAAA,MAAM,SAAA,GAAY,WAAW,MAAM;AACjC,QAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,UAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,cAAA,CAAe,sBAAsB,CAAA;AACvD,UAAA,MAAM,QAAQ,IAAI,mBAAA;AAAA,YAChB,cAAA,CAAe,eAAA;AAAA,YACf;AAAA,WACF;AACA,UAAA,gBAAA,CAAiB,KAAK,CAAA;AAAA,QACxB;AAAA,MACF,CAAA,EAAG,KAAK,YAAY,CAAA;AAGpB,MAAA,MAAM,KAAA,GAA8B,CAAO,YAAA,KAAiB,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAC1D,QAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,yBAAA,EAA4B,YAAY,CAAA,CAAA,CAAG,CAAA;AAC7D,QAAA,IAAI,cAAA,EAAgB;AAClB,UAAA,MAAM,IAAI,wBAAA,EAAyB;AAAA,QACrC;AAEA,QAAA,cAAA,GAAiB,IAAA;AACjB,QAAA,YAAA,CAAa,SAAS,CAAA;AAEtB,QAAA,IAAI;AACF,UAAA,IAAIA,KAAAA;AACJ,UAAA,IAAI,OAAO,iBAAiB,WAAA,EAAa;AACvC,YAAAA,KAAAA,GAAO,KAAA,CAAA;AAAA,UACT,CAAA,MAAA,IAAW,OAAO,YAAA,KAAiB,QAAA,EAAU;AAC3C,YAAAA,KAAAA,GAAO,YAAA;AAAA,UACT,CAAA,MAAO;AACL,YAAAA,KAAAA,GAAO,IAAA,CAAK,SAAA,CAAU,YAAY,CAAA;AAAA,UACpC;AACA,UAAA,MAAM,QAAA,GAAW,IAAI,QAAA,CAASA,KAAAA,EAAM;AAAA,YAClC,MAAA,EAAQ,GAAA;AAAA,YACR,OAAA,EAAS;AAAA,cACP,cAAA,EAAgB;AAAA;AAClB,WACD,CAAA;AAED,UAAA,gBAAA,CAAiB,QAAQ,CAAA;AAAA,QAC3B,SAAS,KAAA,EAAO;AACd,UAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,cAAA,CAAe,oBAAA,EAAsB,KAAK,CAAA;AAC5D,UAAA,gBAAA;AAAA,YACE,iBAAiB,KAAA,GAAQ,KAAA,GAAQ,IAAI,KAAA,CAAM,MAAA,CAAO,KAAK,CAAC;AAAA,WAC1D;AAAA,QACF;AAAA,MACF,CAAA,CAAA;AAEA,MAAA,MAAM,KAAA,GAAQ,KAAK,wBAAA,CAAyB;AAAA,QAC1C,IAAA;AAAA,QACA,SAAS,GAAA,CAAI,OAAA;AAAA,QACb,GAAA,EAAK,KAAA;AAAA,QACL,OAAA,EAAS;AAAA,OACV,CAAA;AAID,MAAA,SAAA;AAAA,QACE,KAAK,GAAA,CAAI,YAAA,CAAa,KAAK,CAAA,CAAE,KAAA,CAAM,CAAC,KAAA,KAAU;AAC5C,UAAA,OAAO,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,QAC/B,CAAC;AAAA,OACH;AAEA,MAAA,IAAI;AACF,QAAA,OAAO,MAAM,eAAA;AAAA,MACf,SAAS,KAAA,EAAO;AACd,QAAA,OAAO,IAAA,CAAK,YAAY,KAAK,CAAA;AAAA,MAC/B;AAAA,IACF,CAAA,CAAA;AAAA,EAAA;AAAA,EAEQ,aAAA,CAAc,KAAc,IAAA,EAAoB;AACtD,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,sBAAsB,CAAA;AACxD,IAAA,MAAM,SAAA,GAAY,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,sBAAsB,CAAA;AAExD,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,yBAAA;AAAA,QACR,cAAA,CAAe,wBAAwB,sBAAsB;AAAA,OAC/D;AAAA,IACF;AAEA,IAAA,IAAI,CAAC,SAAA,EAAW;AACd,MAAA,MAAM,IAAI,yBAAA;AAAA,QACR,cAAA,CAAe,wBAAwB,sBAAsB;AAAA,OAC/D;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,kBAAA,CAAmB;AAAA,QACjB,eAAe,IAAA,CAAK,aAAA;AAAA,QACpB,IAAA;AAAA,QACA,OAAA,EAAS;AAAA,UACP,mBAAA,EAAqB,SAAA;AAAA,UACrB,2BAAA,EAA6B,MAAA,CAAO,QAAA,CAAS,SAAA,EAAW,EAAE;AAAA,SAC5D;AAAA,QACA,QAAQ,IAAA,CAAK;AAAA,OACd,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,IAAI,yBAAA;AAAA,QACR,KAAA,YAAiB,KAAA,GACb,KAAA,CAAM,OAAA,GACN;AAAA,OACN;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,wBAAA,CAAyB;AAAA,IAC/B,IAAA;AAAA,IACA,OAAA;AAAA,IACA,GAAA;AAAA,IACA;AAAA,GACF,EAKkB;AAChB,IAAA,MAAM,mBAAmB,IAAA,CAAK,yBAAA,GAC1B,KAAK,yBAAA,CAA0B,OAAO,IACtC,EAAC;AAEL,IAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,GAAA,CAAI,sBAAsB,CAAA,IAAK,GAAA;AAExD,IAAA,MAAM,WAAA,GAAc,OAAA,CAAQ,GAAA,CAAI,yBAAyB,CAAA,IAAK,EAAA;AAE9D,IAAA,OAAO;AAAA,MACL,IAAA;AAAA,MACA,GAAA;AAAA,MACA,QAAA,EAAU,OAAO,QAAQ,CAAA;AAAA,MACzB,WAAA;AAAA,MACA;AAAA,KACF;AAAA,EACF;AAAA,EAEO,YAAY,KAAA,EAA0B;AAC3C,IAAA,MAAM,YAAA,GAAe,gBAAgB,KAAK,CAAA;AAC1C,IAAA,MAAM,SAAA,GAAY,aAAa,KAAK,CAAA;AACpC,IAAA,MAAM,eAAA,GAAkB,cAAc,KAAK,CAAA;AAE3C,IAAA,IAAA,CAAK,MAAA,CAAO,MAAM,KAAK,CAAA;AACvB,IAAA,OAAO,IAAI,QAAA;AAAA,MACT,KAAK,SAAA,CAAU;AAAA,QACb,KAAA,EAAO,YAAA;AAAA,QACP,IAAA,EAAM;AAAA,OACP,CAAA;AAAA,MACD;AAAA,QACE,MAAA,EAAQ,eAAA;AAAA,QACR,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB;AAChD,KACF;AAAA,EACF;AAAA,EAEQ,kBAAA,CAAmB,QAAgB,QAAA,EAA4B;AACrE,IAAA,MAAA,CAAO,SAAS,QAAQ,CAAA;AAExB,IAAA,OAAO,iCACF,MAAA,CAAA,EADE;AAAA,MAEL,KAAA,EAAO,IAAI,IAAA,KAAM;AAhavB,QAAA,IAAA,EAAA;AAga0B,QAAA,OAAA,CAAA,EAAA,GAAA,MAAA,CAAO,KAAA,KAAP,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,MAAA,EAAe,UAAA,EAAY,GAAG,IAAA,CAAA;AAAA,MAAA,CAAA;AAAA,MAClD,IAAA,EAAM,IAAI,IAAA,KAAM;AAjatB,QAAA,IAAA,EAAA;AAiayB,QAAA,OAAA,CAAA,EAAA,GAAA,MAAA,CAAO,IAAA,KAAP,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,MAAA,EAAc,UAAA,EAAY,GAAG,IAAA,CAAA;AAAA,MAAA,CAAA;AAAA,MAChD,IAAA,EAAM,IAAI,IAAA,KAAM;AAlatB,QAAA,IAAA,EAAA;AAkayB,QAAA,OAAA,CAAA,EAAA,GAAA,MAAA,CAAO,IAAA,KAAP,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,MAAA,EAAc,UAAA,EAAY,GAAG,IAAA,CAAA;AAAA,MAAA,CAAA;AAAA,MAChD,KAAA,EAAO,IAAI,IAAA,KAAM;AAnavB,QAAA,IAAA,EAAA;AAma0B,QAAA,OAAA,CAAA,EAAA,GAAA,MAAA,CAAO,KAAA,KAAP,IAAA,GAAA,MAAA,GAAA,EAAA,CAAA,IAAA,CAAA,MAAA,EAAe,UAAA,EAAY,GAAG,IAAA,CAAA;AAAA,MAAA,CAAA;AAAA,MAClD,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,UAAU,MAAA,CAAO;AAAA,KACnB,CAAA;AAAA,EACF;AACF;AA0BO,SAAS,aAAA,CACd,KACA,QAAA,EACe;AACf,EAAA,IAAI,WAAA,GAAoC,IAAA;AAExC,EAAA,OAAO,CAAO,GAAA,KAAiB,OAAA,CAAA,IAAA,EAAA,IAAA,EAAA,aAAA;AAC7B,IAAA,IAAI;AACF,MAAA,IAAI,CAAC,WAAA,EAAa;AAChB,QAAA,WAAA,GAAc,IAAI,IAAA,EAAK;AAAA,MACzB;AACA,MAAA,MAAM,WAAA;AAEN,MAAA,QAAA,CAAS,KAAK,GAAG,CAAA;AACjB,MAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,KAAA,EAAM;AACrC,MAAA,OAAO,QAAQ,GAAG,CAAA;AAAA,IACpB,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,MAAA,GAAS,SAAS,SAAA,EAAU;AAClC,MAAA,MAAA,CAAO,KAAA,CAAM,cAAA,CAAe,oBAAA,EAAsB,KAAK,CAAA;AACvD,MAAA,OAAO,IAAI,QAAA;AAAA,QACT,KAAK,SAAA,CAAU;AAAA,UACb,OAAO,cAAA,CAAe,6BAAA;AAAA,UACtB,IAAA,EAAM,eAAe,KAAA,CAAM;AAAA,SAC5B,CAAA;AAAA,QACD,EAAE,MAAA,EAAQ,GAAA,EAAK,SAAS,EAAE,cAAA,EAAgB,oBAAmB;AAAE,OACjE;AAAA,IACF;AAAA,EACF,CAAA,CAAA;AACF","file":"index.mjs","sourcesContent":["// Error messages constants\nexport const ERROR_MESSAGES = {\n // VercelReceiver errors\n SIGNING_SECRET_REQUIRED:\n \"SLACK_SIGNING_SECRET is required for VercelReceiver\",\n APP_NOT_INITIALIZED: \"App not initialized\",\n REQUEST_TIMEOUT: \"Request timeout\",\n EVENT_NOT_ACKNOWLEDGED: \"Event not acknowledged within timeout period\",\n\n // Header validation errors\n MISSING_REQUIRED_HEADER: (header: string) =>\n `Missing required header: ${header}`,\n\n // Generic fallback errors\n REQUEST_VERIFICATION_FAILED: \"Request verification failed\",\n INTERNAL_SERVER_ERROR: \"Internal server error\",\n INTERNAL_SERVER_ERROR_HANDLER: \"Internal Server Error\",\n ACKNOWLEDGMENT_ERROR: \"Error in acknowledgment handler\",\n CREATE_HANDLER_ERROR: \"Error in createHandler:\",\n\n // Error type names\n TYPES: {\n VERCEL_RECEIVER_ERROR: \"VercelReceiverError\",\n SIGNATURE_VERIFICATION_ERROR: \"SignatureVerificationError\",\n REQUEST_PARSING_ERROR: \"RequestParsingError\",\n UNEXPECTED_ERROR: \"UnexpectedError\",\n HANDLER_ERROR: \"HandlerError\",\n },\n} as const;\n\nexport class VercelReceiverError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number = 500,\n ) {\n super(message);\n this.name = ERROR_MESSAGES.TYPES.VERCEL_RECEIVER_ERROR;\n }\n}\n\nexport class RequestParsingError extends VercelReceiverError {\n constructor(message: string = \"Failed to parse request\") {\n super(message, 400);\n this.name = ERROR_MESSAGES.TYPES.REQUEST_PARSING_ERROR;\n }\n}\n\n/**\n * Determines the appropriate HTTP status code for a given error.\n * @param error The error to get status code for\n * @returns HTTP status code\n */\nexport function getStatusCode(error: unknown): number {\n if (error instanceof VercelReceiverError) {\n return error.statusCode;\n }\n\n // External error types from @slack/bolt\n if (error && typeof error === \"object\") {\n const errorName =\n error.constructor?.name || (error as { name?: string }).name;\n switch (errorName) {\n case \"ReceiverAuthenticityError\":\n return 401;\n case \"ReceiverMultipleAckError\":\n return 500;\n case \"RequestParsingError\":\n return 400;\n case \"SignatureVerificationError\":\n return 400;\n default:\n return 500;\n }\n }\n\n return 500;\n}\n\n/**\n * Gets the error message for response.\n * @param error The error to get message for\n * @returns Error message string\n */\nexport function getErrorMessage(error: unknown): string {\n if (error && typeof error === \"object\" && \"message\" in error) {\n return String(error.message);\n }\n return ERROR_MESSAGES.INTERNAL_SERVER_ERROR;\n}\n\n/**\n * Gets the error type for response.\n * @param error The error to get type for\n * @returns Error type string\n */\nexport function getErrorType(error: unknown): string {\n if (error && typeof error === \"object\") {\n const ctorName = (error as { constructor?: { name?: string } }).constructor\n ?.name;\n const nameProp = (error as { name?: string }).name;\n const errorName =\n ctorName ?? nameProp ?? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;\n // Use \"UnexpectedError\" for generic Error instances, otherwise use the actual name\n return errorName === \"Error\"\n ? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR\n : errorName;\n }\n return ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;\n}\n","import {\n type AckFn,\n type App,\n type Receiver,\n ReceiverAuthenticityError,\n type ReceiverEvent,\n ReceiverMultipleAckError,\n type StringIndexed,\n verifySlackRequest,\n} from \"@slack/bolt\";\nimport { ConsoleLogger, type Logger, LogLevel } from \"@slack/logger\";\nimport { waitUntil } from \"@vercel/functions\";\nimport {\n ERROR_MESSAGES,\n getErrorMessage,\n getErrorType,\n getStatusCode,\n RequestParsingError,\n VercelReceiverError,\n} from \"./errors\";\n\n// Types\n/**\n * A function to handle the request from the Slack app.\n * @param req - The request from the Slack app.\n * @returns A response object.\n */\nexport type VercelHandler = (req: Request) => Promise<Response>;\n\n/**\n * Configuration options for the VercelReceiver.\n * @property signingSecret - The signing secret for the Slack app.\n * @property signatureVerification - If true, verifies the Slack request signature.\n * @property logger - The logger to use for the VercelReceiver.\n * @property logLevel - The log level to use for the VercelReceiver.\n * @property customPropertiesExtractor - A function to extract custom properties from the request.\n */\nexport interface VercelReceiverOptions {\n /**\n * The signing secret for the Slack app.\n * @default process.env.SLACK_SIGNING_SECRET\n */\n signingSecret?: string;\n /**\n * If true, verifies the Slack request signature.\n * @default true\n */\n signatureVerification?: boolean;\n /**\n * The logger to use for the VercelReceiver.\n * @default new ConsoleLogger()\n */\n logger?: Logger;\n /**\n * The log level to use for the VercelReceiver.\n * @default LogLevel.INFO\n */\n logLevel?: LogLevel;\n /**\n * A function to extract custom properties from incoming events.\n * @default undefined\n * @returns An object with custom properties.\n */\n customPropertiesExtractor?: (req: Request) => StringIndexed;\n /**\n * The timeout in milliseconds for event acknowledgment.\n * @default 3001\n */\n ackTimeoutMs?: number;\n}\n\nconst LOG_PREFIX = \"[@vercel/slack-bolt]\";\nconst ACK_TIMEOUT_MS = 3001;\nconst SLACK_RETRY_NUM_HEADER = \"x-slack-retry-num\";\nconst SLACK_RETRY_REASON_HEADER = \"x-slack-retry-reason\";\nconst SLACK_TIMESTAMP_HEADER = \"x-slack-request-timestamp\";\nconst SLACK_SIGNATURE_HEADER = \"x-slack-signature\";\n\n/**\n * A Slack Bolt receiver implementation designed for Vercel's serverless environment.\n * Handles Slack events, interactions, and slash commands with automatic request verification,\n * background processing, and timeout management.\n *\n * @example\n * ```typescript\n * import { App } from '@slack/bolt';\n * import { VercelReceiver, createHandler } from '@vercel/slack-bolt';\n *\n * const receiver = new VercelReceiver();\n *\n * const app = new App({\n * receiver,\n * token: process.env.SLACK_BOT_TOKEN,\n * signingSecret: process.env.SLACK_SIGNING_SECRET,\n * });\n * ```\n *\n */\nexport class VercelReceiver implements Receiver {\n private readonly signingSecret: string;\n private readonly signatureVerification: boolean;\n private readonly logger: Logger;\n private readonly customPropertiesExtractor?: (req: Request) => StringIndexed;\n private readonly ackTimeoutMs: number;\n private app?: App;\n\n /**\n * Gets the logger instance used by this receiver.\n * @returns The logger instance\n */\n public getLogger(): Logger {\n return this.logger;\n }\n\n /**\n * Creates a new VercelReceiver instance.\n *\n * @param options - Configuration options for the receiver\n * @throws {VercelReceiverError} When signing secret is not provided\n *\n * @example\n * ```typescript\n * const receiver = new VercelReceiver();\n * ```\n */\n public constructor({\n signingSecret = process.env.SLACK_SIGNING_SECRET,\n signatureVerification = true,\n logger,\n logLevel = LogLevel.INFO,\n customPropertiesExtractor,\n ackTimeoutMs = ACK_TIMEOUT_MS,\n }: VercelReceiverOptions = {}) {\n if (!signingSecret) {\n throw new VercelReceiverError(ERROR_MESSAGES.SIGNING_SECRET_REQUIRED);\n }\n\n this.signingSecret = signingSecret;\n this.signatureVerification = signatureVerification;\n this.logger = this.createScopedLogger(\n logger ?? new ConsoleLogger(),\n logLevel,\n );\n this.customPropertiesExtractor = customPropertiesExtractor;\n this.ackTimeoutMs = ackTimeoutMs;\n\n this.logger.debug(\"VercelReceiver initialized\");\n }\n\n /**\n * Initializes the receiver with a Slack Bolt app instance.\n * This method is called automatically by the Bolt framework.\n *\n * @param app - The Slack Bolt app instance\n */\n public init(app: App): void {\n this.app = app;\n this.logger.debug(\"App initialized in VercelReceiver\");\n }\n\n /**\n * Starts the receiver and returns a handler function for processing requests.\n * This method is called automatically by the Bolt framework.\n *\n * @returns A handler function that processes incoming Slack requests\n */\n public async start(): Promise<VercelHandler> {\n this.logger.debug(\"VercelReceiver started\");\n return this.toHandler();\n }\n\n /**\n * Stops the receiver. This method is called automatically by the Bolt framework.\n */\n public async stop(): Promise<void> {\n this.logger.debug(\"VercelReceiver stopped\");\n }\n\n /**\n * Creates a handler function that processes incoming Slack requests.\n * This is the main entry point for handling Slack events in Vercel.\n * It is called automatically by the Bolt framework in the start() method.\n *\n * @returns A handler function compatible with Vercel's function signature\n */\n public toHandler(): VercelHandler {\n return async (req: Request): Promise<Response> => {\n try {\n const rawBody = await req.text();\n\n if (this.signatureVerification) {\n this.verifyRequest(req, rawBody);\n }\n\n const body = await this.parseRequestBody(req, rawBody);\n\n if (body.type === \"url_verification\") {\n this.logger.debug(\"Handling URL verification challenge\");\n return Response.json({ challenge: body.challenge });\n }\n\n return await this.handleSlackEvent(req, body);\n } catch (error) {\n return this.handleError(error);\n }\n };\n }\n\n private async parseRequestBody(\n req: Request,\n rawBody: string,\n ): Promise<StringIndexed> {\n const contentType = req.headers.get(\"content-type\");\n\n try {\n if (contentType === \"application/x-www-form-urlencoded\") {\n const parsedBody: StringIndexed = {};\n const params = new URLSearchParams(rawBody);\n\n for (const [key, value] of params.entries()) {\n parsedBody[key] = value;\n }\n\n if (typeof parsedBody.payload === \"string\") {\n return JSON.parse(parsedBody.payload);\n }\n return parsedBody;\n }\n if (contentType === \"application/json\") {\n return JSON.parse(rawBody);\n }\n\n this.logger.warn(`Unexpected content-type detected: ${contentType}`);\n\n return JSON.parse(rawBody);\n } catch (e) {\n throw new RequestParsingError(\n `Failed to parse body as JSON data for content-type: ${contentType}. Error: ${\n e instanceof Error ? e.message : String(e)\n }`,\n );\n }\n }\n\n private async handleSlackEvent(\n req: Request,\n body: StringIndexed,\n ): Promise<Response> {\n if (!this.app) {\n throw new VercelReceiverError(ERROR_MESSAGES.APP_NOT_INITIALIZED, 500);\n }\n\n let isAcknowledged = false;\n let responseResolver: (value: Response) => void;\n let responseRejecter: (error: Error) => void;\n\n const responsePromise = new Promise<Response>((resolve, reject) => {\n responseResolver = resolve;\n responseRejecter = reject;\n });\n\n // Slack requires an acknowledgment from your app within 3 seconds\n const timeoutId = setTimeout(() => {\n if (!isAcknowledged) {\n this.logger.error(ERROR_MESSAGES.EVENT_NOT_ACKNOWLEDGED);\n const error = new VercelReceiverError(\n ERROR_MESSAGES.REQUEST_TIMEOUT,\n 408,\n );\n responseRejecter(error);\n }\n }, this.ackTimeoutMs);\n\n // Create acknowledgment function\n const ackFn: AckFn<StringIndexed> = async (responseBody) => {\n this.logger.debug(`ack() call begins (body: ${responseBody})`);\n if (isAcknowledged) {\n throw new ReceiverMultipleAckError();\n }\n\n isAcknowledged = true;\n clearTimeout(timeoutId);\n\n try {\n let body: string | undefined;\n if (typeof responseBody === \"undefined\") {\n body = undefined;\n } else if (typeof responseBody === \"string\") {\n body = responseBody;\n } else {\n body = JSON.stringify(responseBody);\n }\n const response = new Response(body, {\n status: 200,\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n responseResolver(response);\n } catch (error) {\n this.logger.error(ERROR_MESSAGES.ACKNOWLEDGMENT_ERROR, error);\n responseRejecter(\n error instanceof Error ? error : new Error(String(error)),\n );\n }\n };\n\n const event = this.createSlackReceiverEvent({\n body,\n headers: req.headers,\n ack: ackFn,\n request: req,\n });\n\n // Process event in background using waitUntil from Vercel Functions\n // https://vercel.com/docs/functions/functions-api-reference/vercel-functions-package#waituntil\n waitUntil(\n this.app.processEvent(event).catch((error) => {\n return this.handleError(error);\n }),\n );\n\n try {\n return await responsePromise;\n } catch (error) {\n return this.handleError(error);\n }\n }\n\n private verifyRequest(req: Request, body: string): void {\n const timestamp = req.headers.get(SLACK_TIMESTAMP_HEADER);\n const signature = req.headers.get(SLACK_SIGNATURE_HEADER);\n\n if (!signature) {\n throw new ReceiverAuthenticityError(\n ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_SIGNATURE_HEADER),\n );\n }\n\n if (!timestamp) {\n throw new ReceiverAuthenticityError(\n ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_TIMESTAMP_HEADER),\n );\n }\n\n try {\n verifySlackRequest({\n signingSecret: this.signingSecret,\n body,\n headers: {\n \"x-slack-signature\": signature,\n \"x-slack-request-timestamp\": Number.parseInt(timestamp, 10),\n },\n logger: this.logger,\n });\n } catch (error) {\n throw new ReceiverAuthenticityError(\n error instanceof Error\n ? error.message\n : \"Failed to verify request signature\",\n );\n }\n }\n\n private createSlackReceiverEvent({\n body,\n headers,\n ack,\n request,\n }: {\n body: StringIndexed;\n headers: Headers;\n ack: AckFn<StringIndexed>;\n request: Request;\n }): ReceiverEvent {\n const customProperties = this.customPropertiesExtractor\n ? this.customPropertiesExtractor(request)\n : {};\n\n const retryNum = headers.get(SLACK_RETRY_NUM_HEADER) || \"0\";\n\n const retryReason = headers.get(SLACK_RETRY_REASON_HEADER) || \"\";\n\n return {\n body,\n ack,\n retryNum: Number(retryNum),\n retryReason,\n customProperties,\n };\n }\n\n public handleError(error: unknown): Response {\n const errorMessage = getErrorMessage(error);\n const errorType = getErrorType(error);\n const errorStatusCode = getStatusCode(error);\n\n this.logger.error(error);\n return new Response(\n JSON.stringify({\n error: errorMessage,\n type: errorType,\n }),\n {\n status: errorStatusCode,\n headers: { \"content-type\": \"application/json\" },\n },\n );\n }\n\n private createScopedLogger(logger: Logger, logLevel: LogLevel): Logger {\n logger.setLevel(logLevel);\n\n return {\n ...logger,\n error: (...args) => logger.error?.(LOG_PREFIX, ...args),\n warn: (...args) => logger.warn?.(LOG_PREFIX, ...args),\n info: (...args) => logger.info?.(LOG_PREFIX, ...args),\n debug: (...args) => logger.debug?.(LOG_PREFIX, ...args),\n setLevel: logger.setLevel,\n getLevel: logger.getLevel,\n };\n }\n}\n\n/**\n * Creates a Vercel-compatible handler function for a Slack Bolt app.\n * This is the recommended way to create handlers for deployment on Vercel.\n *\n * @param {App} app - The initialized Slack Bolt app instance.\n * @param {VercelReceiver} receiver - The VercelReceiver instance.\n * @returns {VercelHandler} A handler function compatible with Vercel's function signature.\n *\n * @example\n * ```typescript\n * // api/events.ts\n * import { createHandler } from '@vercel/slack-bolt';\n * import { app, receiver } from '../app';\n *\n * const handler = createHandler(app, receiver);\n *\n * export const POST = async (req: Request) => {\n * return handler(req);\n * };\n * ```\n *\n * @throws {Error} If app initialization fails.\n * @throws {VercelReceiverError} If request processing fails.\n */\nexport function createHandler(\n app: App,\n receiver: VercelReceiver,\n): VercelHandler {\n let initPromise: Promise<void> | null = null;\n\n return async (req: Request) => {\n try {\n if (!initPromise) {\n initPromise = app.init();\n }\n await initPromise;\n\n receiver.init(app);\n const handler = await receiver.start();\n return handler(req);\n } catch (error) {\n const logger = receiver.getLogger();\n logger.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);\n return new Response(\n JSON.stringify({\n error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,\n type: ERROR_MESSAGES.TYPES.HANDLER_ERROR,\n }),\n { status: 500, headers: { \"content-type\": \"application/json\" } },\n );\n }\n };\n}\n"]}
|
package/package.json
CHANGED