@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.
Files changed (140) hide show
  1. package/README.md +22 -16
  2. package/dist/App.d.ts +32 -48
  3. package/dist/App.d.ts.map +1 -1
  4. package/dist/App.js +174 -86
  5. package/dist/App.js.map +1 -1
  6. package/dist/CustomFunction.d.ts +58 -0
  7. package/dist/CustomFunction.d.ts.map +1 -0
  8. package/dist/CustomFunction.js +144 -0
  9. package/dist/CustomFunction.js.map +1 -0
  10. package/dist/WorkflowStep.d.ts +89 -36
  11. package/dist/WorkflowStep.d.ts.map +1 -1
  12. package/dist/WorkflowStep.js +29 -8
  13. package/dist/WorkflowStep.js.map +1 -1
  14. package/dist/conversation-store.d.ts +1 -1
  15. package/dist/conversation-store.d.ts.map +1 -1
  16. package/dist/conversation-store.js +3 -3
  17. package/dist/conversation-store.js.map +1 -1
  18. package/dist/errors.d.ts +19 -2
  19. package/dist/errors.d.ts.map +1 -1
  20. package/dist/errors.js +45 -32
  21. package/dist/errors.js.map +1 -1
  22. package/dist/helpers.d.ts +2 -2
  23. package/dist/helpers.d.ts.map +1 -1
  24. package/dist/helpers.js +5 -4
  25. package/dist/helpers.js.map +1 -1
  26. package/dist/index.d.ts +4 -3
  27. package/dist/index.d.ts.map +1 -1
  28. package/dist/index.js +16 -9
  29. package/dist/index.js.map +1 -1
  30. package/dist/middleware/builtin.d.ts +19 -22
  31. package/dist/middleware/builtin.d.ts.map +1 -1
  32. package/dist/middleware/builtin.js +93 -111
  33. package/dist/middleware/builtin.js.map +1 -1
  34. package/dist/middleware/process.d.ts +3 -3
  35. package/dist/middleware/process.d.ts.map +1 -1
  36. package/dist/middleware/process.js +1 -1
  37. package/dist/middleware/process.js.map +1 -1
  38. package/dist/receivers/AwsLambdaReceiver.d.ts +77 -16
  39. package/dist/receivers/AwsLambdaReceiver.d.ts.map +1 -1
  40. package/dist/receivers/AwsLambdaReceiver.js +53 -25
  41. package/dist/receivers/AwsLambdaReceiver.js.map +1 -1
  42. package/dist/receivers/BufferedIncomingMessage.d.ts +2 -1
  43. package/dist/receivers/BufferedIncomingMessage.d.ts.map +1 -1
  44. package/dist/receivers/ExpressReceiver.d.ts +13 -13
  45. package/dist/receivers/ExpressReceiver.d.ts.map +1 -1
  46. package/dist/receivers/ExpressReceiver.js +70 -70
  47. package/dist/receivers/ExpressReceiver.js.map +1 -1
  48. package/dist/receivers/HTTPModuleFunctions.d.ts +18 -20
  49. package/dist/receivers/HTTPModuleFunctions.d.ts.map +1 -1
  50. package/dist/receivers/HTTPModuleFunctions.js +187 -181
  51. package/dist/receivers/HTTPModuleFunctions.js.map +1 -1
  52. package/dist/receivers/HTTPReceiver.d.ts +14 -14
  53. package/dist/receivers/HTTPReceiver.d.ts.map +1 -1
  54. package/dist/receivers/HTTPReceiver.js +92 -44
  55. package/dist/receivers/HTTPReceiver.js.map +1 -1
  56. package/dist/receivers/HTTPResponseAck.d.ts +7 -7
  57. package/dist/receivers/HTTPResponseAck.d.ts.map +1 -1
  58. package/dist/receivers/HTTPResponseAck.js +37 -5
  59. package/dist/receivers/HTTPResponseAck.js.map +1 -1
  60. package/dist/receivers/ParamsIncomingMessage.d.ts +2 -2
  61. package/dist/receivers/ParamsIncomingMessage.d.ts.map +1 -1
  62. package/dist/receivers/SocketModeFunctions.d.ts +3 -5
  63. package/dist/receivers/SocketModeFunctions.d.ts.map +1 -1
  64. package/dist/receivers/SocketModeFunctions.js +14 -23
  65. package/dist/receivers/SocketModeFunctions.js.map +1 -1
  66. package/dist/receivers/SocketModeReceiver.d.ts +9 -9
  67. package/dist/receivers/SocketModeReceiver.d.ts.map +1 -1
  68. package/dist/receivers/SocketModeReceiver.js +29 -21
  69. package/dist/receivers/SocketModeReceiver.js.map +1 -1
  70. package/dist/receivers/custom-routes.d.ts +2 -2
  71. package/dist/receivers/custom-routes.d.ts.map +1 -1
  72. package/dist/receivers/custom-routes.js +10 -9
  73. package/dist/receivers/custom-routes.js.map +1 -1
  74. package/dist/receivers/verify-redirect-opts.d.ts +1 -1
  75. package/dist/receivers/verify-redirect-opts.d.ts.map +1 -1
  76. package/dist/receivers/verify-redirect-opts.js +3 -3
  77. package/dist/receivers/verify-redirect-opts.js.map +1 -1
  78. package/dist/receivers/verify-request.d.ts +1 -12
  79. package/dist/receivers/verify-request.d.ts.map +1 -1
  80. package/dist/receivers/verify-request.js +4 -18
  81. package/dist/receivers/verify-request.js.map +1 -1
  82. package/dist/types/actions/block-action.d.ts +17 -17
  83. package/dist/types/actions/block-action.d.ts.map +1 -1
  84. package/dist/types/actions/index.d.ts +25 -11
  85. package/dist/types/actions/index.d.ts.map +1 -1
  86. package/dist/types/actions/index.js +1 -0
  87. package/dist/types/actions/index.js.map +1 -1
  88. package/dist/types/actions/interactive-message.d.ts +3 -3
  89. package/dist/types/actions/interactive-message.d.ts.map +1 -1
  90. package/dist/types/actions/workflow-step-edit.d.ts +7 -7
  91. package/dist/types/actions/workflow-step-edit.d.ts.map +1 -1
  92. package/dist/types/command/index.d.ts +1 -2
  93. package/dist/types/command/index.d.ts.map +1 -1
  94. package/dist/types/events/index.d.ts +26 -24
  95. package/dist/types/events/index.d.ts.map +1 -1
  96. package/dist/types/events/index.js +4 -15
  97. package/dist/types/events/index.js.map +1 -1
  98. package/dist/types/middleware.d.ts +26 -14
  99. package/dist/types/middleware.d.ts.map +1 -1
  100. package/dist/types/middleware.js +3 -0
  101. package/dist/types/middleware.js.map +1 -1
  102. package/dist/types/options/index.d.ts +16 -51
  103. package/dist/types/options/index.d.ts.map +1 -1
  104. package/dist/types/receiver.d.ts +3 -3
  105. package/dist/types/receiver.d.ts.map +1 -1
  106. package/dist/types/shortcuts/global-shortcut.d.ts.map +1 -1
  107. package/dist/types/shortcuts/index.d.ts +14 -9
  108. package/dist/types/shortcuts/index.d.ts.map +1 -1
  109. package/dist/types/shortcuts/message-shortcut.d.ts.map +1 -1
  110. package/dist/types/utilities.d.ts +27 -18
  111. package/dist/types/utilities.d.ts.map +1 -1
  112. package/dist/types/utilities.js +7 -0
  113. package/dist/types/utilities.js.map +1 -1
  114. package/dist/types/view/index.d.ts +15 -7
  115. package/dist/types/view/index.d.ts.map +1 -1
  116. package/package.json +27 -41
  117. package/dist/WorkflowFunction.d.ts +0 -63
  118. package/dist/WorkflowFunction.d.ts.map +0 -1
  119. package/dist/WorkflowFunction.js +0 -130
  120. package/dist/WorkflowFunction.js.map +0 -1
  121. package/dist/receivers/http-utils.d.ts +0 -5
  122. package/dist/receivers/http-utils.d.ts.map +0 -1
  123. package/dist/receivers/http-utils.js +0 -19
  124. package/dist/receivers/http-utils.js.map +0 -1
  125. package/dist/receivers/render-html-for-install-path.d.ts +0 -3
  126. package/dist/receivers/render-html-for-install-path.d.ts.map +0 -1
  127. package/dist/receivers/render-html-for-install-path.js +0 -32
  128. package/dist/receivers/render-html-for-install-path.js.map +0 -1
  129. package/dist/types/events/base-events.d.ts +0 -1187
  130. package/dist/types/events/base-events.d.ts.map +0 -1
  131. package/dist/types/events/base-events.js +0 -5
  132. package/dist/types/events/base-events.js.map +0 -1
  133. package/dist/types/events/message-events.d.ts +0 -348
  134. package/dist/types/events/message-events.d.ts.map +0 -1
  135. package/dist/types/events/message-events.js +0 -3
  136. package/dist/types/events/message-events.js.map +0 -1
  137. package/dist/types/helpers.d.ts +0 -17
  138. package/dist/types/helpers.d.ts.map +0 -1
  139. package/dist/types/helpers.js +0 -3
  140. 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 util_1 = __importDefault(require("util"));
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 SocketModeReceiver_1 = __importDefault(require("./receivers/SocketModeReceiver"));
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
- // eslint-disable-next-line import/order
20
- const allSettled = require("promise.allsettled"); // eslint-disable-line @typescript-eslint/no-require-imports
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
- constructor() {
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
- 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, } = {}) {
51
- // Some payloads don't have teamId anymore. So we use EnterpriseId in those scenarios
52
- this.clients = {};
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 !== null && logLevel !== void 0 ? logLevel : logger_1.LogLevel.DEBUG;
86
+ this.logLevel = logLevel ?? logger_1.LogLevel.DEBUG;
58
87
  // Set SocketMode to true if one wasn't passed in
59
- this.socketMode = socketMode !== null && socketMode !== void 0 ? socketMode : true;
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 !== null && socketMode !== void 0 ? socketMode : false;
92
+ this.socketMode = socketMode ?? false;
64
93
  // Set logLevel to Info if one wasn't passed in
65
- this.logLevel = logLevel !== null && logLevel !== void 0 ? logLevel : logger_1.LogLevel.INFO;
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((0, builtin_1.ignoreSelf)());
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
263
- const _listeners = listeners; // FIXME: workaround for TypeScript 4.7 breaking changes
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' || util_1.default.types.isRegExp(patternOrMiddleware)) {
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
277
- }); // FIXME: workaround for TypeScript 4.7 breaking changes
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' || util_1.default.types.isRegExp(callbackIdOrConstraints) ?
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
295
- const _listeners = listeners; // FIXME: workaround for TypeScript 4.7 breaking changes
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' || util_1.default.types.isRegExp(actionIdOrConstraints) ?
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
314
- const _listeners = listeners; // FIXME: workaround for TypeScript 4.7 breaking changes
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
319
- const _listeners = listeners; // FIXME: workaround for TypeScript 4.7 breaking changes
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
- util_1.default.types.isRegExp(actionIdOrConstraints) ?
330
- { action_id: actionIdOrConstraints } :
331
- actionIdOrConstraints;
332
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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' || util_1.default.types.isRegExp(callbackIdOrConstraints) ?
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
351
- const _listeners = listeners; // FIXME: workaround for TypeScript 4.7 breaking changes
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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
- const postMessageArguments = typeof message === 'string' ?
446
- { token, text: message, channel: channelId } :
447
- { ...message, token, channel: channelId };
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
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
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
- const token = selectToken(context);
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 shouldn't get a next fn
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 without a `next` execution
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
- // `next` is already set in the outer processMiddleware
649
+ next: () => { },
580
650
  }));
581
651
  });
582
- const settledListenerResults = await allSettled(listenerResults);
583
- const rejectedListenerResults = settledListenerResults.filter((lr) => lr.status === 'rejected');
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
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
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#authenticating-oauth for these required fields.\n`);
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
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
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.replace(/&/g, '&')
953
+ return input
954
+ .replace(/&/g, '&')
884
955
  .replace(/</g, '&lt;')
885
956
  .replace(/>/g, '&gt;')
886
957
  .replace(/"/g, '&quot;')
@@ -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