@vercel/slack-bolt 0.1.2 → 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 +9 -3
- package/dist/index.d.ts +9 -3
- package/dist/index.js +131 -76
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +132 -77
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -7
package/dist/index.d.mts
CHANGED
|
@@ -42,6 +42,11 @@ interface VercelReceiverOptions {
|
|
|
42
42
|
* @returns An object with custom properties.
|
|
43
43
|
*/
|
|
44
44
|
customPropertiesExtractor?: (req: Request) => StringIndexed;
|
|
45
|
+
/**
|
|
46
|
+
* The timeout in milliseconds for event acknowledgment.
|
|
47
|
+
* @default 3001
|
|
48
|
+
*/
|
|
49
|
+
ackTimeoutMs?: number;
|
|
45
50
|
}
|
|
46
51
|
/**
|
|
47
52
|
* A Slack Bolt receiver implementation designed for Vercel's serverless environment.
|
|
@@ -68,6 +73,7 @@ declare class VercelReceiver implements Receiver {
|
|
|
68
73
|
private readonly signatureVerification;
|
|
69
74
|
private readonly logger;
|
|
70
75
|
private readonly customPropertiesExtractor?;
|
|
76
|
+
private readonly ackTimeoutMs;
|
|
71
77
|
private app?;
|
|
72
78
|
/**
|
|
73
79
|
* Gets the logger instance used by this receiver.
|
|
@@ -85,7 +91,7 @@ declare class VercelReceiver implements Receiver {
|
|
|
85
91
|
* const receiver = new VercelReceiver();
|
|
86
92
|
* ```
|
|
87
93
|
*/
|
|
88
|
-
constructor({ signingSecret, signatureVerification, logger, logLevel, customPropertiesExtractor, }?: VercelReceiverOptions);
|
|
94
|
+
constructor({ signingSecret, signatureVerification, logger, logLevel, customPropertiesExtractor, ackTimeoutMs, }?: VercelReceiverOptions);
|
|
89
95
|
/**
|
|
90
96
|
* Initializes the receiver with a Slack Bolt app instance.
|
|
91
97
|
* This method is called automatically by the Bolt framework.
|
|
@@ -114,9 +120,9 @@ declare class VercelReceiver implements Receiver {
|
|
|
114
120
|
toHandler(): VercelHandler;
|
|
115
121
|
private parseRequestBody;
|
|
116
122
|
private handleSlackEvent;
|
|
117
|
-
private
|
|
123
|
+
private verifyRequest;
|
|
118
124
|
private createSlackReceiverEvent;
|
|
119
|
-
|
|
125
|
+
handleError(error: unknown): Response;
|
|
120
126
|
private createScopedLogger;
|
|
121
127
|
}
|
|
122
128
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -42,6 +42,11 @@ interface VercelReceiverOptions {
|
|
|
42
42
|
* @returns An object with custom properties.
|
|
43
43
|
*/
|
|
44
44
|
customPropertiesExtractor?: (req: Request) => StringIndexed;
|
|
45
|
+
/**
|
|
46
|
+
* The timeout in milliseconds for event acknowledgment.
|
|
47
|
+
* @default 3001
|
|
48
|
+
*/
|
|
49
|
+
ackTimeoutMs?: number;
|
|
45
50
|
}
|
|
46
51
|
/**
|
|
47
52
|
* A Slack Bolt receiver implementation designed for Vercel's serverless environment.
|
|
@@ -68,6 +73,7 @@ declare class VercelReceiver implements Receiver {
|
|
|
68
73
|
private readonly signatureVerification;
|
|
69
74
|
private readonly logger;
|
|
70
75
|
private readonly customPropertiesExtractor?;
|
|
76
|
+
private readonly ackTimeoutMs;
|
|
71
77
|
private app?;
|
|
72
78
|
/**
|
|
73
79
|
* Gets the logger instance used by this receiver.
|
|
@@ -85,7 +91,7 @@ declare class VercelReceiver implements Receiver {
|
|
|
85
91
|
* const receiver = new VercelReceiver();
|
|
86
92
|
* ```
|
|
87
93
|
*/
|
|
88
|
-
constructor({ signingSecret, signatureVerification, logger, logLevel, customPropertiesExtractor, }?: VercelReceiverOptions);
|
|
94
|
+
constructor({ signingSecret, signatureVerification, logger, logLevel, customPropertiesExtractor, ackTimeoutMs, }?: VercelReceiverOptions);
|
|
89
95
|
/**
|
|
90
96
|
* Initializes the receiver with a Slack Bolt app instance.
|
|
91
97
|
* This method is called automatically by the Bolt framework.
|
|
@@ -114,9 +120,9 @@ declare class VercelReceiver implements Receiver {
|
|
|
114
120
|
toHandler(): VercelHandler;
|
|
115
121
|
private parseRequestBody;
|
|
116
122
|
private handleSlackEvent;
|
|
117
|
-
private
|
|
123
|
+
private verifyRequest;
|
|
118
124
|
private createSlackReceiverEvent;
|
|
119
|
-
|
|
125
|
+
handleError(error: unknown): Response;
|
|
120
126
|
private createScopedLogger;
|
|
121
127
|
}
|
|
122
128
|
/**
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var functions = require('@vercel/functions');
|
|
4
3
|
var bolt = require('@slack/bolt');
|
|
5
4
|
var logger = require('@slack/logger');
|
|
5
|
+
var functions = require('@vercel/functions');
|
|
6
6
|
|
|
7
7
|
var __defProp = Object.defineProperty;
|
|
8
8
|
var __defProps = Object.defineProperties;
|
|
@@ -45,26 +45,83 @@ var __async = (__this, __arguments, generator) => {
|
|
|
45
45
|
};
|
|
46
46
|
|
|
47
47
|
// src/errors.ts
|
|
48
|
+
var ERROR_MESSAGES = {
|
|
49
|
+
// VercelReceiver errors
|
|
50
|
+
SIGNING_SECRET_REQUIRED: "SLACK_SIGNING_SECRET is required for VercelReceiver",
|
|
51
|
+
APP_NOT_INITIALIZED: "App not initialized",
|
|
52
|
+
REQUEST_TIMEOUT: "Request timeout",
|
|
53
|
+
EVENT_NOT_ACKNOWLEDGED: "Event not acknowledged within timeout period",
|
|
54
|
+
// Header validation errors
|
|
55
|
+
MISSING_REQUIRED_HEADER: (header) => `Missing required header: ${header}`,
|
|
56
|
+
// Generic fallback errors
|
|
57
|
+
REQUEST_VERIFICATION_FAILED: "Request verification failed",
|
|
58
|
+
INTERNAL_SERVER_ERROR: "Internal server error",
|
|
59
|
+
INTERNAL_SERVER_ERROR_HANDLER: "Internal Server Error",
|
|
60
|
+
ACKNOWLEDGMENT_ERROR: "Error in acknowledgment handler",
|
|
61
|
+
CREATE_HANDLER_ERROR: "Error in createHandler:",
|
|
62
|
+
// Error type names
|
|
63
|
+
TYPES: {
|
|
64
|
+
VERCEL_RECEIVER_ERROR: "VercelReceiverError",
|
|
65
|
+
SIGNATURE_VERIFICATION_ERROR: "SignatureVerificationError",
|
|
66
|
+
REQUEST_PARSING_ERROR: "RequestParsingError",
|
|
67
|
+
UNEXPECTED_ERROR: "UnexpectedError",
|
|
68
|
+
HANDLER_ERROR: "HandlerError"
|
|
69
|
+
}
|
|
70
|
+
};
|
|
48
71
|
var VercelReceiverError = class extends Error {
|
|
49
72
|
constructor(message, statusCode = 500) {
|
|
50
73
|
super(message);
|
|
51
74
|
this.statusCode = statusCode;
|
|
52
|
-
this.name =
|
|
53
|
-
}
|
|
54
|
-
};
|
|
55
|
-
var SignatureVerificationError = class extends VercelReceiverError {
|
|
56
|
-
constructor(message = "Invalid request signature") {
|
|
57
|
-
super(message, 401);
|
|
58
|
-
this.name = "SignatureVerificationError";
|
|
75
|
+
this.name = ERROR_MESSAGES.TYPES.VERCEL_RECEIVER_ERROR;
|
|
59
76
|
}
|
|
60
77
|
};
|
|
61
78
|
var RequestParsingError = class extends VercelReceiverError {
|
|
62
79
|
constructor(message = "Failed to parse request") {
|
|
63
80
|
super(message, 400);
|
|
64
|
-
this.name =
|
|
81
|
+
this.name = ERROR_MESSAGES.TYPES.REQUEST_PARSING_ERROR;
|
|
65
82
|
}
|
|
66
83
|
};
|
|
67
|
-
|
|
84
|
+
function getStatusCode(error) {
|
|
85
|
+
var _a;
|
|
86
|
+
if (error instanceof VercelReceiverError) {
|
|
87
|
+
return error.statusCode;
|
|
88
|
+
}
|
|
89
|
+
if (error && typeof error === "object") {
|
|
90
|
+
const errorName = ((_a = error.constructor) == null ? void 0 : _a.name) || error.name;
|
|
91
|
+
switch (errorName) {
|
|
92
|
+
case "ReceiverAuthenticityError":
|
|
93
|
+
return 401;
|
|
94
|
+
case "ReceiverMultipleAckError":
|
|
95
|
+
return 500;
|
|
96
|
+
case "RequestParsingError":
|
|
97
|
+
return 400;
|
|
98
|
+
case "SignatureVerificationError":
|
|
99
|
+
return 400;
|
|
100
|
+
default:
|
|
101
|
+
return 500;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return 500;
|
|
105
|
+
}
|
|
106
|
+
function getErrorMessage(error) {
|
|
107
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
108
|
+
return String(error.message);
|
|
109
|
+
}
|
|
110
|
+
return ERROR_MESSAGES.INTERNAL_SERVER_ERROR;
|
|
111
|
+
}
|
|
112
|
+
function getErrorType(error) {
|
|
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;
|
|
118
|
+
return errorName === "Error" ? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR : errorName;
|
|
119
|
+
}
|
|
120
|
+
return ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// src/index.ts
|
|
124
|
+
var LOG_PREFIX = "[@vercel/slack-bolt]";
|
|
68
125
|
var ACK_TIMEOUT_MS = 3001;
|
|
69
126
|
var SLACK_RETRY_NUM_HEADER = "x-slack-retry-num";
|
|
70
127
|
var SLACK_RETRY_REASON_HEADER = "x-slack-retry-reason";
|
|
@@ -94,12 +151,11 @@ var VercelReceiver = class {
|
|
|
94
151
|
signatureVerification = true,
|
|
95
152
|
logger: logger$1,
|
|
96
153
|
logLevel = logger.LogLevel.INFO,
|
|
97
|
-
customPropertiesExtractor
|
|
154
|
+
customPropertiesExtractor,
|
|
155
|
+
ackTimeoutMs = ACK_TIMEOUT_MS
|
|
98
156
|
} = {}) {
|
|
99
157
|
if (!signingSecret) {
|
|
100
|
-
throw new VercelReceiverError(
|
|
101
|
-
"SLACK_SIGNING_SECRET is required for VercelReceiver"
|
|
102
|
-
);
|
|
158
|
+
throw new VercelReceiverError(ERROR_MESSAGES.SIGNING_SECRET_REQUIRED);
|
|
103
159
|
}
|
|
104
160
|
this.signingSecret = signingSecret;
|
|
105
161
|
this.signatureVerification = signatureVerification;
|
|
@@ -108,6 +164,7 @@ var VercelReceiver = class {
|
|
|
108
164
|
logLevel
|
|
109
165
|
);
|
|
110
166
|
this.customPropertiesExtractor = customPropertiesExtractor;
|
|
167
|
+
this.ackTimeoutMs = ackTimeoutMs;
|
|
111
168
|
this.logger.debug("VercelReceiver initialized");
|
|
112
169
|
}
|
|
113
170
|
/**
|
|
@@ -152,7 +209,7 @@ var VercelReceiver = class {
|
|
|
152
209
|
try {
|
|
153
210
|
const rawBody = yield req.text();
|
|
154
211
|
if (this.signatureVerification) {
|
|
155
|
-
|
|
212
|
+
this.verifyRequest(req, rawBody);
|
|
156
213
|
}
|
|
157
214
|
const body = yield this.parseRequestBody(req, rawBody);
|
|
158
215
|
if (body.type === "url_verification") {
|
|
@@ -195,7 +252,7 @@ var VercelReceiver = class {
|
|
|
195
252
|
handleSlackEvent(req, body) {
|
|
196
253
|
return __async(this, null, function* () {
|
|
197
254
|
if (!this.app) {
|
|
198
|
-
throw new VercelReceiverError(
|
|
255
|
+
throw new VercelReceiverError(ERROR_MESSAGES.APP_NOT_INITIALIZED, 500);
|
|
199
256
|
}
|
|
200
257
|
let isAcknowledged = false;
|
|
201
258
|
let responseResolver;
|
|
@@ -206,11 +263,14 @@ var VercelReceiver = class {
|
|
|
206
263
|
});
|
|
207
264
|
const timeoutId = setTimeout(() => {
|
|
208
265
|
if (!isAcknowledged) {
|
|
209
|
-
this.logger.error(
|
|
210
|
-
const error = new VercelReceiverError(
|
|
266
|
+
this.logger.error(ERROR_MESSAGES.EVENT_NOT_ACKNOWLEDGED);
|
|
267
|
+
const error = new VercelReceiverError(
|
|
268
|
+
ERROR_MESSAGES.REQUEST_TIMEOUT,
|
|
269
|
+
408
|
|
270
|
+
);
|
|
211
271
|
responseRejecter(error);
|
|
212
272
|
}
|
|
213
|
-
},
|
|
273
|
+
}, this.ackTimeoutMs);
|
|
214
274
|
const ackFn = (responseBody) => __async(this, null, function* () {
|
|
215
275
|
this.logger.debug(`ack() call begins (body: ${responseBody})`);
|
|
216
276
|
if (isAcknowledged) {
|
|
@@ -235,7 +295,7 @@ var VercelReceiver = class {
|
|
|
235
295
|
});
|
|
236
296
|
responseResolver(response);
|
|
237
297
|
} catch (error) {
|
|
238
|
-
this.logger.error(
|
|
298
|
+
this.logger.error(ERROR_MESSAGES.ACKNOWLEDGMENT_ERROR, error);
|
|
239
299
|
responseRejecter(
|
|
240
300
|
error instanceof Error ? error : new Error(String(error))
|
|
241
301
|
);
|
|
@@ -247,7 +307,11 @@ var VercelReceiver = class {
|
|
|
247
307
|
ack: ackFn,
|
|
248
308
|
request: req
|
|
249
309
|
});
|
|
250
|
-
functions.waitUntil(
|
|
310
|
+
functions.waitUntil(
|
|
311
|
+
this.app.processEvent(event).catch((error) => {
|
|
312
|
+
return this.handleError(error);
|
|
313
|
+
})
|
|
314
|
+
);
|
|
251
315
|
try {
|
|
252
316
|
return yield responsePromise;
|
|
253
317
|
} catch (error) {
|
|
@@ -255,35 +319,34 @@ var VercelReceiver = class {
|
|
|
255
319
|
}
|
|
256
320
|
});
|
|
257
321
|
}
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
});
|
|
322
|
+
verifyRequest(req, body) {
|
|
323
|
+
const timestamp = req.headers.get(SLACK_TIMESTAMP_HEADER);
|
|
324
|
+
const signature = req.headers.get(SLACK_SIGNATURE_HEADER);
|
|
325
|
+
if (!signature) {
|
|
326
|
+
throw new bolt.ReceiverAuthenticityError(
|
|
327
|
+
ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_SIGNATURE_HEADER)
|
|
328
|
+
);
|
|
329
|
+
}
|
|
330
|
+
if (!timestamp) {
|
|
331
|
+
throw new bolt.ReceiverAuthenticityError(
|
|
332
|
+
ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_TIMESTAMP_HEADER)
|
|
333
|
+
);
|
|
334
|
+
}
|
|
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
|
+
}
|
|
287
350
|
}
|
|
288
351
|
createSlackReceiverEvent({
|
|
289
352
|
body,
|
|
@@ -303,47 +366,39 @@ var VercelReceiver = class {
|
|
|
303
366
|
};
|
|
304
367
|
}
|
|
305
368
|
handleError(error) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
});
|
|
311
|
-
return new Response(
|
|
312
|
-
JSON.stringify({
|
|
313
|
-
error: error.message,
|
|
314
|
-
type: error.name
|
|
315
|
-
}),
|
|
316
|
-
{ status: error.statusCode }
|
|
317
|
-
);
|
|
318
|
-
}
|
|
319
|
-
this.logger.error("Unexpected error in VercelReceiver", error);
|
|
369
|
+
const errorMessage = getErrorMessage(error);
|
|
370
|
+
const errorType = getErrorType(error);
|
|
371
|
+
const errorStatusCode = getStatusCode(error);
|
|
372
|
+
this.logger.error(error);
|
|
320
373
|
return new Response(
|
|
321
374
|
JSON.stringify({
|
|
322
|
-
error:
|
|
323
|
-
type:
|
|
375
|
+
error: errorMessage,
|
|
376
|
+
type: errorType
|
|
324
377
|
}),
|
|
325
|
-
{
|
|
378
|
+
{
|
|
379
|
+
status: errorStatusCode,
|
|
380
|
+
headers: { "content-type": "application/json" }
|
|
381
|
+
}
|
|
326
382
|
);
|
|
327
383
|
}
|
|
328
384
|
createScopedLogger(logger, logLevel) {
|
|
329
|
-
const prefix = SCOPE.map((s) => `[${s}]`).join(" ");
|
|
330
385
|
logger.setLevel(logLevel);
|
|
331
386
|
return __spreadProps(__spreadValues({}, logger), {
|
|
332
387
|
error: (...args) => {
|
|
333
388
|
var _a;
|
|
334
|
-
return (_a = logger.error) == null ? void 0 : _a.call(logger,
|
|
389
|
+
return (_a = logger.error) == null ? void 0 : _a.call(logger, LOG_PREFIX, ...args);
|
|
335
390
|
},
|
|
336
391
|
warn: (...args) => {
|
|
337
392
|
var _a;
|
|
338
|
-
return (_a = logger.warn) == null ? void 0 : _a.call(logger,
|
|
393
|
+
return (_a = logger.warn) == null ? void 0 : _a.call(logger, LOG_PREFIX, ...args);
|
|
339
394
|
},
|
|
340
395
|
info: (...args) => {
|
|
341
396
|
var _a;
|
|
342
|
-
return (_a = logger.info) == null ? void 0 : _a.call(logger,
|
|
397
|
+
return (_a = logger.info) == null ? void 0 : _a.call(logger, LOG_PREFIX, ...args);
|
|
343
398
|
},
|
|
344
399
|
debug: (...args) => {
|
|
345
400
|
var _a;
|
|
346
|
-
return (_a = logger.debug) == null ? void 0 : _a.call(logger,
|
|
401
|
+
return (_a = logger.debug) == null ? void 0 : _a.call(logger, LOG_PREFIX, ...args);
|
|
347
402
|
},
|
|
348
403
|
setLevel: logger.setLevel,
|
|
349
404
|
getLevel: logger.getLevel
|
|
@@ -363,13 +418,13 @@ function createHandler(app, receiver) {
|
|
|
363
418
|
return handler(req);
|
|
364
419
|
} catch (error) {
|
|
365
420
|
const logger = receiver.getLogger();
|
|
366
|
-
logger.error(
|
|
421
|
+
logger.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);
|
|
367
422
|
return new Response(
|
|
368
423
|
JSON.stringify({
|
|
369
|
-
error:
|
|
370
|
-
type:
|
|
424
|
+
error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,
|
|
425
|
+
type: ERROR_MESSAGES.TYPES.HANDLER_ERROR
|
|
371
426
|
}),
|
|
372
|
-
{ status: 500 }
|
|
427
|
+
{ status: 500, headers: { "content-type": "application/json" } }
|
|
373
428
|
);
|
|
374
429
|
}
|
|
375
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","verifySlackRequest"],"mappings":"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","file":"index.js","sourcesContent":["export class VercelReceiverError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number = 500,\n ) {\n super(message);\n this.name = \"VercelReceiverError\";\n }\n}\n\nexport class SignatureVerificationError extends VercelReceiverError {\n constructor(message: string = \"Invalid request signature\") {\n super(message, 401);\n this.name = \"SignatureVerificationError\";\n }\n}\n\nexport class RequestParsingError extends VercelReceiverError {\n constructor(message: string = \"Failed to parse request\") {\n super(message, 400);\n this.name = \"RequestParsingError\";\n }\n}\n","import {\n VercelReceiverError,\n RequestParsingError,\n SignatureVerificationError,\n} from \"./errors\";\nimport { waitUntil } from \"@vercel/functions\";\n\nimport {\n ReceiverMultipleAckError,\n verifySlackRequest,\n type AckFn,\n type App,\n type Receiver,\n type ReceiverEvent,\n type StringIndexed,\n} from \"@slack/bolt\";\nimport { ConsoleLogger, type Logger, LogLevel } from \"@slack/logger\";\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\nconst SCOPE = [\"@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 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 }: VercelReceiverOptions = {}) {\n if (!signingSecret) {\n throw new VercelReceiverError(\n \"SLACK_SIGNING_SECRET is required for VercelReceiver\",\n );\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\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 await this.verifySlackRequest(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(\"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(\"Event not acknowledged within timeout period\");\n const error = new VercelReceiverError(\"Request timeout\", 408);\n responseRejecter(error);\n }\n }, ACK_TIMEOUT_MS);\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 in acknowledgment handler\", 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 async verifySlackRequest(\n req: Request,\n rawBody: string,\n ): Promise<void> {\n const timestamp = req.headers.get(SLACK_TIMESTAMP_HEADER);\n const signature = req.headers.get(SLACK_SIGNATURE_HEADER);\n\n if (!timestamp) {\n throw new SignatureVerificationError(\"Missing required timestamp header\");\n }\n\n if (!signature) {\n throw new SignatureVerificationError(\n \"Missing required signature headers\",\n );\n }\n\n try {\n verifySlackRequest({\n signingSecret: this.signingSecret,\n body: rawBody,\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 this.logger.error(\"Slack request verification failed\", error);\n throw new SignatureVerificationError(\n error instanceof Error\n ? error.message\n : \"Signature verification failed\",\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 private handleError(error: unknown): Response {\n if (error instanceof VercelReceiverError) {\n this.logger.error(`VercelReceiverError: ${error.message}`, {\n statusCode: error.statusCode,\n name: error.name,\n });\n return new Response(\n JSON.stringify({\n error: error.message,\n type: error.name,\n }),\n { status: error.statusCode },\n );\n }\n\n this.logger.error(\"Unexpected error in VercelReceiver\", error);\n return new Response(\n JSON.stringify({\n error: \"Internal server error\",\n type: \"UnexpectedError\",\n }),\n { status: 500 },\n );\n }\n\n private createScopedLogger(logger: Logger, logLevel: LogLevel): Logger {\n const prefix = SCOPE.map((s) => `[${s}]`).join(\" \");\n logger.setLevel(logLevel);\n\n return {\n ...logger,\n error: (...args) => logger.error?.(prefix, ...args),\n warn: (...args) => logger.warn?.(prefix, ...args),\n info: (...args) => logger.info?.(prefix, ...args),\n debug: (...args) => logger.debug?.(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 in createHandler:\", error);\n return new Response(\n JSON.stringify({\n error: \"Internal Server Error\",\n type: \"HandlerError\",\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
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { verifySlackRequest, ReceiverMultipleAckError } from '@slack/bolt';
|
|
1
|
+
import { ReceiverAuthenticityError, verifySlackRequest, ReceiverMultipleAckError } from '@slack/bolt';
|
|
3
2
|
import { ConsoleLogger, LogLevel } from '@slack/logger';
|
|
3
|
+
import { waitUntil } from '@vercel/functions';
|
|
4
4
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
6
6
|
var __defProps = Object.defineProperties;
|
|
@@ -43,26 +43,83 @@ var __async = (__this, __arguments, generator) => {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
// src/errors.ts
|
|
46
|
+
var ERROR_MESSAGES = {
|
|
47
|
+
// VercelReceiver errors
|
|
48
|
+
SIGNING_SECRET_REQUIRED: "SLACK_SIGNING_SECRET is required for VercelReceiver",
|
|
49
|
+
APP_NOT_INITIALIZED: "App not initialized",
|
|
50
|
+
REQUEST_TIMEOUT: "Request timeout",
|
|
51
|
+
EVENT_NOT_ACKNOWLEDGED: "Event not acknowledged within timeout period",
|
|
52
|
+
// Header validation errors
|
|
53
|
+
MISSING_REQUIRED_HEADER: (header) => `Missing required header: ${header}`,
|
|
54
|
+
// Generic fallback errors
|
|
55
|
+
REQUEST_VERIFICATION_FAILED: "Request verification failed",
|
|
56
|
+
INTERNAL_SERVER_ERROR: "Internal server error",
|
|
57
|
+
INTERNAL_SERVER_ERROR_HANDLER: "Internal Server Error",
|
|
58
|
+
ACKNOWLEDGMENT_ERROR: "Error in acknowledgment handler",
|
|
59
|
+
CREATE_HANDLER_ERROR: "Error in createHandler:",
|
|
60
|
+
// Error type names
|
|
61
|
+
TYPES: {
|
|
62
|
+
VERCEL_RECEIVER_ERROR: "VercelReceiverError",
|
|
63
|
+
SIGNATURE_VERIFICATION_ERROR: "SignatureVerificationError",
|
|
64
|
+
REQUEST_PARSING_ERROR: "RequestParsingError",
|
|
65
|
+
UNEXPECTED_ERROR: "UnexpectedError",
|
|
66
|
+
HANDLER_ERROR: "HandlerError"
|
|
67
|
+
}
|
|
68
|
+
};
|
|
46
69
|
var VercelReceiverError = class extends Error {
|
|
47
70
|
constructor(message, statusCode = 500) {
|
|
48
71
|
super(message);
|
|
49
72
|
this.statusCode = statusCode;
|
|
50
|
-
this.name =
|
|
51
|
-
}
|
|
52
|
-
};
|
|
53
|
-
var SignatureVerificationError = class extends VercelReceiverError {
|
|
54
|
-
constructor(message = "Invalid request signature") {
|
|
55
|
-
super(message, 401);
|
|
56
|
-
this.name = "SignatureVerificationError";
|
|
73
|
+
this.name = ERROR_MESSAGES.TYPES.VERCEL_RECEIVER_ERROR;
|
|
57
74
|
}
|
|
58
75
|
};
|
|
59
76
|
var RequestParsingError = class extends VercelReceiverError {
|
|
60
77
|
constructor(message = "Failed to parse request") {
|
|
61
78
|
super(message, 400);
|
|
62
|
-
this.name =
|
|
79
|
+
this.name = ERROR_MESSAGES.TYPES.REQUEST_PARSING_ERROR;
|
|
63
80
|
}
|
|
64
81
|
};
|
|
65
|
-
|
|
82
|
+
function getStatusCode(error) {
|
|
83
|
+
var _a;
|
|
84
|
+
if (error instanceof VercelReceiverError) {
|
|
85
|
+
return error.statusCode;
|
|
86
|
+
}
|
|
87
|
+
if (error && typeof error === "object") {
|
|
88
|
+
const errorName = ((_a = error.constructor) == null ? void 0 : _a.name) || error.name;
|
|
89
|
+
switch (errorName) {
|
|
90
|
+
case "ReceiverAuthenticityError":
|
|
91
|
+
return 401;
|
|
92
|
+
case "ReceiverMultipleAckError":
|
|
93
|
+
return 500;
|
|
94
|
+
case "RequestParsingError":
|
|
95
|
+
return 400;
|
|
96
|
+
case "SignatureVerificationError":
|
|
97
|
+
return 400;
|
|
98
|
+
default:
|
|
99
|
+
return 500;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return 500;
|
|
103
|
+
}
|
|
104
|
+
function getErrorMessage(error) {
|
|
105
|
+
if (error && typeof error === "object" && "message" in error) {
|
|
106
|
+
return String(error.message);
|
|
107
|
+
}
|
|
108
|
+
return ERROR_MESSAGES.INTERNAL_SERVER_ERROR;
|
|
109
|
+
}
|
|
110
|
+
function getErrorType(error) {
|
|
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;
|
|
116
|
+
return errorName === "Error" ? ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR : errorName;
|
|
117
|
+
}
|
|
118
|
+
return ERROR_MESSAGES.TYPES.UNEXPECTED_ERROR;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/index.ts
|
|
122
|
+
var LOG_PREFIX = "[@vercel/slack-bolt]";
|
|
66
123
|
var ACK_TIMEOUT_MS = 3001;
|
|
67
124
|
var SLACK_RETRY_NUM_HEADER = "x-slack-retry-num";
|
|
68
125
|
var SLACK_RETRY_REASON_HEADER = "x-slack-retry-reason";
|
|
@@ -92,12 +149,11 @@ var VercelReceiver = class {
|
|
|
92
149
|
signatureVerification = true,
|
|
93
150
|
logger,
|
|
94
151
|
logLevel = LogLevel.INFO,
|
|
95
|
-
customPropertiesExtractor
|
|
152
|
+
customPropertiesExtractor,
|
|
153
|
+
ackTimeoutMs = ACK_TIMEOUT_MS
|
|
96
154
|
} = {}) {
|
|
97
155
|
if (!signingSecret) {
|
|
98
|
-
throw new VercelReceiverError(
|
|
99
|
-
"SLACK_SIGNING_SECRET is required for VercelReceiver"
|
|
100
|
-
);
|
|
156
|
+
throw new VercelReceiverError(ERROR_MESSAGES.SIGNING_SECRET_REQUIRED);
|
|
101
157
|
}
|
|
102
158
|
this.signingSecret = signingSecret;
|
|
103
159
|
this.signatureVerification = signatureVerification;
|
|
@@ -106,6 +162,7 @@ var VercelReceiver = class {
|
|
|
106
162
|
logLevel
|
|
107
163
|
);
|
|
108
164
|
this.customPropertiesExtractor = customPropertiesExtractor;
|
|
165
|
+
this.ackTimeoutMs = ackTimeoutMs;
|
|
109
166
|
this.logger.debug("VercelReceiver initialized");
|
|
110
167
|
}
|
|
111
168
|
/**
|
|
@@ -150,7 +207,7 @@ var VercelReceiver = class {
|
|
|
150
207
|
try {
|
|
151
208
|
const rawBody = yield req.text();
|
|
152
209
|
if (this.signatureVerification) {
|
|
153
|
-
|
|
210
|
+
this.verifyRequest(req, rawBody);
|
|
154
211
|
}
|
|
155
212
|
const body = yield this.parseRequestBody(req, rawBody);
|
|
156
213
|
if (body.type === "url_verification") {
|
|
@@ -193,7 +250,7 @@ var VercelReceiver = class {
|
|
|
193
250
|
handleSlackEvent(req, body) {
|
|
194
251
|
return __async(this, null, function* () {
|
|
195
252
|
if (!this.app) {
|
|
196
|
-
throw new VercelReceiverError(
|
|
253
|
+
throw new VercelReceiverError(ERROR_MESSAGES.APP_NOT_INITIALIZED, 500);
|
|
197
254
|
}
|
|
198
255
|
let isAcknowledged = false;
|
|
199
256
|
let responseResolver;
|
|
@@ -204,11 +261,14 @@ var VercelReceiver = class {
|
|
|
204
261
|
});
|
|
205
262
|
const timeoutId = setTimeout(() => {
|
|
206
263
|
if (!isAcknowledged) {
|
|
207
|
-
this.logger.error(
|
|
208
|
-
const error = new VercelReceiverError(
|
|
264
|
+
this.logger.error(ERROR_MESSAGES.EVENT_NOT_ACKNOWLEDGED);
|
|
265
|
+
const error = new VercelReceiverError(
|
|
266
|
+
ERROR_MESSAGES.REQUEST_TIMEOUT,
|
|
267
|
+
408
|
|
268
|
+
);
|
|
209
269
|
responseRejecter(error);
|
|
210
270
|
}
|
|
211
|
-
},
|
|
271
|
+
}, this.ackTimeoutMs);
|
|
212
272
|
const ackFn = (responseBody) => __async(this, null, function* () {
|
|
213
273
|
this.logger.debug(`ack() call begins (body: ${responseBody})`);
|
|
214
274
|
if (isAcknowledged) {
|
|
@@ -233,7 +293,7 @@ var VercelReceiver = class {
|
|
|
233
293
|
});
|
|
234
294
|
responseResolver(response);
|
|
235
295
|
} catch (error) {
|
|
236
|
-
this.logger.error(
|
|
296
|
+
this.logger.error(ERROR_MESSAGES.ACKNOWLEDGMENT_ERROR, error);
|
|
237
297
|
responseRejecter(
|
|
238
298
|
error instanceof Error ? error : new Error(String(error))
|
|
239
299
|
);
|
|
@@ -245,7 +305,11 @@ var VercelReceiver = class {
|
|
|
245
305
|
ack: ackFn,
|
|
246
306
|
request: req
|
|
247
307
|
});
|
|
248
|
-
waitUntil(
|
|
308
|
+
waitUntil(
|
|
309
|
+
this.app.processEvent(event).catch((error) => {
|
|
310
|
+
return this.handleError(error);
|
|
311
|
+
})
|
|
312
|
+
);
|
|
249
313
|
try {
|
|
250
314
|
return yield responsePromise;
|
|
251
315
|
} catch (error) {
|
|
@@ -253,35 +317,34 @@ var VercelReceiver = class {
|
|
|
253
317
|
}
|
|
254
318
|
});
|
|
255
319
|
}
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
)
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
});
|
|
320
|
+
verifyRequest(req, body) {
|
|
321
|
+
const timestamp = req.headers.get(SLACK_TIMESTAMP_HEADER);
|
|
322
|
+
const signature = req.headers.get(SLACK_SIGNATURE_HEADER);
|
|
323
|
+
if (!signature) {
|
|
324
|
+
throw new ReceiverAuthenticityError(
|
|
325
|
+
ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_SIGNATURE_HEADER)
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
if (!timestamp) {
|
|
329
|
+
throw new ReceiverAuthenticityError(
|
|
330
|
+
ERROR_MESSAGES.MISSING_REQUIRED_HEADER(SLACK_TIMESTAMP_HEADER)
|
|
331
|
+
);
|
|
332
|
+
}
|
|
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
|
+
}
|
|
285
348
|
}
|
|
286
349
|
createSlackReceiverEvent({
|
|
287
350
|
body,
|
|
@@ -301,47 +364,39 @@ var VercelReceiver = class {
|
|
|
301
364
|
};
|
|
302
365
|
}
|
|
303
366
|
handleError(error) {
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
});
|
|
309
|
-
return new Response(
|
|
310
|
-
JSON.stringify({
|
|
311
|
-
error: error.message,
|
|
312
|
-
type: error.name
|
|
313
|
-
}),
|
|
314
|
-
{ status: error.statusCode }
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
this.logger.error("Unexpected error in VercelReceiver", error);
|
|
367
|
+
const errorMessage = getErrorMessage(error);
|
|
368
|
+
const errorType = getErrorType(error);
|
|
369
|
+
const errorStatusCode = getStatusCode(error);
|
|
370
|
+
this.logger.error(error);
|
|
318
371
|
return new Response(
|
|
319
372
|
JSON.stringify({
|
|
320
|
-
error:
|
|
321
|
-
type:
|
|
373
|
+
error: errorMessage,
|
|
374
|
+
type: errorType
|
|
322
375
|
}),
|
|
323
|
-
{
|
|
376
|
+
{
|
|
377
|
+
status: errorStatusCode,
|
|
378
|
+
headers: { "content-type": "application/json" }
|
|
379
|
+
}
|
|
324
380
|
);
|
|
325
381
|
}
|
|
326
382
|
createScopedLogger(logger, logLevel) {
|
|
327
|
-
const prefix = SCOPE.map((s) => `[${s}]`).join(" ");
|
|
328
383
|
logger.setLevel(logLevel);
|
|
329
384
|
return __spreadProps(__spreadValues({}, logger), {
|
|
330
385
|
error: (...args) => {
|
|
331
386
|
var _a;
|
|
332
|
-
return (_a = logger.error) == null ? void 0 : _a.call(logger,
|
|
387
|
+
return (_a = logger.error) == null ? void 0 : _a.call(logger, LOG_PREFIX, ...args);
|
|
333
388
|
},
|
|
334
389
|
warn: (...args) => {
|
|
335
390
|
var _a;
|
|
336
|
-
return (_a = logger.warn) == null ? void 0 : _a.call(logger,
|
|
391
|
+
return (_a = logger.warn) == null ? void 0 : _a.call(logger, LOG_PREFIX, ...args);
|
|
337
392
|
},
|
|
338
393
|
info: (...args) => {
|
|
339
394
|
var _a;
|
|
340
|
-
return (_a = logger.info) == null ? void 0 : _a.call(logger,
|
|
395
|
+
return (_a = logger.info) == null ? void 0 : _a.call(logger, LOG_PREFIX, ...args);
|
|
341
396
|
},
|
|
342
397
|
debug: (...args) => {
|
|
343
398
|
var _a;
|
|
344
|
-
return (_a = logger.debug) == null ? void 0 : _a.call(logger,
|
|
399
|
+
return (_a = logger.debug) == null ? void 0 : _a.call(logger, LOG_PREFIX, ...args);
|
|
345
400
|
},
|
|
346
401
|
setLevel: logger.setLevel,
|
|
347
402
|
getLevel: logger.getLevel
|
|
@@ -361,13 +416,13 @@ function createHandler(app, receiver) {
|
|
|
361
416
|
return handler(req);
|
|
362
417
|
} catch (error) {
|
|
363
418
|
const logger = receiver.getLogger();
|
|
364
|
-
logger.error(
|
|
419
|
+
logger.error(ERROR_MESSAGES.CREATE_HANDLER_ERROR, error);
|
|
365
420
|
return new Response(
|
|
366
421
|
JSON.stringify({
|
|
367
|
-
error:
|
|
368
|
-
type:
|
|
422
|
+
error: ERROR_MESSAGES.INTERNAL_SERVER_ERROR_HANDLER,
|
|
423
|
+
type: ERROR_MESSAGES.TYPES.HANDLER_ERROR
|
|
369
424
|
}),
|
|
370
|
-
{ status: 500 }
|
|
425
|
+
{ status: 500, headers: { "content-type": "application/json" } }
|
|
371
426
|
);
|
|
372
427
|
}
|
|
373
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":["export class VercelReceiverError extends Error {\n constructor(\n message: string,\n public readonly statusCode: number = 500,\n ) {\n super(message);\n this.name = \"VercelReceiverError\";\n }\n}\n\nexport class SignatureVerificationError extends VercelReceiverError {\n constructor(message: string = \"Invalid request signature\") {\n super(message, 401);\n this.name = \"SignatureVerificationError\";\n }\n}\n\nexport class RequestParsingError extends VercelReceiverError {\n constructor(message: string = \"Failed to parse request\") {\n super(message, 400);\n this.name = \"RequestParsingError\";\n }\n}\n","import {\n VercelReceiverError,\n RequestParsingError,\n SignatureVerificationError,\n} from \"./errors\";\nimport { waitUntil } from \"@vercel/functions\";\n\nimport {\n ReceiverMultipleAckError,\n verifySlackRequest,\n type AckFn,\n type App,\n type Receiver,\n type ReceiverEvent,\n type StringIndexed,\n} from \"@slack/bolt\";\nimport { ConsoleLogger, type Logger, LogLevel } from \"@slack/logger\";\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\nconst SCOPE = [\"@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 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 }: VercelReceiverOptions = {}) {\n if (!signingSecret) {\n throw new VercelReceiverError(\n \"SLACK_SIGNING_SECRET is required for VercelReceiver\",\n );\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\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 await this.verifySlackRequest(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(\"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(\"Event not acknowledged within timeout period\");\n const error = new VercelReceiverError(\"Request timeout\", 408);\n responseRejecter(error);\n }\n }, ACK_TIMEOUT_MS);\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 in acknowledgment handler\", 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 async verifySlackRequest(\n req: Request,\n rawBody: string,\n ): Promise<void> {\n const timestamp = req.headers.get(SLACK_TIMESTAMP_HEADER);\n const signature = req.headers.get(SLACK_SIGNATURE_HEADER);\n\n if (!timestamp) {\n throw new SignatureVerificationError(\"Missing required timestamp header\");\n }\n\n if (!signature) {\n throw new SignatureVerificationError(\n \"Missing required signature headers\",\n );\n }\n\n try {\n verifySlackRequest({\n signingSecret: this.signingSecret,\n body: rawBody,\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 this.logger.error(\"Slack request verification failed\", error);\n throw new SignatureVerificationError(\n error instanceof Error\n ? error.message\n : \"Signature verification failed\",\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 private handleError(error: unknown): Response {\n if (error instanceof VercelReceiverError) {\n this.logger.error(`VercelReceiverError: ${error.message}`, {\n statusCode: error.statusCode,\n name: error.name,\n });\n return new Response(\n JSON.stringify({\n error: error.message,\n type: error.name,\n }),\n { status: error.statusCode },\n );\n }\n\n this.logger.error(\"Unexpected error in VercelReceiver\", error);\n return new Response(\n JSON.stringify({\n error: \"Internal server error\",\n type: \"UnexpectedError\",\n }),\n { status: 500 },\n );\n }\n\n private createScopedLogger(logger: Logger, logLevel: LogLevel): Logger {\n const prefix = SCOPE.map((s) => `[${s}]`).join(\" \");\n logger.setLevel(logLevel);\n\n return {\n ...logger,\n error: (...args) => logger.error?.(prefix, ...args),\n warn: (...args) => logger.warn?.(prefix, ...args),\n info: (...args) => logger.info?.(prefix, ...args),\n debug: (...args) => logger.debug?.(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 in createHandler:\", error);\n return new Response(\n JSON.stringify({\n error: \"Internal Server Error\",\n type: \"HandlerError\",\n }),\n { status: 500 },\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 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
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vercel/slack-bolt",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
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,14 +34,13 @@
|
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@slack/logger": "^4.0.0",
|
|
37
|
-
"@vercel/functions": "^2.2.
|
|
38
|
-
"tsscmp": "^1.0.6"
|
|
37
|
+
"@vercel/functions": "^2.2.12"
|
|
39
38
|
},
|
|
40
39
|
"devDependencies": {
|
|
41
|
-
"@biomejs/biome": "2.
|
|
42
|
-
"@changesets/cli": "^2.29.
|
|
43
|
-
"@types/node": "^
|
|
44
|
-
"
|
|
40
|
+
"@biomejs/biome": "2.2.0",
|
|
41
|
+
"@changesets/cli": "^2.29.6",
|
|
42
|
+
"@types/node": "^24.3.0",
|
|
43
|
+
"husky": "^9.1.7",
|
|
45
44
|
"tsup": "^8.5.0",
|
|
46
45
|
"typescript": "^5.9.2",
|
|
47
46
|
"vitest": "^3.2.4"
|