@slack/bolt 3.6.0 → 3.9.0

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 (93) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +4 -2
  3. package/dist/App.d.ts +60 -4
  4. package/dist/App.d.ts.map +1 -1
  5. package/dist/App.js +179 -100
  6. package/dist/App.js.map +1 -1
  7. package/dist/WorkflowStep.d.ts.map +1 -1
  8. package/dist/WorkflowStep.js +25 -28
  9. package/dist/WorkflowStep.js.map +1 -1
  10. package/dist/conversation-store.d.ts.map +1 -1
  11. package/dist/conversation-store.js +5 -6
  12. package/dist/conversation-store.js.map +1 -1
  13. package/dist/errors.d.ts +13 -5
  14. package/dist/errors.d.ts.map +1 -1
  15. package/dist/errors.js +25 -9
  16. package/dist/errors.js.map +1 -1
  17. package/dist/helpers.d.ts.map +1 -1
  18. package/dist/helpers.js +1 -0
  19. package/dist/helpers.js.map +1 -1
  20. package/dist/index.js +2 -2
  21. package/dist/index.js.map +1 -1
  22. package/dist/middleware/builtin.d.ts.map +1 -1
  23. package/dist/middleware/builtin.js +0 -19
  24. package/dist/middleware/builtin.js.map +1 -1
  25. package/dist/middleware/process.d.ts +1 -1
  26. package/dist/middleware/process.d.ts.map +1 -1
  27. package/dist/middleware/process.js +1 -2
  28. package/dist/middleware/process.js.map +1 -1
  29. package/dist/receivers/AwsLambdaReceiver.d.ts +4 -1
  30. package/dist/receivers/AwsLambdaReceiver.d.ts.map +1 -1
  31. package/dist/receivers/AwsLambdaReceiver.js +15 -20
  32. package/dist/receivers/AwsLambdaReceiver.js.map +1 -1
  33. package/dist/receivers/ExpressReceiver.d.ts +20 -7
  34. package/dist/receivers/ExpressReceiver.d.ts.map +1 -1
  35. package/dist/receivers/ExpressReceiver.js +167 -87
  36. package/dist/receivers/ExpressReceiver.js.map +1 -1
  37. package/dist/receivers/HTTPReceiver.d.ts +54 -4
  38. package/dist/receivers/HTTPReceiver.d.ts.map +1 -1
  39. package/dist/receivers/HTTPReceiver.js +240 -94
  40. package/dist/receivers/HTTPReceiver.js.map +1 -1
  41. package/dist/receivers/SocketModeReceiver.d.ts +18 -1
  42. package/dist/receivers/SocketModeReceiver.d.ts.map +1 -1
  43. package/dist/receivers/SocketModeReceiver.js +109 -41
  44. package/dist/receivers/SocketModeReceiver.js.map +1 -1
  45. package/dist/receivers/custom-routes.d.ts +14 -0
  46. package/dist/receivers/custom-routes.d.ts.map +1 -0
  47. package/dist/receivers/custom-routes.js +33 -0
  48. package/dist/receivers/custom-routes.js.map +1 -0
  49. package/dist/receivers/http-utils.d.ts +5 -0
  50. package/dist/receivers/http-utils.d.ts.map +1 -0
  51. package/dist/receivers/http-utils.js +35 -0
  52. package/dist/receivers/http-utils.js.map +1 -0
  53. package/dist/receivers/render-html-for-install-path.d.ts +1 -0
  54. package/dist/receivers/render-html-for-install-path.d.ts.map +1 -1
  55. package/dist/receivers/render-html-for-install-path.js +6 -1
  56. package/dist/receivers/render-html-for-install-path.js.map +1 -1
  57. package/dist/receivers/verify-redirect-opts.d.ts +7 -0
  58. package/dist/receivers/verify-redirect-opts.d.ts.map +1 -0
  59. package/dist/receivers/verify-redirect-opts.js +23 -0
  60. package/dist/receivers/verify-redirect-opts.js.map +1 -0
  61. package/dist/receivers/verify-request.d.ts +1 -0
  62. package/dist/receivers/verify-request.d.ts.map +1 -1
  63. package/dist/receivers/verify-request.js +8 -4
  64. package/dist/receivers/verify-request.js.map +1 -1
  65. package/dist/types/actions/block-action.d.ts +8 -1
  66. package/dist/types/actions/block-action.d.ts.map +1 -1
  67. package/dist/types/actions/index.d.ts +4 -4
  68. package/dist/types/actions/index.d.ts.map +1 -1
  69. package/dist/types/actions/index.js.map +1 -1
  70. package/dist/types/actions/workflow-step-edit.d.ts.map +1 -1
  71. package/dist/types/events/base-events.d.ts +5 -5
  72. package/dist/types/events/base-events.d.ts.map +1 -1
  73. package/dist/types/events/base-events.js.map +1 -1
  74. package/dist/types/events/index.d.ts +4 -4
  75. package/dist/types/events/index.d.ts.map +1 -1
  76. package/dist/types/events/index.js.map +1 -1
  77. package/dist/types/events/message-events.d.ts.map +1 -1
  78. package/dist/types/helpers.d.ts +2 -2
  79. package/dist/types/helpers.d.ts.map +1 -1
  80. package/dist/types/middleware.d.ts +10 -1
  81. package/dist/types/middleware.d.ts.map +1 -1
  82. package/dist/types/middleware.js +11 -0
  83. package/dist/types/middleware.js.map +1 -1
  84. package/dist/types/options/index.d.ts +2 -2
  85. package/dist/types/options/index.d.ts.map +1 -1
  86. package/dist/types/receiver.d.ts +3 -0
  87. package/dist/types/receiver.d.ts.map +1 -1
  88. package/dist/types/shortcuts/index.d.ts +2 -2
  89. package/dist/types/shortcuts/index.d.ts.map +1 -1
  90. package/dist/types/shortcuts/index.js.map +1 -1
  91. package/dist/types/shortcuts/message-shortcut.d.ts.map +1 -1
  92. package/dist/types/utilities.d.ts.map +1 -1
  93. package/package.json +18 -20
