@vercel/slack-bolt 1.0.0 → 1.0.2
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/README.md +41 -86
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/README.md
CHANGED
|
@@ -2,34 +2,28 @@
|
|
|
2
2
|
|
|
3
3
|
A custom [Slack Bolt](https://slack.dev/bolt-js/) receiver built for Vercel's [Fluid Compute](https://vercel.com/docs/fluid-compute).
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
- **Easy integration:** Use with your existing Bolt app code
|
|
7
|
-
- **Customizable:** Supports custom response handlers and property extraction
|
|
8
|
-
- **TypeScript ready:** Fully typed for modern development
|
|
9
|
-
- **Node.js Compatible:** The library is compatible with any framework or function using the Node.js Request object.
|
|
5
|
+
## Getting Started
|
|
10
6
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
pnpm add @vercel/slack-bolt @slack/bolt
|
|
15
|
-
```
|
|
7
|
+
Visit our [template](https://vercel.com/templates/backend/slack-bolt-with-nitro) to get started building a Slack app.
|
|
16
8
|
|
|
17
|
-
## Quick Start
|
|
18
|
-
|
|
19
|
-
### 1. Environment Setup
|
|
20
|
-
|
|
21
|
-
Add your `SLACK_SIGNING_SECRET` and `SLACK_BOT_TOKEN` to your environment variables:
|
|
22
9
|
|
|
10
|
+
## Installation
|
|
23
11
|
```bash
|
|
24
|
-
|
|
25
|
-
|
|
12
|
+
npm install @vercel/slack-bolt
|
|
13
|
+
# or
|
|
14
|
+
yarn add @vercel/slack-bolt
|
|
15
|
+
# or
|
|
16
|
+
pnpm add @vercel/slack-bolt
|
|
17
|
+
# or
|
|
18
|
+
bun add @vercel/slack-bolt
|
|
26
19
|
```
|
|
27
20
|
|
|
28
|
-
|
|
21
|
+
## API Reference
|
|
29
22
|
|
|
30
|
-
|
|
31
|
-
|
|
23
|
+
### `VercelReceiver`
|
|
24
|
+
Responsible for handling and parsing any incoming requests from Slack and then forwarding them to your Bolt app for event processing.
|
|
32
25
|
|
|
26
|
+
```typescript
|
|
33
27
|
import { App } from "@slack/bolt";
|
|
34
28
|
import { VercelReceiver } from "@vercel/slack-bolt";
|
|
35
29
|
|
|
@@ -48,84 +42,45 @@ app.message(/^(hi|hello|hey).*/, async ({ say }) => {
|
|
|
48
42
|
|
|
49
43
|
export { app, receiver };
|
|
50
44
|
```
|
|
45
|
+
#### Parameters
|
|
51
46
|
|
|
52
|
-
|
|
47
|
+
| Name | Type | Default Value | Required | Description |
|
|
48
|
+
| --- | --- | --- | --- | --- |
|
|
49
|
+
| `signingSecret` | `string` | `process.env.SLACK_SIGNING_SECRET` | No<sup>1</sup> | Signing secret for your Slack app used to verify requests. |
|
|
50
|
+
| `signatureVerification` | `boolean` | `true` | No | Enable or disable request signature verification. |
|
|
51
|
+
| `logger` | `Logger`<sup>2</sup> | `new ConsoleLogger()` | No | Logger used for diagnostics. |
|
|
52
|
+
| `logLevel` | `LogLevel`<sup>2</sup> | `LogLevel.INFO` | No | Minimum log level for the logger. |
|
|
53
|
+
| `customPropertiesExtractor` | `(req: Request) => StringIndexed` | `undefined` | No | Return value is merged into Bolt event `customProperties`<sup>2</sup>. |
|
|
54
|
+
| `ackTimeoutMs` | `number` | `3001` | No | Milliseconds to wait for `ack()` before returning a timeout error. |
|
|
53
55
|
|
|
54
|
-
|
|
56
|
+
<sup>1</sup> Optional if `process.env.SLACK_SIGNING_SECRET` is provided.
|
|
55
57
|
|
|
56
|
-
|
|
57
|
-
root/
|
|
58
|
-
├── api/
|
|
59
|
-
│ └── events.ts # Vercel API endpoint to handle requests
|
|
60
|
-
├── app.ts # Bolt app
|
|
61
|
-
├── package.json
|
|
62
|
-
└── .env # Environment variables
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### 4. Create a POST request handler using `createHandler` from `@vercel/slack-bolt`
|
|
66
|
-
|
|
67
|
-
```typescript
|
|
68
|
-
// api/events.ts
|
|
58
|
+
<sup>2</sup> Provided by the [`@slack/bolt`](https://www.npmjs.com/package/@slack/bolt) library. More information [here](https://docs.slack.dev/tools/bolt-js/reference#app-options).
|
|
69
59
|
|
|
70
|
-
import { createHandler } from "@vercel/slack-bolt";
|
|
71
|
-
import { app, receiver } from "../app";
|
|
72
60
|
|
|
73
|
-
|
|
61
|
+
### `createHandler`
|
|
62
|
+
A function that returns a Vercel-compatible request handler that will initialize and start your Bolt app to process the event.
|
|
74
63
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
};
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
> **Note:**
|
|
81
|
-
> The `handler` returned by `createHandler` works with standard Node.js `Request` objects.
|
|
82
|
-
> You can use it directly in your Vercel API routes or with any framework that provides compatible request objects.
|
|
83
|
-
|
|
84
|
-
### 5. Update your Slack App Manifest
|
|
85
|
-
|
|
86
|
-
- Disable socket mode on your app
|
|
87
|
-
- Update your `request_url` to match your Vercel deployment
|
|
88
|
-
- If using features such as `commands`, `shortcuts`, and `interactivity` you must update their `urls` as well.
|
|
89
|
-
|
|
90
|
-
See the [example](./manifest.example.json) for reference.
|
|
91
|
-
|
|
92
|
-
## Local Development
|
|
93
|
-
|
|
94
|
-
This package is compatible with the Slack CLI and can be used with the `slack run` command.
|
|
95
|
-
|
|
96
|
-
### 1. Update the `start` command in your `./slack/hooks.json` file
|
|
97
|
-
|
|
98
|
-
```jsonc
|
|
99
|
-
// ./slack/hooks.json
|
|
100
|
-
{
|
|
101
|
-
"hooks": {
|
|
102
|
-
"get-hooks": "npx -q --no-install -p @slack/cli-hooks slack-cli-get-hooks",
|
|
103
|
-
"start": "vc dev" // or the start command for your framework
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
64
|
+
```typescript
|
|
65
|
+
// An example using Next.js route handlers
|
|
107
66
|
|
|
108
|
-
|
|
67
|
+
import { createHandler } from "@vercel/slack-bolt"
|
|
68
|
+
import { app, receiver } from "./app"
|
|
109
69
|
|
|
110
|
-
|
|
111
|
-
{
|
|
112
|
-
// ./slack/config.json
|
|
113
|
-
"manifest": {
|
|
114
|
-
"source": "local" // remote pulls the manifest from your Slack's remote manifest
|
|
115
|
-
},
|
|
116
|
-
"project_id": "<your-project-id>"
|
|
117
|
-
}
|
|
70
|
+
export const POST = createHandler(app, receiver)
|
|
118
71
|
```
|
|
119
72
|
|
|
120
|
-
|
|
73
|
+
#### Parameters
|
|
121
74
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
75
|
+
| Name | Type | Required | Description |
|
|
76
|
+
|-------------|-------------|----------|----------------------------------------------------------------------|
|
|
77
|
+
| `app` | `App`<sup>1</sup> | Yes | Your Bolt app |
|
|
78
|
+
| `receiver` | `VercelReceiver` | Yes | The Vercel receiver instance used to process Slack requests. |
|
|
125
79
|
|
|
126
|
-
|
|
80
|
+
<sup>1</sup> Provided by the [`@slack/bolt`](https://www.npmjs.com/package/@slack/bolt) library. More information [here](https://docs.slack.dev/tools/bolt-js/reference#app-options).
|
|
127
81
|
|
|
128
|
-
|
|
82
|
+
## Examples
|
|
83
|
+
Starter templates: [Next.js](https://github.com/vercel-labs/slack-bolt/tree/examples/examples/nextjs), [Hono](https://github.com/vercel-labs/slack-bolt/tree/examples/examples/hono), [Nitro](https://github.com/vercel-labs/slack-bolt/tree/examples/examples/nitro).
|
|
129
84
|
|
|
130
85
|
## Contributing
|
|
131
86
|
|
|
@@ -137,4 +92,4 @@ For issues and questions:
|
|
|
137
92
|
|
|
138
93
|
- Check the [Slack Bolt documentation](https://slack.dev/bolt-js/)
|
|
139
94
|
- Review [Vercel Functions documentation](https://vercel.com/docs/functions)
|
|
140
|
-
- Open an issue in this repository
|
|
95
|
+
- [Open an issue](https://github.com/vercel-labs/slack-bolt/issues) in this repository
|
package/dist/index.js
CHANGED
|
@@ -417,8 +417,7 @@ function createHandler(app, receiver) {
|
|
|
417
417
|
const handler = yield receiver.start();
|
|
418
418
|
return handler(req);
|
|
419
419
|
} catch (error) {
|
|
420
|
-
|
|
421
|
-
logger.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);
|
|
420
|
+
console.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);
|
|
422
421
|
return new Response(
|
|
423
422
|
JSON.stringify({
|
|
424
423
|
error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,
|
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\") {\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"]}
|
|
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 // if app.init fails, we use console.error instead of logger.error because the logger is not available\n console.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
|
@@ -415,8 +415,7 @@ function createHandler(app, receiver) {
|
|
|
415
415
|
const handler = yield receiver.start();
|
|
416
416
|
return handler(req);
|
|
417
417
|
} catch (error) {
|
|
418
|
-
|
|
419
|
-
logger.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);
|
|
418
|
+
console.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);
|
|
420
419
|
return new Response(
|
|
421
420
|
JSON.stringify({
|
|
422
421
|
error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,
|
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\") {\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"]}
|
|
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\") {\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 // if app.init fails, we use console.error instead of logger.error because the logger is not available\n console.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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/slack-bolt",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"description": "A Vercel receiver for building Slack apps with Bolt and deploying them to Vercel",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@slack/logger": "^4.0.0",
|
|
37
|
-
"@vercel/functions": "^
|
|
37
|
+
"@vercel/functions": "^3.1.0"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@biomejs/biome": "2.2.2",
|
|
41
|
-
"@changesets/cli": "^2.29.
|
|
42
|
-
"@types/node": "^24.
|
|
41
|
+
"@changesets/cli": "^2.29.7",
|
|
42
|
+
"@types/node": "^24.4.0",
|
|
43
43
|
"husky": "^9.1.7",
|
|
44
44
|
"tsup": "^8.5.0",
|
|
45
45
|
"typescript": "^5.9.2",
|