@slack/bolt 4.0.0-rc.1 → 4.0.0-rc.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 +22 -16
- package/dist/App.d.ts +32 -48
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +174 -86
- package/dist/App.js.map +1 -1
- package/dist/CustomFunction.d.ts +58 -0
- package/dist/CustomFunction.d.ts.map +1 -0
- package/dist/CustomFunction.js +144 -0
- package/dist/CustomFunction.js.map +1 -0
- package/dist/WorkflowStep.d.ts +89 -36
- package/dist/WorkflowStep.d.ts.map +1 -1
- package/dist/WorkflowStep.js +29 -8
- package/dist/WorkflowStep.js.map +1 -1
- package/dist/conversation-store.d.ts +1 -1
- package/dist/conversation-store.d.ts.map +1 -1
- package/dist/conversation-store.js +3 -3
- package/dist/conversation-store.js.map +1 -1
- package/dist/errors.d.ts +19 -2
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +45 -32
- package/dist/errors.js.map +1 -1
- package/dist/helpers.d.ts +2 -2
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +5 -4
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -9
- package/dist/index.js.map +1 -1
- package/dist/middleware/builtin.d.ts +19 -22
- package/dist/middleware/builtin.d.ts.map +1 -1
- package/dist/middleware/builtin.js +93 -111
- package/dist/middleware/builtin.js.map +1 -1
- package/dist/middleware/process.d.ts +3 -3
- package/dist/middleware/process.d.ts.map +1 -1
- package/dist/middleware/process.js +1 -1
- package/dist/middleware/process.js.map +1 -1
- package/dist/receivers/AwsLambdaReceiver.d.ts +77 -16
- package/dist/receivers/AwsLambdaReceiver.d.ts.map +1 -1
- package/dist/receivers/AwsLambdaReceiver.js +53 -25
- package/dist/receivers/AwsLambdaReceiver.js.map +1 -1
- package/dist/receivers/BufferedIncomingMessage.d.ts +2 -1
- package/dist/receivers/BufferedIncomingMessage.d.ts.map +1 -1
- package/dist/receivers/ExpressReceiver.d.ts +13 -13
- package/dist/receivers/ExpressReceiver.d.ts.map +1 -1
- package/dist/receivers/ExpressReceiver.js +70 -70
- package/dist/receivers/ExpressReceiver.js.map +1 -1
- package/dist/receivers/HTTPModuleFunctions.d.ts +18 -20
- package/dist/receivers/HTTPModuleFunctions.d.ts.map +1 -1
- package/dist/receivers/HTTPModuleFunctions.js +187 -181
- package/dist/receivers/HTTPModuleFunctions.js.map +1 -1
- package/dist/receivers/HTTPReceiver.d.ts +14 -14
- package/dist/receivers/HTTPReceiver.d.ts.map +1 -1
- package/dist/receivers/HTTPReceiver.js +92 -44
- package/dist/receivers/HTTPReceiver.js.map +1 -1
- package/dist/receivers/HTTPResponseAck.d.ts +7 -7
- package/dist/receivers/HTTPResponseAck.d.ts.map +1 -1
- package/dist/receivers/HTTPResponseAck.js +37 -5
- package/dist/receivers/HTTPResponseAck.js.map +1 -1
- package/dist/receivers/ParamsIncomingMessage.d.ts +2 -2
- package/dist/receivers/ParamsIncomingMessage.d.ts.map +1 -1
- package/dist/receivers/SocketModeFunctions.d.ts +3 -5
- package/dist/receivers/SocketModeFunctions.d.ts.map +1 -1
- package/dist/receivers/SocketModeFunctions.js +14 -23
- package/dist/receivers/SocketModeFunctions.js.map +1 -1
- package/dist/receivers/SocketModeReceiver.d.ts +9 -9
- package/dist/receivers/SocketModeReceiver.d.ts.map +1 -1
- package/dist/receivers/SocketModeReceiver.js +29 -21
- package/dist/receivers/SocketModeReceiver.js.map +1 -1
- package/dist/receivers/custom-routes.d.ts +2 -2
- package/dist/receivers/custom-routes.d.ts.map +1 -1
- package/dist/receivers/custom-routes.js +10 -9
- package/dist/receivers/custom-routes.js.map +1 -1
- package/dist/receivers/verify-redirect-opts.d.ts +1 -1
- package/dist/receivers/verify-redirect-opts.d.ts.map +1 -1
- package/dist/receivers/verify-redirect-opts.js +3 -3
- package/dist/receivers/verify-redirect-opts.js.map +1 -1
- package/dist/receivers/verify-request.d.ts +1 -12
- package/dist/receivers/verify-request.d.ts.map +1 -1
- package/dist/receivers/verify-request.js +4 -18
- package/dist/receivers/verify-request.js.map +1 -1
- package/dist/types/actions/block-action.d.ts +17 -17
- package/dist/types/actions/block-action.d.ts.map +1 -1
- package/dist/types/actions/index.d.ts +25 -11
- package/dist/types/actions/index.d.ts.map +1 -1
- package/dist/types/actions/index.js +1 -0
- package/dist/types/actions/index.js.map +1 -1
- package/dist/types/actions/interactive-message.d.ts +3 -3
- package/dist/types/actions/interactive-message.d.ts.map +1 -1
- package/dist/types/actions/workflow-step-edit.d.ts +7 -7
- package/dist/types/actions/workflow-step-edit.d.ts.map +1 -1
- package/dist/types/command/index.d.ts +1 -2
- package/dist/types/command/index.d.ts.map +1 -1
- package/dist/types/events/index.d.ts +26 -24
- package/dist/types/events/index.d.ts.map +1 -1
- package/dist/types/events/index.js +4 -15
- package/dist/types/events/index.js.map +1 -1
- package/dist/types/middleware.d.ts +26 -14
- package/dist/types/middleware.d.ts.map +1 -1
- package/dist/types/middleware.js +3 -0
- package/dist/types/middleware.js.map +1 -1
- package/dist/types/options/index.d.ts +16 -51
- package/dist/types/options/index.d.ts.map +1 -1
- package/dist/types/receiver.d.ts +3 -3
- package/dist/types/receiver.d.ts.map +1 -1
- package/dist/types/shortcuts/global-shortcut.d.ts.map +1 -1
- package/dist/types/shortcuts/index.d.ts +14 -9
- package/dist/types/shortcuts/index.d.ts.map +1 -1
- package/dist/types/shortcuts/message-shortcut.d.ts.map +1 -1
- package/dist/types/utilities.d.ts +27 -18
- package/dist/types/utilities.d.ts.map +1 -1
- package/dist/types/utilities.js +7 -0
- package/dist/types/utilities.js.map +1 -1
- package/dist/types/view/index.d.ts +15 -7
- package/dist/types/view/index.d.ts.map +1 -1
- package/package.json +27 -41
- package/dist/WorkflowFunction.d.ts +0 -63
- package/dist/WorkflowFunction.d.ts.map +0 -1
- package/dist/WorkflowFunction.js +0 -130
- package/dist/WorkflowFunction.js.map +0 -1
- package/dist/receivers/http-utils.d.ts +0 -5
- package/dist/receivers/http-utils.d.ts.map +0 -1
- package/dist/receivers/http-utils.js +0 -19
- package/dist/receivers/http-utils.js.map +0 -1
- package/dist/receivers/render-html-for-install-path.d.ts +0 -3
- package/dist/receivers/render-html-for-install-path.d.ts.map +0 -1
- package/dist/receivers/render-html-for-install-path.js +0 -32
- package/dist/receivers/render-html-for-install-path.js.map +0 -1
- package/dist/types/events/base-events.d.ts +0 -1187
- package/dist/types/events/base-events.d.ts.map +0 -1
- package/dist/types/events/base-events.js +0 -5
- package/dist/types/events/base-events.js.map +0 -1
- package/dist/types/events/message-events.d.ts +0 -348
- package/dist/types/events/message-events.d.ts.map +0 -1
- package/dist/types/events/message-events.js +0 -3
- package/dist/types/events/message-events.js.map +0 -1
- package/dist/types/helpers.d.ts +0 -17
- package/dist/types/helpers.d.ts.map +0 -1
- package/dist/types/helpers.js +0 -3
- package/dist/types/helpers.js.map +0 -1
package/dist/App.js
CHANGED
|
@@ -4,24 +4,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.LogLevel = void 0;
|
|
7
|
-
const
|
|
8
|
-
const web_api_1 = require("@slack/web-api");
|
|
7
|
+
const node_util_1 = __importDefault(require("node:util"));
|
|
9
8
|
const logger_1 = require("@slack/logger");
|
|
9
|
+
const web_api_1 = require("@slack/web-api");
|
|
10
10
|
const axios_1 = __importDefault(require("axios"));
|
|
11
|
-
const
|
|
12
|
-
const HTTPReceiver_1 = __importDefault(require("./receivers/HTTPReceiver"));
|
|
13
|
-
const builtin_1 = require("./middleware/builtin");
|
|
14
|
-
const process_1 = __importDefault(require("./middleware/process"));
|
|
11
|
+
const CustomFunction_1 = require("./CustomFunction");
|
|
15
12
|
const conversation_store_1 = require("./conversation-store");
|
|
16
|
-
const helpers_1 = require("./helpers");
|
|
17
13
|
const errors_1 = require("./errors");
|
|
14
|
+
const helpers_1 = require("./helpers");
|
|
15
|
+
const builtin_1 = require("./middleware/builtin");
|
|
16
|
+
const process_1 = __importDefault(require("./middleware/process"));
|
|
17
|
+
const HTTPReceiver_1 = __importDefault(require("./receivers/HTTPReceiver"));
|
|
18
|
+
const SocketModeReceiver_1 = __importDefault(require("./receivers/SocketModeReceiver"));
|
|
18
19
|
const middleware_1 = require("./types/middleware");
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-commonjs
|
|
22
|
-
const packageJson = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires
|
|
20
|
+
const utilities_1 = require("./types/utilities");
|
|
21
|
+
const packageJson = require('../package.json');
|
|
23
22
|
// ----------------------------
|
|
24
23
|
// For listener registration methods
|
|
24
|
+
// TODO: we have types for this... consolidate
|
|
25
25
|
const validViewTypes = ['view_closed', 'view_submission'];
|
|
26
26
|
// ----------------------------
|
|
27
27
|
// For the constructor
|
|
@@ -30,9 +30,7 @@ const tokenUsage = 'Apps used in a single workspace can be initialized with a to
|
|
|
30
30
|
var logger_2 = require("@slack/logger");
|
|
31
31
|
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_2.LogLevel; } });
|
|
32
32
|
class WebClientPool {
|
|
33
|
-
|
|
34
|
-
this.pool = {};
|
|
35
|
-
}
|
|
33
|
+
pool = {};
|
|
36
34
|
getOrCreate(token, clientOptions) {
|
|
37
35
|
const cachedClient = this.pool[token];
|
|
38
36
|
if (typeof cachedClient !== 'undefined') {
|
|
@@ -47,22 +45,53 @@ class WebClientPool {
|
|
|
47
45
|
* A Slack App
|
|
48
46
|
*/
|
|
49
47
|
class App {
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
/** Slack Web API client */
|
|
49
|
+
client;
|
|
50
|
+
clientOptions;
|
|
51
|
+
// Some payloads don't have teamId anymore. So we use EnterpriseId in those scenarios
|
|
52
|
+
clients = {};
|
|
53
|
+
/** Receiver - ingests events from the Slack platform */
|
|
54
|
+
receiver;
|
|
55
|
+
/** Logger */
|
|
56
|
+
logger;
|
|
57
|
+
/** Log Level */
|
|
58
|
+
logLevel;
|
|
59
|
+
/** Authorize */
|
|
60
|
+
authorize;
|
|
61
|
+
/** Global middleware chain */
|
|
62
|
+
middleware;
|
|
63
|
+
/** Listener middleware chains */
|
|
64
|
+
listeners;
|
|
65
|
+
errorHandler;
|
|
66
|
+
axios;
|
|
67
|
+
installerOptions;
|
|
68
|
+
socketMode;
|
|
69
|
+
developerMode;
|
|
70
|
+
extendedErrorHandler;
|
|
71
|
+
hasCustomErrorHandler;
|
|
72
|
+
// used when deferInitialization is true
|
|
73
|
+
argToken;
|
|
74
|
+
// used when deferInitialization is true
|
|
75
|
+
argAuthorize;
|
|
76
|
+
// used when deferInitialization is true
|
|
77
|
+
argAuthorization;
|
|
78
|
+
tokenVerificationEnabled;
|
|
79
|
+
initialized;
|
|
80
|
+
attachFunctionToken;
|
|
81
|
+
constructor({ signingSecret = undefined, endpoints = undefined, port = undefined, customRoutes = undefined, agent = undefined, clientTls = undefined, receiver = undefined, convoStore = undefined, token = undefined, appToken = undefined, botId = undefined, botUserId = undefined, authorize = undefined, logger = undefined, logLevel = undefined, ignoreSelf = true, clientOptions = undefined, processBeforeResponse = false, signatureVerification = true, clientId = undefined, clientSecret = undefined, stateSecret = undefined, redirectUri = undefined, installationStore = undefined, scopes = undefined, installerOptions = undefined, socketMode = undefined, developerMode = false, tokenVerificationEnabled = true, extendedErrorHandler = false, deferInitialization = false, attachFunctionToken = true, } = {}) {
|
|
53
82
|
/* ------------------------ Developer mode ----------------------------- */
|
|
54
83
|
this.developerMode = developerMode;
|
|
55
84
|
if (developerMode) {
|
|
56
85
|
// Set logLevel to Debug in Developer Mode if one wasn't passed in
|
|
57
|
-
this.logLevel = logLevel
|
|
86
|
+
this.logLevel = logLevel ?? logger_1.LogLevel.DEBUG;
|
|
58
87
|
// Set SocketMode to true if one wasn't passed in
|
|
59
|
-
this.socketMode = socketMode
|
|
88
|
+
this.socketMode = socketMode ?? true;
|
|
60
89
|
}
|
|
61
90
|
else {
|
|
62
91
|
// If devs aren't using Developer Mode or Socket Mode, set it to false
|
|
63
|
-
this.socketMode = socketMode
|
|
92
|
+
this.socketMode = socketMode ?? false;
|
|
64
93
|
// Set logLevel to Info if one wasn't passed in
|
|
65
|
-
this.logLevel = logLevel
|
|
94
|
+
this.logLevel = logLevel ?? logger_1.LogLevel.INFO;
|
|
66
95
|
}
|
|
67
96
|
/* ------------------------ Set logger ----------------------------- */
|
|
68
97
|
if (typeof logger === 'undefined') {
|
|
@@ -81,6 +110,8 @@ class App {
|
|
|
81
110
|
this.hasCustomErrorHandler = false;
|
|
82
111
|
this.errorHandler = defaultErrorHandler(this.logger);
|
|
83
112
|
this.extendedErrorHandler = extendedErrorHandler;
|
|
113
|
+
// Override token with functionBotAccessToken in function-related handlers
|
|
114
|
+
this.attachFunctionToken = attachFunctionToken;
|
|
84
115
|
/* ------------------------ Set client options ------------------------*/
|
|
85
116
|
this.clientOptions = clientOptions !== undefined ? clientOptions : {};
|
|
86
117
|
if (agent !== undefined && this.clientOptions.agent === undefined) {
|
|
@@ -161,7 +192,7 @@ class App {
|
|
|
161
192
|
}
|
|
162
193
|
// Conditionally use a global middleware that ignores events (including messages) that are sent from this app
|
|
163
194
|
if (ignoreSelf) {
|
|
164
|
-
this.use(
|
|
195
|
+
this.use(builtin_1.ignoreSelf);
|
|
165
196
|
}
|
|
166
197
|
// Use conversation state global middleware
|
|
167
198
|
if (convoStore !== false) {
|
|
@@ -207,6 +238,9 @@ class App {
|
|
|
207
238
|
throw e;
|
|
208
239
|
}
|
|
209
240
|
}
|
|
241
|
+
get webClientOptions() {
|
|
242
|
+
return this.clientOptions;
|
|
243
|
+
}
|
|
210
244
|
/**
|
|
211
245
|
* Register a new middleware, processed in the order registered.
|
|
212
246
|
*
|
|
@@ -220,12 +254,23 @@ class App {
|
|
|
220
254
|
* Register WorkflowStep middleware
|
|
221
255
|
*
|
|
222
256
|
* @param workflowStep global workflow step middleware function
|
|
257
|
+
* @deprecated Steps from Apps are no longer supported and support for them will be removed in the next major bolt-js
|
|
258
|
+
* version.
|
|
223
259
|
*/
|
|
224
260
|
step(workflowStep) {
|
|
225
261
|
const m = workflowStep.getMiddleware();
|
|
226
262
|
this.middleware.push(m);
|
|
227
263
|
return this;
|
|
228
264
|
}
|
|
265
|
+
/**
|
|
266
|
+
* Register CustomFunction middleware
|
|
267
|
+
*/
|
|
268
|
+
function(callbackId, ...listeners) {
|
|
269
|
+
const fn = new CustomFunction_1.CustomFunction(callbackId, listeners, this.webClientOptions);
|
|
270
|
+
const m = fn.getMiddleware();
|
|
271
|
+
this.middleware.push(m);
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
229
274
|
/**
|
|
230
275
|
* Convenience method to call start on the receiver
|
|
231
276
|
*
|
|
@@ -240,7 +285,7 @@ class App {
|
|
|
240
285
|
// TODO: HTTPReceiver['start'] should be the actual receiver's return type
|
|
241
286
|
return this.receiver.start(...args);
|
|
242
287
|
}
|
|
243
|
-
//
|
|
288
|
+
// biome-ignore lint/suspicious/noExplicitAny: receivers could accept anything as arguments for stop
|
|
244
289
|
stop(...args) {
|
|
245
290
|
return this.receiver.stop(...args);
|
|
246
291
|
}
|
|
@@ -255,26 +300,25 @@ class App {
|
|
|
255
300
|
invalidEventName = name.startsWith('message\\.');
|
|
256
301
|
}
|
|
257
302
|
if (invalidEventName) {
|
|
258
|
-
throw new errors_1.AppInitializationError(`Although the document mentions "${eventNameOrPattern}"
|
|
259
|
-
'it is not a valid event type. Use "message" instead. ' +
|
|
260
|
-
'If you want to filter message events, you can use event.channel_type for it.');
|
|
303
|
+
throw new errors_1.AppInitializationError(`Although the document mentions "${eventNameOrPattern}", it is not a valid event type. Use "message" instead. If you want to filter message events, you can use event.channel_type for it.`);
|
|
261
304
|
}
|
|
262
|
-
//
|
|
263
|
-
const _listeners = listeners;
|
|
305
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
306
|
+
const _listeners = listeners;
|
|
264
307
|
this.listeners.push([
|
|
265
308
|
builtin_1.onlyEvents,
|
|
266
309
|
(0, builtin_1.matchEventType)(eventNameOrPattern),
|
|
267
310
|
..._listeners,
|
|
268
311
|
]);
|
|
269
312
|
}
|
|
313
|
+
// TODO: expose a type parameter for overriding the MessageEvent type (just like shortcut() and action() does) https://github.com/slackapi/bolt-js/issues/796
|
|
270
314
|
message(...patternsOrMiddleware) {
|
|
271
315
|
const messageMiddleware = patternsOrMiddleware.map((patternOrMiddleware) => {
|
|
272
|
-
if (typeof patternOrMiddleware === 'string' ||
|
|
316
|
+
if (typeof patternOrMiddleware === 'string' || node_util_1.default.types.isRegExp(patternOrMiddleware)) {
|
|
273
317
|
return (0, builtin_1.matchMessage)(patternOrMiddleware);
|
|
274
318
|
}
|
|
275
319
|
return patternOrMiddleware;
|
|
276
|
-
//
|
|
277
|
-
});
|
|
320
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
321
|
+
});
|
|
278
322
|
this.listeners.push([
|
|
279
323
|
builtin_1.onlyEvents,
|
|
280
324
|
(0, builtin_1.matchEventType)('message'),
|
|
@@ -282,17 +326,18 @@ class App {
|
|
|
282
326
|
]);
|
|
283
327
|
}
|
|
284
328
|
shortcut(callbackIdOrConstraints, ...listeners) {
|
|
285
|
-
const constraints = typeof callbackIdOrConstraints === 'string' ||
|
|
286
|
-
{ callback_id: callbackIdOrConstraints }
|
|
287
|
-
callbackIdOrConstraints;
|
|
329
|
+
const constraints = typeof callbackIdOrConstraints === 'string' || node_util_1.default.types.isRegExp(callbackIdOrConstraints)
|
|
330
|
+
? { callback_id: callbackIdOrConstraints }
|
|
331
|
+
: callbackIdOrConstraints;
|
|
288
332
|
// Fail early if the constraints contain invalid keys
|
|
289
333
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'callback_id' && k !== 'type');
|
|
290
334
|
if (unknownConstraintKeys.length > 0) {
|
|
335
|
+
// TODO:event() will throw an error if you provide an invalid event name; we should align this behaviour.
|
|
291
336
|
this.logger.error(`Slack listener cannot be attached using unknown constraint keys: ${unknownConstraintKeys.join(', ')}`);
|
|
292
337
|
return;
|
|
293
338
|
}
|
|
294
|
-
//
|
|
295
|
-
const _listeners = listeners;
|
|
339
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
340
|
+
const _listeners = listeners;
|
|
296
341
|
this.listeners.push([
|
|
297
342
|
builtin_1.onlyShortcuts,
|
|
298
343
|
(0, builtin_1.matchConstraints)(constraints),
|
|
@@ -301,22 +346,23 @@ class App {
|
|
|
301
346
|
}
|
|
302
347
|
action(actionIdOrConstraints, ...listeners) {
|
|
303
348
|
// Normalize Constraints
|
|
304
|
-
const constraints = typeof actionIdOrConstraints === 'string' ||
|
|
305
|
-
{ action_id: actionIdOrConstraints }
|
|
306
|
-
actionIdOrConstraints;
|
|
349
|
+
const constraints = typeof actionIdOrConstraints === 'string' || node_util_1.default.types.isRegExp(actionIdOrConstraints)
|
|
350
|
+
? { action_id: actionIdOrConstraints }
|
|
351
|
+
: actionIdOrConstraints;
|
|
307
352
|
// Fail early if the constraints contain invalid keys
|
|
308
353
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'action_id' && k !== 'block_id' && k !== 'callback_id' && k !== 'type');
|
|
309
354
|
if (unknownConstraintKeys.length > 0) {
|
|
355
|
+
// TODO:event() will throw an error if you provide an invalid event name; we should align this behaviour.
|
|
310
356
|
this.logger.error(`Action listener cannot be attached using unknown constraint keys: ${unknownConstraintKeys.join(', ')}`);
|
|
311
357
|
return;
|
|
312
358
|
}
|
|
313
|
-
//
|
|
314
|
-
const _listeners = listeners;
|
|
359
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
360
|
+
const _listeners = listeners;
|
|
315
361
|
this.listeners.push([builtin_1.onlyActions, (0, builtin_1.matchConstraints)(constraints), ..._listeners]);
|
|
316
362
|
}
|
|
317
363
|
command(commandName, ...listeners) {
|
|
318
|
-
//
|
|
319
|
-
const _listeners = listeners;
|
|
364
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
365
|
+
const _listeners = listeners;
|
|
320
366
|
this.listeners.push([
|
|
321
367
|
builtin_1.onlyCommands,
|
|
322
368
|
(0, builtin_1.matchCommandName)(commandName),
|
|
@@ -325,18 +371,17 @@ class App {
|
|
|
325
371
|
}
|
|
326
372
|
// TODO: reflect the type in constraints to Source
|
|
327
373
|
options(actionIdOrConstraints, ...listeners) {
|
|
328
|
-
const constraints = typeof actionIdOrConstraints === 'string' ||
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
const _listeners = listeners; // FIXME: workaround for TypeScript 4.7 breaking changes
|
|
374
|
+
const constraints = typeof actionIdOrConstraints === 'string' || node_util_1.default.types.isRegExp(actionIdOrConstraints)
|
|
375
|
+
? { action_id: actionIdOrConstraints }
|
|
376
|
+
: actionIdOrConstraints;
|
|
377
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
378
|
+
const _listeners = listeners;
|
|
334
379
|
this.listeners.push([builtin_1.onlyOptions, (0, builtin_1.matchConstraints)(constraints), ..._listeners]);
|
|
335
380
|
}
|
|
336
381
|
view(callbackIdOrConstraints, ...listeners) {
|
|
337
|
-
const constraints = typeof callbackIdOrConstraints === 'string' ||
|
|
338
|
-
{ callback_id: callbackIdOrConstraints, type: 'view_submission' }
|
|
339
|
-
callbackIdOrConstraints;
|
|
382
|
+
const constraints = typeof callbackIdOrConstraints === 'string' || node_util_1.default.types.isRegExp(callbackIdOrConstraints)
|
|
383
|
+
? { callback_id: callbackIdOrConstraints, type: 'view_submission' }
|
|
384
|
+
: callbackIdOrConstraints;
|
|
340
385
|
// Fail early if the constraints contain invalid keys
|
|
341
386
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'callback_id' && k !== 'type');
|
|
342
387
|
if (unknownConstraintKeys.length > 0) {
|
|
@@ -347,8 +392,8 @@ class App {
|
|
|
347
392
|
this.logger.error(`View listener cannot be attached using unknown view event type: ${constraints.type}`);
|
|
348
393
|
return;
|
|
349
394
|
}
|
|
350
|
-
//
|
|
351
|
-
const _listeners = listeners;
|
|
395
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
396
|
+
const _listeners = listeners;
|
|
352
397
|
this.listeners.push([
|
|
353
398
|
builtin_1.onlyViewActions,
|
|
354
399
|
(0, builtin_1.matchConstraints)(constraints),
|
|
@@ -396,12 +441,10 @@ class App {
|
|
|
396
441
|
authorizeResult = await this.authorize(source, bodyArg);
|
|
397
442
|
}
|
|
398
443
|
catch (error) {
|
|
399
|
-
//
|
|
444
|
+
// biome-ignore lint/suspicious/noExplicitAny: errors can be anything
|
|
400
445
|
const e = error;
|
|
401
446
|
this.logger.warn('Authorization of incoming event did not succeed. No listeners will be called.');
|
|
402
447
|
e.code = errors_1.ErrorCode.AuthorizationError;
|
|
403
|
-
// disabling due to https://github.com/typescript-eslint/typescript-eslint/issues/1277
|
|
404
|
-
// eslint-disable-next-line consistent-return
|
|
405
448
|
return this.handleError({
|
|
406
449
|
error: e,
|
|
407
450
|
logger: this.logger,
|
|
@@ -438,18 +481,38 @@ class App {
|
|
|
438
481
|
retryNum: event.retryNum,
|
|
439
482
|
retryReason: event.retryReason,
|
|
440
483
|
};
|
|
484
|
+
// Extract function-related information and augment context
|
|
485
|
+
const { functionExecutionId, functionBotAccessToken, functionInputs } = extractFunctionContext(body);
|
|
486
|
+
if (functionExecutionId) {
|
|
487
|
+
context.functionExecutionId = functionExecutionId;
|
|
488
|
+
if (functionInputs) {
|
|
489
|
+
context.functionInputs = functionInputs;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Attach and make available the JIT/function-related token on context
|
|
493
|
+
if (this.attachFunctionToken) {
|
|
494
|
+
if (functionBotAccessToken) {
|
|
495
|
+
context.functionBotAccessToken = functionBotAccessToken;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
441
498
|
// Factory for say() utility
|
|
442
499
|
const createSay = (channelId) => {
|
|
443
500
|
const token = selectToken(context);
|
|
444
501
|
return (message) => {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
{
|
|
502
|
+
let postMessageArguments;
|
|
503
|
+
if (typeof message === 'string') {
|
|
504
|
+
postMessageArguments = { token, text: message, channel: channelId };
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
postMessageArguments = { ...message, token, channel: channelId };
|
|
508
|
+
}
|
|
448
509
|
return this.client.chat.postMessage(postMessageArguments);
|
|
449
510
|
};
|
|
450
511
|
};
|
|
451
512
|
// Set body and payload
|
|
452
513
|
// TODO: this value should eventually conform to AnyMiddlewareArgs
|
|
514
|
+
// TODO: remove workflow step stuff in bolt v5
|
|
515
|
+
// TODO: can we instead use type predicates in these switch cases to allow for narrowing of the body simultaneously? we have isEvent, isView, isShortcut, isAction already in types/utilities / helpers
|
|
453
516
|
let payload;
|
|
454
517
|
switch (type) {
|
|
455
518
|
case helpers_1.IncomingEventType.Event:
|
|
@@ -461,8 +524,7 @@ class App {
|
|
|
461
524
|
case helpers_1.IncomingEventType.Shortcut:
|
|
462
525
|
payload = bodyArg;
|
|
463
526
|
break;
|
|
464
|
-
//
|
|
465
|
-
// @ts-ignore: Fallthrough case in switch
|
|
527
|
+
// biome-ignore lint/suspicious/noFallthroughSwitchClause: usually not great, but we do it here
|
|
466
528
|
case helpers_1.IncomingEventType.Action:
|
|
467
529
|
if (isBlockActionOrInteractiveMessageBody(bodyArg)) {
|
|
468
530
|
const { actions } = bodyArg;
|
|
@@ -480,6 +542,7 @@ class App {
|
|
|
480
542
|
body: bodyArg,
|
|
481
543
|
payload,
|
|
482
544
|
};
|
|
545
|
+
// TODO: can we instead use type predicates in these switch cases to allow for narrowing of the body simultaneously? we have isEvent, isView, isShortcut, isAction already in types/utilities / helpers
|
|
483
546
|
// Set aliases
|
|
484
547
|
if (type === helpers_1.IncomingEventType.Event) {
|
|
485
548
|
const eventListenerArgs = listenerArgs;
|
|
@@ -531,14 +594,22 @@ class App {
|
|
|
531
594
|
}
|
|
532
595
|
// Get the client arg
|
|
533
596
|
let { client } = this;
|
|
534
|
-
|
|
597
|
+
// If functionBotAccessToken exists on context, the incoming event is function-related *and* the
|
|
598
|
+
// user has `attachFunctionToken` enabled. In that case, subsequent calls with the client should
|
|
599
|
+
// use the function-related/JIT token in lieu of the botToken or userToken.
|
|
600
|
+
const token = context.functionBotAccessToken ? context.functionBotAccessToken : selectToken(context);
|
|
601
|
+
// Add complete() and fail() utilities for function-related interactivity
|
|
602
|
+
if (type === helpers_1.IncomingEventType.Action && context.functionExecutionId !== undefined) {
|
|
603
|
+
listenerArgs.complete = CustomFunction_1.CustomFunction.createFunctionComplete(context, client);
|
|
604
|
+
listenerArgs.fail = CustomFunction_1.CustomFunction.createFunctionFail(context, client);
|
|
605
|
+
listenerArgs.inputs = context.functionInputs;
|
|
606
|
+
}
|
|
535
607
|
if (token !== undefined) {
|
|
536
|
-
let pool;
|
|
608
|
+
let pool = undefined;
|
|
537
609
|
const clientOptionsCopy = { ...this.clientOptions };
|
|
538
610
|
if (authorizeResult.teamId !== undefined) {
|
|
539
611
|
pool = this.clients[authorizeResult.teamId];
|
|
540
612
|
if (pool === undefined) {
|
|
541
|
-
// eslint-disable-next-line no-multi-assign
|
|
542
613
|
pool = this.clients[authorizeResult.teamId] = new WebClientPool();
|
|
543
614
|
}
|
|
544
615
|
// Add teamId to clientOptions so it can be automatically added to web-api calls
|
|
@@ -547,7 +618,6 @@ class App {
|
|
|
547
618
|
else if (authorizeResult.enterpriseId !== undefined) {
|
|
548
619
|
pool = this.clients[authorizeResult.enterpriseId];
|
|
549
620
|
if (pool === undefined) {
|
|
550
|
-
// eslint-disable-next-line no-multi-assign
|
|
551
621
|
pool = this.clients[authorizeResult.enterpriseId] = new WebClientPool();
|
|
552
622
|
}
|
|
553
623
|
}
|
|
@@ -563,26 +633,27 @@ class App {
|
|
|
563
633
|
const listenerResults = this.listeners.map(async (origListenerMiddleware) => {
|
|
564
634
|
// Copy the array so modifications don't affect the original
|
|
565
635
|
const listenerMiddleware = [...origListenerMiddleware];
|
|
566
|
-
// Don't process the last item in the listenerMiddleware array - it
|
|
636
|
+
// Don't process the last item in the listenerMiddleware array - it will be passed a no-op next fn
|
|
567
637
|
const listener = listenerMiddleware.pop();
|
|
568
638
|
if (listener === undefined) {
|
|
569
639
|
return undefined;
|
|
570
640
|
}
|
|
571
641
|
return (0, process_1.default)(listenerMiddleware, listenerArgs, context, client, this.logger,
|
|
572
642
|
// When all the listener middleware are done processing,
|
|
573
|
-
// `listener` here will be called
|
|
643
|
+
// `listener` here will be called with a noop `next` fn
|
|
574
644
|
async () => listener({
|
|
575
645
|
...listenerArgs,
|
|
576
646
|
context,
|
|
577
647
|
client,
|
|
578
648
|
logger: this.logger,
|
|
579
|
-
|
|
649
|
+
next: () => { },
|
|
580
650
|
}));
|
|
581
651
|
});
|
|
582
|
-
const settledListenerResults = await allSettled(listenerResults);
|
|
583
|
-
const rejectedListenerResults = settledListenerResults.filter(
|
|
652
|
+
const settledListenerResults = await Promise.allSettled(listenerResults);
|
|
653
|
+
const rejectedListenerResults = settledListenerResults.filter(utilities_1.isRejected);
|
|
584
654
|
if (rejectedListenerResults.length === 1) {
|
|
585
655
|
throw rejectedListenerResults[0].reason;
|
|
656
|
+
// biome-ignore lint/style/noUselessElse: I think this is a biome issue actually...
|
|
586
657
|
}
|
|
587
658
|
else if (rejectedListenerResults.length > 1) {
|
|
588
659
|
throw new errors_1.MultipleListenerError(rejectedListenerResults.map((rlr) => rlr.reason));
|
|
@@ -590,10 +661,8 @@ class App {
|
|
|
590
661
|
});
|
|
591
662
|
}
|
|
592
663
|
catch (error) {
|
|
593
|
-
//
|
|
664
|
+
// biome-ignore lint/suspicious/noExplicitAny: errors can be anything
|
|
594
665
|
const e = error;
|
|
595
|
-
// disabling due to https://github.com/typescript-eslint/typescript-eslint/issues/1277
|
|
596
|
-
// eslint-disable-next-line consistent-return
|
|
597
666
|
return this.handleError({
|
|
598
667
|
context,
|
|
599
668
|
error: e,
|
|
@@ -607,9 +676,9 @@ class App {
|
|
|
607
676
|
*/
|
|
608
677
|
handleError(args) {
|
|
609
678
|
const { error, ...rest } = args;
|
|
610
|
-
return this.extendedErrorHandler && this.hasCustomErrorHandler
|
|
611
|
-
this.errorHandler({ error: (0, errors_1.asCodedError)(error), ...rest })
|
|
612
|
-
this.errorHandler((0, errors_1.asCodedError)(error));
|
|
679
|
+
return this.extendedErrorHandler && this.hasCustomErrorHandler
|
|
680
|
+
? this.errorHandler({ error: (0, errors_1.asCodedError)(error), ...rest })
|
|
681
|
+
: this.errorHandler((0, errors_1.asCodedError)(error));
|
|
613
682
|
}
|
|
614
683
|
// ---------------------
|
|
615
684
|
// Private methods for initialization
|
|
@@ -668,8 +737,7 @@ class App {
|
|
|
668
737
|
initAuthorizeIfNoTokenIsGiven(token, authorize) {
|
|
669
738
|
let usingOauth = false;
|
|
670
739
|
const httpReceiver = this.receiver;
|
|
671
|
-
if (httpReceiver.installer !== undefined &&
|
|
672
|
-
httpReceiver.installer.authorize !== undefined) {
|
|
740
|
+
if (httpReceiver.installer !== undefined && httpReceiver.installer.authorize !== undefined) {
|
|
673
741
|
// This supports using the built-in HTTPReceiver, declaring your own HTTPReceiver
|
|
674
742
|
// and theoretically, doing a fully custom (non-Express.js) receiver that implements OAuth
|
|
675
743
|
usingOauth = true;
|
|
@@ -681,14 +749,17 @@ class App {
|
|
|
681
749
|
return undefined;
|
|
682
750
|
}
|
|
683
751
|
if (authorize === undefined && !usingOauth) {
|
|
684
|
-
throw new errors_1.AppInitializationError(`${tokenUsage} \n\nSince you have not provided a token or authorize, you might be missing one or more required oauth installer options. See https://slack.dev/bolt-js/concepts
|
|
752
|
+
throw new errors_1.AppInitializationError(`${tokenUsage} \n\nSince you have not provided a token or authorize, you might be missing one or more required oauth installer options. See https://slack.dev/bolt-js/concepts/authenticating-oauth for these required fields.\n`);
|
|
753
|
+
// biome-ignore lint/style/noUselessElse: I think this is a biome issue actually...
|
|
685
754
|
}
|
|
686
755
|
else if (authorize !== undefined && usingOauth) {
|
|
687
756
|
throw new errors_1.AppInitializationError(`You cannot provide both authorize and oauth installer options. ${tokenUsage}`);
|
|
757
|
+
// biome-ignore lint/style/noUselessElse: I think this is a biome issue actually...
|
|
688
758
|
}
|
|
689
759
|
else if (authorize === undefined && usingOauth) {
|
|
690
|
-
//
|
|
760
|
+
// biome-ignore lint/style/noNonNullAssertion: we know installer is truthy here
|
|
691
761
|
return httpReceiver.installer.authorize;
|
|
762
|
+
// biome-ignore lint/style/noUselessElse: I think this is a biome issue actually...
|
|
692
763
|
}
|
|
693
764
|
else if (authorize !== undefined && !usingOauth) {
|
|
694
765
|
return authorize;
|
|
@@ -720,9 +791,9 @@ function defaultErrorHandler(logger) {
|
|
|
720
791
|
// singleAuthorization
|
|
721
792
|
function runAuthTestForBotToken(client, authorization) {
|
|
722
793
|
// TODO: warn when something needed isn't found
|
|
723
|
-
return authorization.botUserId !== undefined && authorization.botId !== undefined
|
|
724
|
-
Promise.resolve({ botUserId: authorization.botUserId, botId: authorization.botId })
|
|
725
|
-
client.auth.test({ token: authorization.botToken }).then((result) => ({
|
|
794
|
+
return authorization.botUserId !== undefined && authorization.botId !== undefined
|
|
795
|
+
? Promise.resolve({ botUserId: authorization.botUserId, botId: authorization.botId })
|
|
796
|
+
: client.auth.test({ token: authorization.botToken }).then((result) => ({
|
|
726
797
|
botUserId: result.user_id,
|
|
727
798
|
botId: result.bot_id,
|
|
728
799
|
}));
|
|
@@ -873,14 +944,14 @@ function selectToken(context) {
|
|
|
873
944
|
}
|
|
874
945
|
function buildRespondFn(axiosInstance, responseUrl) {
|
|
875
946
|
return async (message) => {
|
|
876
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
877
947
|
const normalizedArgs = typeof message === 'string' ? { text: message } : message;
|
|
878
948
|
return axiosInstance.post(responseUrl, normalizedArgs);
|
|
879
949
|
};
|
|
880
950
|
}
|
|
881
951
|
function escapeHtml(input) {
|
|
882
952
|
if (input) {
|
|
883
|
-
return input
|
|
953
|
+
return input
|
|
954
|
+
.replace(/&/g, '&')
|
|
884
955
|
.replace(/</g, '<')
|
|
885
956
|
.replace(/>/g, '>')
|
|
886
957
|
.replace(/"/g, '"')
|
|
@@ -888,6 +959,23 @@ function escapeHtml(input) {
|
|
|
888
959
|
}
|
|
889
960
|
return '';
|
|
890
961
|
}
|
|
962
|
+
function extractFunctionContext(body) {
|
|
963
|
+
let functionExecutionId = undefined;
|
|
964
|
+
let functionBotAccessToken = undefined;
|
|
965
|
+
let functionInputs = undefined;
|
|
966
|
+
// function_executed event
|
|
967
|
+
if (body.event && body.event.type === 'function_executed' && body.event.function_execution_id) {
|
|
968
|
+
functionExecutionId = body.event.function_execution_id;
|
|
969
|
+
functionBotAccessToken = body.event.bot_access_token;
|
|
970
|
+
}
|
|
971
|
+
// interactivity (block_actions)
|
|
972
|
+
if (body.function_data) {
|
|
973
|
+
functionExecutionId = body.function_data.execution_id;
|
|
974
|
+
functionBotAccessToken = body.bot_access_token;
|
|
975
|
+
functionInputs = body.function_data.inputs;
|
|
976
|
+
}
|
|
977
|
+
return { functionExecutionId, functionBotAccessToken, functionInputs };
|
|
978
|
+
}
|
|
891
979
|
// ----------------------------
|
|
892
980
|
// Instrumentation
|
|
893
981
|
// Don't change the position of the following code
|