package/dist/App.js CHANGED
@@ -11,14 +11,22 @@ const axios_1 = __importDefault(require("axios"));
11
11
  const SocketModeReceiver_1 = __importDefault(require("./receivers/SocketModeReceiver"));
12
12
  const HTTPReceiver_1 = __importDefault(require("./receivers/HTTPReceiver"));
13
13
  const builtin_1 = require("./middleware/builtin");
14
- const process_1 = require("./middleware/process");
14
+ const process_1 = __importDefault(require("./middleware/process"));
15
15
  const conversation_store_1 = require("./conversation-store");
16
16
  const helpers_1 = require("./helpers");
17
17
  const errors_1 = require("./errors");
18
+ const middleware_1 = require("./types/middleware");
18
19
  // eslint-disable-next-line import/order
19
20
  const allSettled = require("promise.allsettled"); // eslint-disable-line @typescript-eslint/no-require-imports
20
- // eslint-disable-next-line @typescript-eslint/no-require-imports
21
+ // eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-commonjs
21
22
  const packageJson = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires
23
+ // ----------------------------
24
+ // For listener registration methods
25
+ const validViewTypes = ['view_closed', 'view_submission'];
26
+ // ----------------------------
27
+ // For the constructor
28
+ const tokenUsage = 'Apps used in a single workspace can be initialized with a token. Apps used in many workspaces ' +
29
+ 'should be initialized with oauth installer options or authorize.';
22
30
  var logger_2 = require("@slack/logger");
23
31
  Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_2.LogLevel; } });
