@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.
- package/LICENSE +1 -1
- package/README.md +4 -2
- package/dist/App.d.ts +60 -4
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +179 -100
- package/dist/App.js.map +1 -1
- package/dist/WorkflowStep.d.ts.map +1 -1
- package/dist/WorkflowStep.js +25 -28
- package/dist/WorkflowStep.js.map +1 -1
- package/dist/conversation-store.d.ts.map +1 -1
- package/dist/conversation-store.js +5 -6
- package/dist/conversation-store.js.map +1 -1
- package/dist/errors.d.ts +13 -5
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +25 -9
- package/dist/errors.js.map +1 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +1 -0
- package/dist/helpers.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/middleware/builtin.d.ts.map +1 -1
- package/dist/middleware/builtin.js +0 -19
- package/dist/middleware/builtin.js.map +1 -1
- package/dist/middleware/process.d.ts +1 -1
- package/dist/middleware/process.d.ts.map +1 -1
- package/dist/middleware/process.js +1 -2
- package/dist/middleware/process.js.map +1 -1
- package/dist/receivers/AwsLambdaReceiver.d.ts +4 -1
- package/dist/receivers/AwsLambdaReceiver.d.ts.map +1 -1
- package/dist/receivers/AwsLambdaReceiver.js +15 -20
- package/dist/receivers/AwsLambdaReceiver.js.map +1 -1
- package/dist/receivers/ExpressReceiver.d.ts +20 -7
- package/dist/receivers/ExpressReceiver.d.ts.map +1 -1
- package/dist/receivers/ExpressReceiver.js +167 -87
- package/dist/receivers/ExpressReceiver.js.map +1 -1
- package/dist/receivers/HTTPReceiver.d.ts +54 -4
- package/dist/receivers/HTTPReceiver.d.ts.map +1 -1
- package/dist/receivers/HTTPReceiver.js +240 -94
- package/dist/receivers/HTTPReceiver.js.map +1 -1
- package/dist/receivers/SocketModeReceiver.d.ts +18 -1
- package/dist/receivers/SocketModeReceiver.d.ts.map +1 -1
- package/dist/receivers/SocketModeReceiver.js +109 -41
- package/dist/receivers/SocketModeReceiver.js.map +1 -1
- package/dist/receivers/custom-routes.d.ts +14 -0
- package/dist/receivers/custom-routes.d.ts.map +1 -0
- package/dist/receivers/custom-routes.js +33 -0
- package/dist/receivers/custom-routes.js.map +1 -0
- package/dist/receivers/http-utils.d.ts +5 -0
- package/dist/receivers/http-utils.d.ts.map +1 -0
- package/dist/receivers/http-utils.js +35 -0
- package/dist/receivers/http-utils.js.map +1 -0
- package/dist/receivers/render-html-for-install-path.d.ts +1 -0
- package/dist/receivers/render-html-for-install-path.d.ts.map +1 -1
- package/dist/receivers/render-html-for-install-path.js +6 -1
- package/dist/receivers/render-html-for-install-path.js.map +1 -1
- package/dist/receivers/verify-redirect-opts.d.ts +7 -0
- package/dist/receivers/verify-redirect-opts.d.ts.map +1 -0
- package/dist/receivers/verify-redirect-opts.js +23 -0
- package/dist/receivers/verify-redirect-opts.js.map +1 -0
- package/dist/receivers/verify-request.d.ts +1 -0
- package/dist/receivers/verify-request.d.ts.map +1 -1
- package/dist/receivers/verify-request.js +8 -4
- package/dist/receivers/verify-request.js.map +1 -1
- package/dist/types/actions/block-action.d.ts +8 -1
- package/dist/types/actions/block-action.d.ts.map +1 -1
- package/dist/types/actions/index.d.ts +4 -4
- package/dist/types/actions/index.d.ts.map +1 -1
- package/dist/types/actions/index.js.map +1 -1
- package/dist/types/actions/workflow-step-edit.d.ts.map +1 -1
- package/dist/types/events/base-events.d.ts +5 -5
- package/dist/types/events/base-events.d.ts.map +1 -1
- package/dist/types/events/base-events.js.map +1 -1
- package/dist/types/events/index.d.ts +4 -4
- package/dist/types/events/index.d.ts.map +1 -1
- package/dist/types/events/index.js.map +1 -1
- package/dist/types/events/message-events.d.ts.map +1 -1
- package/dist/types/helpers.d.ts +2 -2
- package/dist/types/helpers.d.ts.map +1 -1
- package/dist/types/middleware.d.ts +10 -1
- package/dist/types/middleware.d.ts.map +1 -1
- package/dist/types/middleware.js +11 -0
- package/dist/types/middleware.js.map +1 -1
- package/dist/types/options/index.d.ts +2 -2
- package/dist/types/options/index.d.ts.map +1 -1
- package/dist/types/receiver.d.ts +3 -0
- package/dist/types/receiver.d.ts.map +1 -1
- package/dist/types/shortcuts/index.d.ts +2 -2
- package/dist/types/shortcuts/index.d.ts.map +1 -1
- package/dist/types/shortcuts/index.js.map +1 -1
- package/dist/types/shortcuts/message-shortcut.d.ts.map +1 -1
- package/dist/types/utilities.d.ts.map +1 -1
- 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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
//
|
|
150
|
-
throw new errors_1.AppInitializationError('
|
|
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
|
-
|
|
172
|
-
|
|
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
|
-
|
|
179
|
-
|
|
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(
|
|
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(`
|
|
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
|
-
|
|
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('
|
|
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
|
-
|
|
286
|
-
|
|
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
|
-
|
|
303
|
-
|
|
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
|
-
|
|
319
|
-
|
|
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
|
-
|
|
325
|
-
|
|
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
|
-
|
|
382
|
-
|
|
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
|
-
|
|
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
|
-
|
|
399
|
-
|
|
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
|
|
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
|
|
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.
|
|
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
|
|
505
|
-
return
|
|
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
|
-
|
|
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(
|
|
528
|
-
|
|
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
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
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,
|
|
791
|
+
function buildRespondFn(axiosInstance, responseUrl) {
|
|
710
792
|
return async (message) => {
|
|
711
793
|
const normalizedArgs = typeof message === 'string' ? { text: message } : message;
|
|
712
|
-
return axiosInstance.post(
|
|
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
|