24
32
  class WebClientPool {
@@ -39,10 +47,11 @@ class WebClientPool {
39
47
  * A Slack App
40
48
  */
41
49
  class App {
42
- constructor({ signingSecret = undefined, endpoints = 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, clientId = undefined, clientSecret = undefined, stateSecret = undefined, installationStore = undefined, scopes = undefined, installerOptions = undefined, socketMode = undefined, developerMode = false, tokenVerificationEnabled = true, } = {}) {
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, } = {}) {
51
+ // this.logLevel = logLevel;
43
52
  // Some payloads don't have teamId anymore. So we use EnterpriseId in those scenarios
44
53
  this.clients = {};
45
- // this.logLevel = logLevel;
54
+ /* ------------------------ Developer mode ----------------------------- */
46
55
  this.developerMode = developerMode;
47
56
  if (developerMode) {
48
57
  // Set logLevel to Debug in Developer Mode if one wasn't passed in
@@ -56,6 +65,7 @@ class App {
56
65
  // Set logLevel to Info if one wasn't passed in
57
66
  this.logLevel = logLevel !== null && logLevel !== void 0 ? logLevel : logger_1.LogLevel.INFO;
58
67
  }
68
+ /* ------------------------ Set logger ----------------------------- */
59
69
  if (typeof logger === 'undefined') {
60
70
  // Initialize with the default logger
61
71
  const consoleLogger = new logger_1.ConsoleLogger();
@@ -68,7 +78,11 @@ class App {
68
78
  if (typeof this.logLevel !== 'undefined' && this.logger.getLevel() !== this.logLevel) {
69
79
  this.logger.setLevel(this.logLevel);
70
80
  }
81
+ // Error-related properties used to later determine args passed into the error handler
82
+ this.hasCustomErrorHandler = false;
71
83
  this.errorHandler = defaultErrorHandler(this.logger);
84
+ this.extendedErrorHandler = extendedErrorHandler;
85
+ /* ------------------------ Set client options ------------------------*/
72
86
  this.clientOptions = clientOptions !== undefined ? clientOptions : {};
73
87
  if (agent !== undefined && this.clientOptions.agent === undefined) {
74
88
  this.clientOptions.agent = agent;
@@ -81,11 +95,7 @@ class App {
81
95
  this.clientOptions.logLevel = logLevel;
82
96
  }
83
97
  else {
84
- if (logLevel !== undefined) {
85
- // If the constructor has both, logLevel is ignored
86
- this.logger.warn("As `logger` is passed as well, `logLevel` argument won't be used. Set the log level to the `logger` instance instead.");
87
- }
88
- // Since v3.4, WebClient starts sharing loggger with App
98
+ // Since v3.4, WebClient starts sharing logger with App
89
99
  this.clientOptions.logger = this.logger;
90
100
  }
91
101
  // The public WebClient instance (app.client)
@@ -108,6 +118,11 @@ class App {
108
118
  clientOptions: this.clientOptions,
109
119
  ...installerOptions,
110
120
  };
121
+ if (socketMode && port !== undefined && this.installerOptions.port === undefined) {
122
+ // SocketModeReceiver only uses a custom port number when listening for the OAuth flow.
123
+ // Therefore only installerOptions.port is available in the constructor arguments.
124
+ this.installerOptions.port = port;
125
+ }
111
126
  if (this.developerMode &&
112
127
  this.installerOptions &&
113
128
  (typeof this.installerOptions.callbackOptions === 'undefined' ||
@@ -123,43 +138,54 @@ class App {
123
138
  },
124
139
  };
125
140
  }
126
- // Check for required arguments of HTTPReceiver
141
+ /* --------------------- Initialize receiver ---------------------- */
127
142
  if (receiver !== undefined) {
143
+ // Custom receiver supplied
144
+ if (this.socketMode === true) {
145
+ // socketMode = true should result in SocketModeReceiver being used as receiver
146
+ // TODO: Add case for when socketMode = true and receiver = SocketModeReceiver
147
+ // as this should not result in an error
148
+ throw new errors_1.AppInitializationError('You cannot supply a custom receiver when socketMode is set to true.');
149
+ }
128
150
  this.receiver = receiver;
129
151
  }
130
- else if (this.socketMode) {
152
+ else if (this.socketMode === true) {
131
153
  if (appToken === undefined) {
132
- throw new errors_1.AppInitializationError('You must provide an appToken when using Socket Mode');
154
+ throw new errors_1.AppInitializationError('You must provide an appToken when socketMode is set to true. To generate an appToken see: https://api.slack.com/apis/connections/socket#token');
133
155
  }
134
156
  this.logger.debug('Initializing SocketModeReceiver');
135
- // Create default SocketModeReceiver
136
157
  this.receiver = new SocketModeReceiver_1.default({
137
158
  appToken,
138
159
  clientId,
139
160
  clientSecret,
140
161
  stateSecret,
162
+ redirectUri,
141
163
  installationStore,
142
164
  scopes,
143
165
  logger,
144
166
  logLevel: this.logLevel,
145
167
  installerOptions: this.installerOptions,
168
+ customRoutes,
146
169
  });
147
170
  }
148
- else if (signingSecret === undefined) {
149
- // No custom receiver
150
- throw new errors_1.AppInitializationError('Signing secret not found, so could not initialize the default receiver. Set a signing secret or use a ' +
151
- 'custom receiver.');
171
+ else if (signatureVerification === true && signingSecret === undefined) {
172
+ // Using default receiver HTTPReceiver, signature verification enabled, missing signingSecret
173
+ throw new errors_1.AppInitializationError('signingSecret is required to initialize the default receiver. Set signingSecret or use a ' +
174
+ 'custom receiver. You can find your Signing Secret in your Slack App Settings.');
152
175
  }
153
176
  else {
154
177
  this.logger.debug('Initializing HTTPReceiver');
155
- // Create default HTTPReceiver
156
178
  this.receiver = new HTTPReceiver_1.default({
157
- signingSecret,
179
+ signingSecret: signingSecret || '',
158
180
  endpoints,
181
+ port,
182
+ customRoutes,
159
183
  processBeforeResponse,
184
+ signatureVerification,
160
185
  clientId,
161
186
  clientSecret,
162
187
  stateSecret,
188
+ redirectUri,
163
189
  installationStore,
164
190
  scopes,
165
191
  logger,
@@ -167,16 +193,19 @@ class App {
167
193
  installerOptions: this.installerOptions,
168
194
  });
169
195
  }
196
+ /* ------------------------ Set authorize ----------------------------- */
170
197
  let usingOauth = false;
171
- if (this.receiver.installer !== undefined &&
172
- this.receiver.installer.authorize !== undefined) {
198
+ const httpReceiver = this.receiver;
199
+ if (httpReceiver.installer !== undefined &&
200
+ httpReceiver.installer.authorize !== undefined) {
173
201
  // This supports using the built in HTTPReceiver, declaring your own HTTPReceiver
174
202
  // and theoretically, doing a fully custom (non express) receiver that implements OAuth
175
203
  usingOauth = true;
176
204
  }
177
205
  if (token !== undefined) {
178
- if (authorize !== undefined || usingOauth) {
179
- throw new errors_1.AppInitializationError(`token as well as authorize or oauth installer options were provided. ${tokenUsage}`);
206
+ // If a token is supplied, the app is installed in at least one workspace
207
+ if (usingOauth || authorize !== undefined) {
208
+ throw new errors_1.AppInitializationError(`You cannot provide a token along with either oauth installer options or authorize. ${tokenUsage}`);
180
209
  }
181
210
  this.authorize = singleAuthorization(this.client, {
182
211
  botId,
@@ -185,31 +214,33 @@ class App {
185
214
  }, tokenVerificationEnabled);
186
215
  }
187
216
  else if (authorize === undefined && !usingOauth) {
188
- throw new errors_1.AppInitializationError(`No token, no authorize, and no oauth installer options provided. ${tokenUsage}`);
217
+ 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`);
189
218
  }
190
219
  else if (authorize !== undefined && usingOauth) {
191
- throw new errors_1.AppInitializationError(`Both authorize options and oauth installer options provided. ${tokenUsage}`);
220
+ throw new errors_1.AppInitializationError(`You cannot provide both authorize and oauth installer options. ${tokenUsage}`);
192
221
  }
193
222
  else if (authorize === undefined && usingOauth) {
194
- this.authorize = this.receiver.installer.authorize;
223
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
224
+ this.authorize = httpReceiver.installer.authorize;
195
225
  }
196
226
  else if (authorize !== undefined && !usingOauth) {
197
227
  this.authorize = authorize;
198
228
  }
199
229
  else {
200
- this.logger.error('Never should have reached this point, please report to the team');
201
- helpers_1.assertNever();
230
+ this.logger.error('Something has gone wrong. Please report this issue to the maintainers. https://github.com/slackapi/bolt-js/issues');
231
+ (0, helpers_1.assertNever)();
202
232
  }
203
233
  // Conditionally use a global middleware that ignores events (including messages) that are sent from this app
204
234
  if (ignoreSelf) {
205
- this.use(builtin_1.ignoreSelf());
235
+ this.use((0, builtin_1.ignoreSelf)());
206
236
  }
207
237
  // Use conversation state global middleware
208
238
  if (convoStore !== false) {
209
239
  // Use the memory store by default, or another store if provided
210
240
  const store = convoStore === undefined ? new conversation_store_1.MemoryStore() : convoStore;
211
- this.use(conversation_store_1.conversationContext(store));
241
+ this.use((0, conversation_store_1.conversationContext)(store));
212
242
  }
243
+ /* ------------------------ Initialize receiver ------------------------ */
213
244
  // Should be last to avoid exposing partially initialized app
214
245
  this.receiver.init(this);
215
246
  }
@@ -243,6 +274,7 @@ class App {
243
274
  // TODO: HTTPReceiver['start'] should be the actual receiver's return type
244
275
  return this.receiver.start(...args);
245
276
  }
277
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
246
278
  stop(...args) {
247
279
  return this.receiver.stop(...args);
248
280
  }
@@ -263,27 +295,27 @@ class App {
263
295
  }
264
296
  this.listeners.push([
265
297
  builtin_1.onlyEvents,
266
- builtin_1.matchEventType(eventNameOrPattern),
298
+ (0, builtin_1.matchEventType)(eventNameOrPattern),
267
299
  ...listeners,
268
300
  ]);
269
301
  }
270
302
  message(...patternsOrMiddleware) {
271
303
  const messageMiddleware = patternsOrMiddleware.map((patternOrMiddleware) => {
272
304
  if (typeof patternOrMiddleware === 'string' || util_1.default.types.isRegExp(patternOrMiddleware)) {
273
- return builtin_1.matchMessage(patternOrMiddleware);
305
+ return (0, builtin_1.matchMessage)(patternOrMiddleware);
274
306
  }
275
307
  return patternOrMiddleware;
276
308
  });
277
309
  this.listeners.push([
278
310
  builtin_1.onlyEvents,
279
- builtin_1.matchEventType('message'),
311
+ (0, builtin_1.matchEventType)('message'),
280
312
  ...messageMiddleware,
281
313
  ]);
282
314
  }
283
315
  shortcut(callbackIdOrConstraints, ...listeners) {
284
- const constraints = typeof callbackIdOrConstraints === 'string' || util_1.default.types.isRegExp(callbackIdOrConstraints)
285
- ? { callback_id: callbackIdOrConstraints }
286
- : callbackIdOrConstraints;
316
+ const constraints = typeof callbackIdOrConstraints === 'string' || util_1.default.types.isRegExp(callbackIdOrConstraints) ?
317
+ { callback_id: callbackIdOrConstraints } :
318
+ callbackIdOrConstraints;
287
319
  // Fail early if the constraints contain invalid keys
288
320
  const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'callback_id' && k !== 'type');
289
321
  if (unknownConstraintKeys.length > 0) {
@@ -292,37 +324,37 @@ class App {
292
324
  }
293
325
  this.listeners.push([
294
326
  builtin_1.onlyShortcuts,
295
- builtin_1.matchConstraints(constraints),
327
+ (0, builtin_1.matchConstraints)(constraints),
296
328
  ...listeners,
297
329
  ]);
298
330
  }
299
331
  action(actionIdOrConstraints, ...listeners) {
300
332
  // Normalize Constraints
301
- const constraints = typeof actionIdOrConstraints === 'string' || util_1.default.types.isRegExp(actionIdOrConstraints)
302
- ? { action_id: actionIdOrConstraints }
303
- : actionIdOrConstraints;
333
+ const constraints = typeof actionIdOrConstraints === 'string' || util_1.default.types.isRegExp(actionIdOrConstraints) ?
334
+ { action_id: actionIdOrConstraints } :
335
+ actionIdOrConstraints;
304
336
  // Fail early if the constraints contain invalid keys
305
337
  const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'action_id' && k !== 'block_id' && k !== 'callback_id' && k !== 'type');
306
338
  if (unknownConstraintKeys.length > 0) {
307
339
  this.logger.error(`Action listener cannot be attached using unknown constraint keys: ${unknownConstraintKeys.join(', ')}`);
308
340
  return;
309
341
  }
310
- this.listeners.push([builtin_1.onlyActions, builtin_1.matchConstraints(constraints), ...listeners]);
342
+ this.listeners.push([builtin_1.onlyActions, (0, builtin_1.matchConstraints)(constraints), ...listeners]);
311
343
  }
312
344
  command(commandName, ...listeners) {
313
- this.listeners.push([builtin_1.onlyCommands, builtin_1.matchCommandName(commandName), ...listeners]);
345
+ this.listeners.push([builtin_1.onlyCommands, (0, builtin_1.matchCommandName)(commandName), ...listeners]);
314
346
  }
315
347
  // TODO: reflect the type in constraits to Source
316
348
  options(actionIdOrConstraints, ...listeners) {
317
- const constraints = typeof actionIdOrConstraints === 'string' || util_1.default.types.isRegExp(actionIdOrConstraints)
318
- ? { action_id: actionIdOrConstraints }
319
- : actionIdOrConstraints;
320
- this.listeners.push([builtin_1.onlyOptions, builtin_1.matchConstraints(constraints), ...listeners]);
349
+ const constraints = typeof actionIdOrConstraints === 'string' || util_1.default.types.isRegExp(actionIdOrConstraints) ?
350
+ { action_id: actionIdOrConstraints } :
351
+ actionIdOrConstraints;
352
+ this.listeners.push([builtin_1.onlyOptions, (0, builtin_1.matchConstraints)(constraints), ...listeners]);
321
353
  }
322
354
  view(callbackIdOrConstraints, ...listeners) {
323
- const constraints = typeof callbackIdOrConstraints === 'string' || util_1.default.types.isRegExp(callbackIdOrConstraints)
324
- ? { callback_id: callbackIdOrConstraints, type: 'view_submission' }
325
- : callbackIdOrConstraints;
355
+ const constraints = typeof callbackIdOrConstraints === 'string' || util_1.default.types.isRegExp(callbackIdOrConstraints) ?
356
+ { callback_id: callbackIdOrConstraints, type: 'view_submission' } :
357
+ callbackIdOrConstraints;
326
358
  // Fail early if the constraints contain invalid keys
327
359
  const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'callback_id' && k !== 'type');
328
360
  if (unknownConstraintKeys.length > 0) {
@@ -335,12 +367,13 @@ class App {
335
367
  }
336
368
  this.listeners.push([
337
369
  builtin_1.onlyViewActions,
338
- builtin_1.matchConstraints(constraints),
370
+ (0, builtin_1.matchConstraints)(constraints),
339
371
  ...listeners,
340
372
  ]);
341
373
  }
342
374
  error(errorHandler) {
343
375
  this.errorHandler = errorHandler;
376
+ this.hasCustomErrorHandler = true;
344
377
  }
345
378
  /**
346
379
  * Handles events from the receiver
@@ -356,7 +389,7 @@ class App {
356
389
  // or even all of the args, as properties of the error. This would give error handling code some ability to deal
357
390
  // with "finally" type error situations.
358
391
  // Introspect the body to determine what type of incoming event is being handled, and any channel context
359
- const { type, conversationId } = helpers_1.getTypeAndConversation(body);
392
+ const { type, conversationId } = (0, helpers_1.getTypeAndConversation)(body);
360
393
  // If the type could not be determined, warn and exit
361
394
  if (type === undefined) {
362
395
  this.logger.warn('Could not determine the type of an incoming event. No listeners will be called.');
@@ -377,9 +410,18 @@ class App {
377
410
  }
378
411
  }
379
412
  catch (error) {
413
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
414
+ const e = error;
380
415
  this.logger.warn('Authorization of incoming event did not succeed. No listeners will be called.');
381
- error.code = 'slack_bolt_authorization_error';
382
- return this.handleError(error);
416
+ e.code = errors_1.ErrorCode.AuthorizationError;
417
+ // disabling due to https://github.com/typescript-eslint/typescript-eslint/issues/1277
418
+ // eslint-disable-next-line consistent-return
419
+ return this.handleError({
420
+ error: e,
421
+ logger: this.logger,
422
+ body: bodyArg,
423
+ context: {},
424
+ });
383
425
  }
384
426
  // Try to set teamId from AuthorizeResult before using one from source
385
427
  if (authorizeResult.teamId === undefined && source.teamId !== undefined) {
@@ -389,32 +431,60 @@ class App {
389
431
  if (authorizeResult.enterpriseId === undefined && source.enterpriseId !== undefined) {
390
432
  authorizeResult.enterpriseId = source.enterpriseId;
391
433
  }
392
- const context = { ...authorizeResult };
434
+ if (typeof event.customProperties !== 'undefined') {
435
+ const customProps = event.customProperties;
436
+ const builtinKeyDetected = middleware_1.contextBuiltinKeys.find((key) => key in customProps);
437
+ if (typeof builtinKeyDetected !== 'undefined') {
438
+ throw new errors_1.InvalidCustomPropertyError('customProperties cannot have the same names with the built-in ones');
439
+ }
440
+ }
441
+ const context = {
442
+ ...authorizeResult,
443
+ ...event.customProperties,
444
+ retryNum: event.retryNum,
445
+ retryReason: event.retryReason,
446
+ };
393
447
  // Factory for say() utility
394
448
  const createSay = (channelId) => {
395
449
  const token = selectToken(context);
396
450
  return (message) => {
397
- const postMessageArguments = typeof message === 'string'
398
- ? { token, text: message, channel: channelId }
399
- : { ...message, token, channel: channelId };
451
+ const postMessageArguments = typeof message === 'string' ?
452
+ { token, text: message, channel: channelId } :
453
+ { ...message, token, channel: channelId };
400
454
  return this.client.chat.postMessage(postMessageArguments);
401
455
  };
402
456
  };
403
- // Set body and payload (this value will eventually conform to AnyMiddlewareArgs)
457
+ // Set body and payload
458
+ // TODO: this value should eventually conform to AnyMiddlewareArgs
459
+ let payload;
460
+ switch (type) {
461
+ case helpers_1.IncomingEventType.Event:
462
+ payload = bodyArg.event;
463
+ break;
464
+ case helpers_1.IncomingEventType.ViewAction:
465
+ payload = bodyArg.view;
466
+ break;
467
+ case helpers_1.IncomingEventType.Shortcut:
468
+ payload = bodyArg;
469
+ break;
470
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
471
+ // @ts-ignore: Fallthrough case in switch
472
+ case helpers_1.IncomingEventType.Action:
473
+ if (isBlockActionOrInteractiveMessageBody(bodyArg)) {
474
+ const { actions } = bodyArg;
475
+ [payload] = actions;
476
+ break;
477
+ }
478
+ // If above conditional does not hit, fall through to fallback payload in default block below
479
+ default:
480
+ payload = bodyArg;
481
+ break;
482
+ }
404
483
  // NOTE: the following doesn't work because... distributive?
405
484
  // const listenerArgs: Partial<AnyMiddlewareArgs> = {
406
485
  const listenerArgs = {
407
486
  body: bodyArg,
408
- payload: type === helpers_1.IncomingEventType.Event
409
- ? bodyArg.event
410
- : type === helpers_1.IncomingEventType.ViewAction
411
- ? bodyArg.view
412
- : type === helpers_1.IncomingEventType.Shortcut
413
- ? bodyArg
414
- : type === helpers_1.IncomingEventType.Action &&
415
- isBlockActionOrInteractiveMessageBody(bodyArg)
416
- ? bodyArg.actions[0]
417
- : bodyArg,
487
+ payload,
418
488
  };
419
489
  // Set aliases
420
490
  if (type === helpers_1.IncomingEventType.Event) {
@@ -493,7 +563,7 @@ class App {
493
563
  }
494
564
  // Dispatch event through the global middleware chain
495
565
  try {
496
- await process_1.processMiddleware(this.middleware, listenerArgs, context, client, this.logger, async () => {
566
+ await (0, process_1.default)(this.middleware, listenerArgs, context, client, this.logger, async () => {
497
567
  // Dispatch the event through the listener middleware chains and aggregate their results
498
568
  // TODO: change the name of this.middleware and this.listeners to help this make more sense
499
569
  const listenerResults = this.listeners.map(async (origListenerMiddleware) => {
@@ -501,11 +571,19 @@ class App {
501
571
  const listenerMiddleware = [...origListenerMiddleware];
502
572
  // Don't process the last item in the listenerMiddleware array - it shouldn't get a next fn
503
573
  const listener = listenerMiddleware.pop();
504
- if (listener !== undefined) {
505
- return process_1.processMiddleware(listenerMiddleware, listenerArgs, context, client, this.logger, async () =>
506
- // When the listener middleware chain is done processing, call the listener without a next fn
507
- listener({ ...listenerArgs, context, client, logger: this.logger }));
574
+ if (listener === undefined) {
575
+ return undefined;
508
576
  }
577
+ return (0, process_1.default)(listenerMiddleware, listenerArgs, context, client, this.logger,
578
+ // When all of the listener middleware are done processing,
579
+ // `listener` here will be called without a `next` execution
580
+ async () => listener({
581
+ ...listenerArgs,
582
+ context,
583
+ client,
584
+ logger: this.logger,
585
+ // `next` is already set in the outer processMiddleware
586
+ }));
509
587
  });
510
588
  const settledListenerResults = await allSettled(listenerResults);
511
589
  const rejectedListenerResults = settledListenerResults.filter((lr) => lr.status === 'rejected');
@@ -518,21 +596,29 @@ class App {
518
596
  });
519
597
  }
520
598
  catch (error) {
521
- return this.handleError(error);
599
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
600
+ const e = error;
601
+ // disabling due to https://github.com/typescript-eslint/typescript-eslint/issues/1277
602
+ // eslint-disable-next-line consistent-return
603
+ return this.handleError({
604
+ context,
605
+ error: e,
606
+ logger: this.logger,
607
+ body: bodyArg,
608
+ });
522
609
  }
523
610
  }
524
611
  /**
525
612
  * Global error handler. The final destination for all errors (hopefully).
526
613
  */
527
- handleError(error) {
528
- return this.errorHandler(errors_1.asCodedError(error));
614
+ handleError(args) {
615
+ const { error, ...rest } = args;
616
+ return this.extendedErrorHandler && this.hasCustomErrorHandler ?
617
+ this.errorHandler({ error: (0, errors_1.asCodedError)(error), ...rest }) :
618
+ this.errorHandler((0, errors_1.asCodedError)(error));
529
619
  }
530
620
  }
531
621
  exports.default = App;
532
- // ----------------------------
533
- // For the constructor
534
- const tokenUsage = 'Apps used in one workspace should be initialized with a token. Apps used in many workspaces ' +
535
- 'should be initialized with oauth installer or authorize.';
536
622
  function defaultErrorHandler(logger) {
537
623
  return (error) => {
538
624
  logger.error(error);
@@ -543,14 +629,12 @@ function defaultErrorHandler(logger) {
543
629
  // singleAuthorization
544
630
  function runAuthTestForBotToken(client, authorization) {
545
631
  // TODO: warn when something needed isn't found
546
- return authorization.botUserId !== undefined && authorization.botId !== undefined
547
- ? Promise.resolve({ botUserId: authorization.botUserId, botId: authorization.botId })
548
- : client.auth.test({ token: authorization.botToken }).then((result) => {
549
- return {
550
- botUserId: result.user_id,
551
- botId: result.bot_id,
552
- };
553
- });
632
+ return authorization.botUserId !== undefined && authorization.botId !== undefined ?
633
+ Promise.resolve({ botUserId: authorization.botUserId, botId: authorization.botId }) :
634
+ client.auth.test({ token: authorization.botToken }).then((result) => ({
635
+ botUserId: result.user_id,
636
+ botId: result.bot_id,
637
+ }));
554
638
  }
555
639
  async function buildAuthorizeResult(isEnterpriseInstall, authTestResult, authorization) {
556
640
  return { isEnterpriseInstall, botToken: authorization.botToken, ...(await authTestResult) };
@@ -562,9 +646,7 @@ function singleAuthorization(client, authorization, tokenVerificationEnabled) {
562
646
  if (tokenVerificationEnabled) {
563
647
  // call auth.test immediately
564
648
  cachedAuthTestResult = runAuthTestForBotToken(client, authorization);
565
- return async ({ isEnterpriseInstall }) => {
566
- return buildAuthorizeResult(isEnterpriseInstall, cachedAuthTestResult, authorization);
567
- };
649
+ return async ({ isEnterpriseInstall }) => buildAuthorizeResult(isEnterpriseInstall, cachedAuthTestResult, authorization);
568
650
  }
569
651
  return async ({ isEnterpriseInstall }) => {
570
652
  // hold off calling auth.test API until the first access to authorize function
@@ -606,7 +688,7 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
606
688
  // This is the only place where this function might return undefined
607
689
  return bodyAsActionOrOptionsOrViewActionOrShortcut.user.team_id;
608
690
  }
609
- return helpers_1.assertNever(type);
691
+ return (0, helpers_1.assertNever)(type);
610
692
  })();
611
693
  const enterpriseId = (() => {
612
694
  if (type === helpers_1.IncomingEventType.Event) {
@@ -638,7 +720,7 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
638
720
  }
639
721
  return undefined;
640
722
  }
641
- return helpers_1.assertNever(type);
723
+ return (0, helpers_1.assertNever)(type);
642
724
  })();
643
725
  const userId = (() => {
644
726
  if (type === helpers_1.IncomingEventType.Event) {
@@ -671,7 +753,7 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
671
753
  if (type === helpers_1.IncomingEventType.Command) {
672
754
  return body.user_id;
673
755
  }
674
- return helpers_1.assertNever(type);
756
+ return (0, helpers_1.assertNever)(type);
675
757
  })();
676
758
  return {
677
759
  userId,
@@ -706,17 +788,14 @@ function isBlockActionOrInteractiveMessageBody(body) {
706
788
  function selectToken(context) {
707
789
  return context.botToken !== undefined ? context.botToken : context.userToken;
708
790
  }
709
- function buildRespondFn(axiosInstance, response_url) {
791
+ function buildRespondFn(axiosInstance, responseUrl) {
710
792
  return async (message) => {
711
793
  const normalizedArgs = typeof message === 'string' ? { text: message } : message;
712
- return axiosInstance.post(response_url, normalizedArgs);
794
+ return axiosInstance.post(responseUrl, normalizedArgs);
713
795
  };
714
796
  }
715
797
  // ----------------------------
716
- // For listener registration methods
717
- const validViewTypes = ['view_closed', 'view_submission'];
718
- // ----------------------------
719
798
  // Instrumentation
720
799
  // Don't change the position of the following code
721
- web_api_1.addAppMetadata({ name: packageJson.name, version: packageJson.version });
800
+ (0, web_api_1.addAppMetadata)({ name: packageJson.name, version: packageJson.version });
722
801
  //# sourceMappingURL=App.js.map