@slack/bolt 3.6.0 → 3.9.0-hermesBeta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +4 -2
- package/dist/App.d.ts +67 -4
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +219 -106
- package/dist/App.js.map +1 -1
- package/dist/Subscription.d.ts +61 -0
- package/dist/Subscription.d.ts.map +1 -0
- package/dist/Subscription.js +169 -0
- package/dist/Subscription.js.map +1 -0
- 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 +2 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +9 -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 -20
- 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/notification-subscription.d.ts +59 -0
- package/dist/types/actions/notification-subscription.d.ts.map +1 -0
- package/dist/types/actions/notification-subscription.js +3 -0
- package/dist/types/actions/notification-subscription.js.map +1 -0
- 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/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +1 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/middleware.d.ts +12 -2
- 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/subscription/index.d.ts +80 -0
- package/dist/types/subscription/index.d.ts.map +1 -0
- package/dist/types/subscription/index.js +3 -0
- package/dist/types/subscription/index.js.map +1 -0
- package/dist/types/utilities.d.ts.map +1 -1
- package/package.json +18 -20
package/dist/App.js
CHANGED
|
@@ -11,14 +11,23 @@ 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
|
+
const Subscription_1 = require("./Subscription");
|
|
16
17
|
const helpers_1 = require("./helpers");
|
|
17
18
|
const errors_1 = require("./errors");
|
|
19
|
+
const middleware_1 = require("./types/middleware");
|
|
18
20
|
// eslint-disable-next-line import/order
|
|
19
21
|
const allSettled = require("promise.allsettled"); // eslint-disable-line @typescript-eslint/no-require-imports
|
|
20
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-commonjs
|
|
21
23
|
const packageJson = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires
|
|
24
|
+
// ----------------------------
|
|
25
|
+
// For listener registration methods
|
|
26
|
+
const validViewTypes = ['view_closed', 'view_submission'];
|
|
27
|
+
// ----------------------------
|
|
28
|
+
// For the constructor
|
|
29
|
+
const tokenUsage = 'Apps used in a single workspace can be initialized with a token. Apps used in many workspaces ' +
|
|
30
|
+
'should be initialized with oauth installer options or authorize.';
|
|
22
31
|
var logger_2 = require("@slack/logger");
|
|
23
32
|
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_2.LogLevel; } });
|
|
24
33
|
class WebClientPool {
|
|
@@ -39,10 +48,11 @@ class WebClientPool {
|
|
|
39
48
|
* A Slack App
|
|
40
49
|
*/
|
|
41
50
|
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, } = {}) {
|
|
51
|
+
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, } = {}) {
|
|
52
|
+
// this.logLevel = logLevel;
|
|
43
53
|
// Some payloads don't have teamId anymore. So we use EnterpriseId in those scenarios
|
|
44
54
|
this.clients = {};
|
|
45
|
-
|
|
55
|
+
/* ------------------------ Developer mode ----------------------------- */
|
|
46
56
|
this.developerMode = developerMode;
|
|
47
57
|
if (developerMode) {
|
|
48
58
|
// Set logLevel to Debug in Developer Mode if one wasn't passed in
|
|
@@ -56,6 +66,7 @@ class App {
|
|
|
56
66
|
// Set logLevel to Info if one wasn't passed in
|
|
57
67
|
this.logLevel = logLevel !== null && logLevel !== void 0 ? logLevel : logger_1.LogLevel.INFO;
|
|
58
68
|
}
|
|
69
|
+
/* ------------------------ Set logger ----------------------------- */
|
|
59
70
|
if (typeof logger === 'undefined') {
|
|
60
71
|
// Initialize with the default logger
|
|
61
72
|
const consoleLogger = new logger_1.ConsoleLogger();
|
|
@@ -68,7 +79,11 @@ class App {
|
|
|
68
79
|
if (typeof this.logLevel !== 'undefined' && this.logger.getLevel() !== this.logLevel) {
|
|
69
80
|
this.logger.setLevel(this.logLevel);
|
|
70
81
|
}
|
|
82
|
+
// Error-related properties used to later determine args passed into the error handler
|
|
83
|
+
this.hasCustomErrorHandler = false;
|
|
71
84
|
this.errorHandler = defaultErrorHandler(this.logger);
|
|
85
|
+
this.extendedErrorHandler = extendedErrorHandler;
|
|
86
|
+
/* ------------------------ Set client options ------------------------*/
|
|
72
87
|
this.clientOptions = clientOptions !== undefined ? clientOptions : {};
|
|
73
88
|
if (agent !== undefined && this.clientOptions.agent === undefined) {
|
|
74
89
|
this.clientOptions.agent = agent;
|
|
@@ -81,11 +96,7 @@ class App {
|
|
|
81
96
|
this.clientOptions.logLevel = logLevel;
|
|
82
97
|
}
|
|
83
98
|
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
|
|
99
|
+
// Since v3.4, WebClient starts sharing logger with App
|
|
89
100
|
this.clientOptions.logger = this.logger;
|
|
90
101
|
}
|
|
91
102
|
// The public WebClient instance (app.client)
|
|
@@ -108,6 +119,11 @@ class App {
|
|
|
108
119
|
clientOptions: this.clientOptions,
|
|
109
120
|
...installerOptions,
|
|
110
121
|
};
|
|
122
|
+
if (socketMode && port !== undefined && this.installerOptions.port === undefined) {
|
|
123
|
+
// SocketModeReceiver only uses a custom port number when listening for the OAuth flow.
|
|
124
|
+
// Therefore only installerOptions.port is available in the constructor arguments.
|
|
125
|
+
this.installerOptions.port = port;
|
|
126
|
+
}
|
|
111
127
|
if (this.developerMode &&
|
|
112
128
|
this.installerOptions &&
|
|
113
129
|
(typeof this.installerOptions.callbackOptions === 'undefined' ||
|
|
@@ -123,43 +139,54 @@ class App {
|
|
|
123
139
|
},
|
|
124
140
|
};
|
|
125
141
|
}
|
|
126
|
-
|
|
142
|
+
/* --------------------- Initialize receiver ---------------------- */
|
|
127
143
|
if (receiver !== undefined) {
|
|
144
|
+
// Custom receiver supplied
|
|
145
|
+
if (this.socketMode === true) {
|
|
146
|
+
// socketMode = true should result in SocketModeReceiver being used as receiver
|
|
147
|
+
// TODO: Add case for when socketMode = true and receiver = SocketModeReceiver
|
|
148
|
+
// as this should not result in an error
|
|
149
|
+
throw new errors_1.AppInitializationError('You cannot supply a custom receiver when socketMode is set to true.');
|
|
150
|
+
}
|
|
128
151
|
this.receiver = receiver;
|
|
129
152
|
}
|
|
130
|
-
else if (this.socketMode) {
|
|
153
|
+
else if (this.socketMode === true) {
|
|
131
154
|
if (appToken === undefined) {
|
|
132
|
-
throw new errors_1.AppInitializationError('You must provide an appToken when
|
|
155
|
+
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
156
|
}
|
|
134
157
|
this.logger.debug('Initializing SocketModeReceiver');
|
|
135
|
-
// Create default SocketModeReceiver
|
|
136
158
|
this.receiver = new SocketModeReceiver_1.default({
|
|
137
159
|
appToken,
|
|
138
160
|
clientId,
|
|
139
161
|
clientSecret,
|
|
140
162
|
stateSecret,
|
|
163
|
+
redirectUri,
|
|
141
164
|
installationStore,
|
|
142
165
|
scopes,
|
|
143
166
|
logger,
|
|
144
167
|
logLevel: this.logLevel,
|
|
145
168
|
installerOptions: this.installerOptions,
|
|
169
|
+
customRoutes,
|
|
146
170
|
});
|
|
147
171
|
}
|
|
148
|
-
else if (signingSecret === undefined) {
|
|
149
|
-
//
|
|
150
|
-
throw new errors_1.AppInitializationError('
|
|
151
|
-
'custom receiver.');
|
|
172
|
+
else if (signatureVerification === true && signingSecret === undefined) {
|
|
173
|
+
// Using default receiver HTTPReceiver, signature verification enabled, missing signingSecret
|
|
174
|
+
throw new errors_1.AppInitializationError('signingSecret is required to initialize the default receiver. Set signingSecret or use a ' +
|
|
175
|
+
'custom receiver. You can find your Signing Secret in your Slack App Settings.');
|
|
152
176
|
}
|
|
153
177
|
else {
|
|
154
178
|
this.logger.debug('Initializing HTTPReceiver');
|
|
155
|
-
// Create default HTTPReceiver
|
|
156
179
|
this.receiver = new HTTPReceiver_1.default({
|
|
157
|
-
signingSecret,
|
|
180
|
+
signingSecret: signingSecret || '',
|
|
158
181
|
endpoints,
|
|
182
|
+
port,
|
|
183
|
+
customRoutes,
|
|
159
184
|
processBeforeResponse,
|
|
185
|
+
signatureVerification,
|
|
160
186
|
clientId,
|
|
161
187
|
clientSecret,
|
|
162
188
|
stateSecret,
|
|
189
|
+
redirectUri,
|
|
163
190
|
installationStore,
|
|
164
191
|
scopes,
|
|
165
192
|
logger,
|
|
@@ -167,16 +194,19 @@ class App {
|
|
|
167
194
|
installerOptions: this.installerOptions,
|
|
168
195
|
});
|
|
169
196
|
}
|
|
197
|
+
/* ------------------------ Set authorize ----------------------------- */
|
|
170
198
|
let usingOauth = false;
|
|
171
|
-
|
|
172
|
-
|
|
199
|
+
const httpReceiver = this.receiver;
|
|
200
|
+
if (httpReceiver.installer !== undefined &&
|
|
201
|
+
httpReceiver.installer.authorize !== undefined) {
|
|
173
202
|
// This supports using the built in HTTPReceiver, declaring your own HTTPReceiver
|
|
174
203
|
// and theoretically, doing a fully custom (non express) receiver that implements OAuth
|
|
175
204
|
usingOauth = true;
|
|
176
205
|
}
|
|
177
206
|
if (token !== undefined) {
|
|
178
|
-
|
|
179
|
-
|
|
207
|
+
// If a token is supplied, the app is installed in at least one workspace
|
|
208
|
+
if (usingOauth || authorize !== undefined) {
|
|
209
|
+
throw new errors_1.AppInitializationError(`You cannot provide a token along with either oauth installer options or authorize. ${tokenUsage}`);
|
|
180
210
|
}
|
|
181
211
|
this.authorize = singleAuthorization(this.client, {
|
|
182
212
|
botId,
|
|
@@ -185,31 +215,33 @@ class App {
|
|
|
185
215
|
}, tokenVerificationEnabled);
|
|
186
216
|
}
|
|
187
217
|
else if (authorize === undefined && !usingOauth) {
|
|
188
|
-
throw new errors_1.AppInitializationError(
|
|
218
|
+
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
219
|
}
|
|
190
220
|
else if (authorize !== undefined && usingOauth) {
|
|
191
|
-
throw new errors_1.AppInitializationError(`
|
|
221
|
+
throw new errors_1.AppInitializationError(`You cannot provide both authorize and oauth installer options. ${tokenUsage}`);
|
|
192
222
|
}
|
|
193
223
|
else if (authorize === undefined && usingOauth) {
|
|
194
|
-
|
|
224
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
225
|
+
this.authorize = httpReceiver.installer.authorize;
|
|
195
226
|
}
|
|
196
227
|
else if (authorize !== undefined && !usingOauth) {
|
|
197
228
|
this.authorize = authorize;
|
|
198
229
|
}
|
|
199
230
|
else {
|
|
200
|
-
this.logger.error('
|
|
201
|
-
helpers_1.assertNever();
|
|
231
|
+
this.logger.error('Something has gone wrong. Please report this issue to the maintainers. https://github.com/slackapi/bolt-js/issues');
|
|
232
|
+
(0, helpers_1.assertNever)();
|
|
202
233
|
}
|
|
203
234
|
// Conditionally use a global middleware that ignores events (including messages) that are sent from this app
|
|
204
235
|
if (ignoreSelf) {
|
|
205
|
-
this.use(builtin_1.ignoreSelf());
|
|
236
|
+
this.use((0, builtin_1.ignoreSelf)());
|
|
206
237
|
}
|
|
207
238
|
// Use conversation state global middleware
|
|
208
239
|
if (convoStore !== false) {
|
|
209
240
|
// Use the memory store by default, or another store if provided
|
|
210
241
|
const store = convoStore === undefined ? new conversation_store_1.MemoryStore() : convoStore;
|
|
211
|
-
this.use(conversation_store_1.conversationContext(store));
|
|
242
|
+
this.use((0, conversation_store_1.conversationContext)(store));
|
|
212
243
|
}
|
|
244
|
+
/* ------------------------ Initialize receiver ------------------------ */
|
|
213
245
|
// Should be last to avoid exposing partially initialized app
|
|
214
246
|
this.receiver.init(this);
|
|
215
247
|
}
|
|
@@ -243,9 +275,26 @@ class App {
|
|
|
243
275
|
// TODO: HTTPReceiver['start'] should be the actual receiver's return type
|
|
244
276
|
return this.receiver.start(...args);
|
|
245
277
|
}
|
|
278
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
246
279
|
stop(...args) {
|
|
247
280
|
return this.receiver.stop(...args);
|
|
248
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Register subcription middleware
|
|
284
|
+
*
|
|
285
|
+
* @param listeners middleware that process and react to subscription payloads
|
|
286
|
+
*/
|
|
287
|
+
subscription(options) {
|
|
288
|
+
/*
|
|
289
|
+
* TODO If it becomes possible for users to set a custom unique resource id,
|
|
290
|
+
* custom id should be supplied in place of the default.
|
|
291
|
+
* */
|
|
292
|
+
const defaultId = 'DEFAULTID';
|
|
293
|
+
const s = new Subscription_1.Subscription(defaultId, options);
|
|
294
|
+
const m = s.getMiddleware();
|
|
295
|
+
this.middleware.push(m);
|
|
296
|
+
return this;
|
|
297
|
+
}
|
|
249
298
|
event(eventNameOrPattern, ...listeners) {
|
|
250
299
|
let invalidEventName = false;
|
|
251
300
|
if (typeof eventNameOrPattern === 'string') {
|
|
@@ -263,27 +312,27 @@ class App {
|
|
|
263
312
|
}
|
|
264
313
|
this.listeners.push([
|
|
265
314
|
builtin_1.onlyEvents,
|
|
266
|
-
builtin_1.matchEventType(eventNameOrPattern),
|
|
315
|
+
(0, builtin_1.matchEventType)(eventNameOrPattern),
|
|
267
316
|
...listeners,
|
|
268
317
|
]);
|
|
269
318
|
}
|
|
270
319
|
message(...patternsOrMiddleware) {
|
|
271
320
|
const messageMiddleware = patternsOrMiddleware.map((patternOrMiddleware) => {
|
|
272
321
|
if (typeof patternOrMiddleware === 'string' || util_1.default.types.isRegExp(patternOrMiddleware)) {
|
|
273
|
-
return builtin_1.matchMessage(patternOrMiddleware);
|
|
322
|
+
return (0, builtin_1.matchMessage)(patternOrMiddleware);
|
|
274
323
|
}
|
|
275
324
|
return patternOrMiddleware;
|
|
276
325
|
});
|
|
277
326
|
this.listeners.push([
|
|
278
327
|
builtin_1.onlyEvents,
|
|
279
|
-
builtin_1.matchEventType('message'),
|
|
328
|
+
(0, builtin_1.matchEventType)('message'),
|
|
280
329
|
...messageMiddleware,
|
|
281
330
|
]);
|
|
282
331
|
}
|
|
283
332
|
shortcut(callbackIdOrConstraints, ...listeners) {
|
|
284
|
-
const constraints = typeof callbackIdOrConstraints === 'string' || util_1.default.types.isRegExp(callbackIdOrConstraints)
|
|
285
|
-
|
|
286
|
-
|
|
333
|
+
const constraints = typeof callbackIdOrConstraints === 'string' || util_1.default.types.isRegExp(callbackIdOrConstraints) ?
|
|
334
|
+
{ callback_id: callbackIdOrConstraints } :
|
|
335
|
+
callbackIdOrConstraints;
|
|
287
336
|
// Fail early if the constraints contain invalid keys
|
|
288
337
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'callback_id' && k !== 'type');
|
|
289
338
|
if (unknownConstraintKeys.length > 0) {
|
|
@@ -292,37 +341,37 @@ class App {
|
|
|
292
341
|
}
|
|
293
342
|
this.listeners.push([
|
|
294
343
|
builtin_1.onlyShortcuts,
|
|
295
|
-
builtin_1.matchConstraints(constraints),
|
|
344
|
+
(0, builtin_1.matchConstraints)(constraints),
|
|
296
345
|
...listeners,
|
|
297
346
|
]);
|
|
298
347
|
}
|
|
299
348
|
action(actionIdOrConstraints, ...listeners) {
|
|
300
349
|
// Normalize Constraints
|
|
301
|
-
const constraints = typeof actionIdOrConstraints === 'string' || util_1.default.types.isRegExp(actionIdOrConstraints)
|
|
302
|
-
|
|
303
|
-
|
|
350
|
+
const constraints = typeof actionIdOrConstraints === 'string' || util_1.default.types.isRegExp(actionIdOrConstraints) ?
|
|
351
|
+
{ action_id: actionIdOrConstraints } :
|
|
352
|
+
actionIdOrConstraints;
|
|
304
353
|
// Fail early if the constraints contain invalid keys
|
|
305
354
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'action_id' && k !== 'block_id' && k !== 'callback_id' && k !== 'type');
|
|
306
355
|
if (unknownConstraintKeys.length > 0) {
|
|
307
356
|
this.logger.error(`Action listener cannot be attached using unknown constraint keys: ${unknownConstraintKeys.join(', ')}`);
|
|
308
357
|
return;
|
|
309
358
|
}
|
|
310
|
-
this.listeners.push([builtin_1.onlyActions, builtin_1.matchConstraints(constraints), ...listeners]);
|
|
359
|
+
this.listeners.push([builtin_1.onlyActions, (0, builtin_1.matchConstraints)(constraints), ...listeners]);
|
|
311
360
|
}
|
|
312
361
|
command(commandName, ...listeners) {
|
|
313
|
-
this.listeners.push([builtin_1.onlyCommands, builtin_1.matchCommandName(commandName), ...listeners]);
|
|
362
|
+
this.listeners.push([builtin_1.onlyCommands, (0, builtin_1.matchCommandName)(commandName), ...listeners]);
|
|
314
363
|
}
|
|
315
364
|
// TODO: reflect the type in constraits to Source
|
|
316
365
|
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]);
|
|
366
|
+
const constraints = typeof actionIdOrConstraints === 'string' || util_1.default.types.isRegExp(actionIdOrConstraints) ?
|
|
367
|
+
{ action_id: actionIdOrConstraints } :
|
|
368
|
+
actionIdOrConstraints;
|
|
369
|
+
this.listeners.push([builtin_1.onlyOptions, (0, builtin_1.matchConstraints)(constraints), ...listeners]);
|
|
321
370
|
}
|
|
322
371
|
view(callbackIdOrConstraints, ...listeners) {
|
|
323
|
-
const constraints = typeof callbackIdOrConstraints === 'string' || util_1.default.types.isRegExp(callbackIdOrConstraints)
|
|
324
|
-
|
|
325
|
-
|
|
372
|
+
const constraints = typeof callbackIdOrConstraints === 'string' || util_1.default.types.isRegExp(callbackIdOrConstraints) ?
|
|
373
|
+
{ callback_id: callbackIdOrConstraints, type: 'view_submission' } :
|
|
374
|
+
callbackIdOrConstraints;
|
|
326
375
|
// Fail early if the constraints contain invalid keys
|
|
327
376
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'callback_id' && k !== 'type');
|
|
328
377
|
if (unknownConstraintKeys.length > 0) {
|
|
@@ -335,12 +384,13 @@ class App {
|
|
|
335
384
|
}
|
|
336
385
|
this.listeners.push([
|
|
337
386
|
builtin_1.onlyViewActions,
|
|
338
|
-
builtin_1.matchConstraints(constraints),
|
|
387
|
+
(0, builtin_1.matchConstraints)(constraints),
|
|
339
388
|
...listeners,
|
|
340
389
|
]);
|
|
341
390
|
}
|
|
342
391
|
error(errorHandler) {
|
|
343
392
|
this.errorHandler = errorHandler;
|
|
393
|
+
this.hasCustomErrorHandler = true;
|
|
344
394
|
}
|
|
345
395
|
/**
|
|
346
396
|
* Handles events from the receiver
|
|
@@ -356,7 +406,7 @@ class App {
|
|
|
356
406
|
// or even all of the args, as properties of the error. This would give error handling code some ability to deal
|
|
357
407
|
// with "finally" type error situations.
|
|
358
408
|
// 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);
|
|
409
|
+
const { type, conversationId } = (0, helpers_1.getTypeAndConversation)(body);
|
|
360
410
|
// If the type could not be determined, warn and exit
|
|
361
411
|
if (type === undefined) {
|
|
362
412
|
this.logger.warn('Could not determine the type of an incoming event. No listeners will be called.');
|
|
@@ -377,9 +427,18 @@ class App {
|
|
|
377
427
|
}
|
|
378
428
|
}
|
|
379
429
|
catch (error) {
|
|
430
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
431
|
+
const e = error;
|
|
380
432
|
this.logger.warn('Authorization of incoming event did not succeed. No listeners will be called.');
|
|
381
|
-
|
|
382
|
-
|
|
433
|
+
e.code = errors_1.ErrorCode.AuthorizationError;
|
|
434
|
+
// disabling due to https://github.com/typescript-eslint/typescript-eslint/issues/1277
|
|
435
|
+
// eslint-disable-next-line consistent-return
|
|
436
|
+
return this.handleError({
|
|
437
|
+
error: e,
|
|
438
|
+
logger: this.logger,
|
|
439
|
+
body: bodyArg,
|
|
440
|
+
context: {},
|
|
441
|
+
});
|
|
383
442
|
}
|
|
384
443
|
// Try to set teamId from AuthorizeResult before using one from source
|
|
385
444
|
if (authorizeResult.teamId === undefined && source.teamId !== undefined) {
|
|
@@ -389,32 +448,60 @@ class App {
|
|
|
389
448
|
if (authorizeResult.enterpriseId === undefined && source.enterpriseId !== undefined) {
|
|
390
449
|
authorizeResult.enterpriseId = source.enterpriseId;
|
|
391
450
|
}
|
|
392
|
-
|
|
451
|
+
if (typeof event.customProperties !== 'undefined') {
|
|
452
|
+
const customProps = event.customProperties;
|
|
453
|
+
const builtinKeyDetected = middleware_1.contextBuiltinKeys.find((key) => key in customProps);
|
|
454
|
+
if (typeof builtinKeyDetected !== 'undefined') {
|
|
455
|
+
throw new errors_1.InvalidCustomPropertyError('customProperties cannot have the same names with the built-in ones');
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
const context = {
|
|
459
|
+
...authorizeResult,
|
|
460
|
+
...event.customProperties,
|
|
461
|
+
retryNum: event.retryNum,
|
|
462
|
+
retryReason: event.retryReason,
|
|
463
|
+
};
|
|
393
464
|
// Factory for say() utility
|
|
394
465
|
const createSay = (channelId) => {
|
|
395
466
|
const token = selectToken(context);
|
|
396
467
|
return (message) => {
|
|
397
|
-
const postMessageArguments = typeof message === 'string'
|
|
398
|
-
|
|
399
|
-
|
|
468
|
+
const postMessageArguments = typeof message === 'string' ?
|
|
469
|
+
{ token, text: message, channel: channelId } :
|
|
470
|
+
{ ...message, token, channel: channelId };
|
|
400
471
|
return this.client.chat.postMessage(postMessageArguments);
|
|
401
472
|
};
|
|
402
473
|
};
|
|
403
|
-
// Set body and payload
|
|
474
|
+
// Set body and payload
|
|
475
|
+
// TODO: this value should eventually conform to AnyMiddlewareArgs
|
|
476
|
+
let payload;
|
|
477
|
+
switch (type) {
|
|
478
|
+
case helpers_1.IncomingEventType.Event:
|
|
479
|
+
payload = bodyArg.event;
|
|
480
|
+
break;
|
|
481
|
+
case helpers_1.IncomingEventType.ViewAction:
|
|
482
|
+
payload = bodyArg.view;
|
|
483
|
+
break;
|
|
484
|
+
case helpers_1.IncomingEventType.Shortcut:
|
|
485
|
+
payload = bodyArg;
|
|
486
|
+
break;
|
|
487
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
488
|
+
// @ts-ignore: Fallthrough case in switch
|
|
489
|
+
case helpers_1.IncomingEventType.Action:
|
|
490
|
+
if (isBlockActionOrInteractiveMessageBody(bodyArg)) {
|
|
491
|
+
const { actions } = bodyArg;
|
|
492
|
+
[payload] = actions;
|
|
493
|
+
break;
|
|
494
|
+
}
|
|
495
|
+
// If above conditional does not hit, fall through to fallback payload in default block below
|
|
496
|
+
default:
|
|
497
|
+
payload = bodyArg;
|
|
498
|
+
break;
|
|
499
|
+
}
|
|
404
500
|
// NOTE: the following doesn't work because... distributive?
|
|
405
501
|
// const listenerArgs: Partial<AnyMiddlewareArgs> = {
|
|
406
502
|
const listenerArgs = {
|
|
407
503
|
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,
|
|
504
|
+
payload,
|
|
418
505
|
};
|
|
419
506
|
// Set aliases
|
|
420
507
|
if (type === helpers_1.IncomingEventType.Event) {
|
|
@@ -493,7 +580,7 @@ class App {
|
|
|
493
580
|
}
|
|
494
581
|
// Dispatch event through the global middleware chain
|
|
495
582
|
try {
|
|
496
|
-
await process_1.
|
|
583
|
+
await (0, process_1.default)(this.middleware, listenerArgs, context, client, this.logger, async () => {
|
|
497
584
|
// Dispatch the event through the listener middleware chains and aggregate their results
|
|
498
585
|
// TODO: change the name of this.middleware and this.listeners to help this make more sense
|
|
499
586
|
const listenerResults = this.listeners.map(async (origListenerMiddleware) => {
|
|
@@ -501,11 +588,19 @@ class App {
|
|
|
501
588
|
const listenerMiddleware = [...origListenerMiddleware];
|
|
502
589
|
// Don't process the last item in the listenerMiddleware array - it shouldn't get a next fn
|
|
503
590
|
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 }));
|
|
591
|
+
if (listener === undefined) {
|
|
592
|
+
return undefined;
|
|
508
593
|
}
|
|
594
|
+
return (0, process_1.default)(listenerMiddleware, listenerArgs, context, client, this.logger,
|
|
595
|
+
// When all of the listener middleware are done processing,
|
|
596
|
+
// `listener` here will be called without a `next` execution
|
|
597
|
+
async () => listener({
|
|
598
|
+
...listenerArgs,
|
|
599
|
+
context,
|
|
600
|
+
client,
|
|
601
|
+
logger: this.logger,
|
|
602
|
+
// `next` is already set in the outer processMiddleware
|
|
603
|
+
}));
|
|
509
604
|
});
|
|
510
605
|
const settledListenerResults = await allSettled(listenerResults);
|
|
511
606
|
const rejectedListenerResults = settledListenerResults.filter((lr) => lr.status === 'rejected');
|
|
@@ -518,21 +613,29 @@ class App {
|
|
|
518
613
|
});
|
|
519
614
|
}
|
|
520
615
|
catch (error) {
|
|
521
|
-
|
|
616
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
617
|
+
const e = error;
|
|
618
|
+
// disabling due to https://github.com/typescript-eslint/typescript-eslint/issues/1277
|
|
619
|
+
// eslint-disable-next-line consistent-return
|
|
620
|
+
return this.handleError({
|
|
621
|
+
context,
|
|
622
|
+
error: e,
|
|
623
|
+
logger: this.logger,
|
|
624
|
+
body: bodyArg,
|
|
625
|
+
});
|
|
522
626
|
}
|
|
523
627
|
}
|
|
524
628
|
/**
|
|
525
629
|
* Global error handler. The final destination for all errors (hopefully).
|
|
526
630
|
*/
|
|
527
|
-
handleError(
|
|
528
|
-
|
|
631
|
+
handleError(args) {
|
|
632
|
+
const { error, ...rest } = args;
|
|
633
|
+
return this.extendedErrorHandler && this.hasCustomErrorHandler ?
|
|
634
|
+
this.errorHandler({ error: (0, errors_1.asCodedError)(error), ...rest }) :
|
|
635
|
+
this.errorHandler((0, errors_1.asCodedError)(error));
|
|
529
636
|
}
|
|
530
637
|
}
|
|
531
638
|
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
639
|
function defaultErrorHandler(logger) {
|
|
537
640
|
return (error) => {
|
|
538
641
|
logger.error(error);
|
|
@@ -543,14 +646,12 @@ function defaultErrorHandler(logger) {
|
|
|
543
646
|
// singleAuthorization
|
|
544
647
|
function runAuthTestForBotToken(client, authorization) {
|
|
545
648
|
// TODO: warn when something needed isn't found
|
|
546
|
-
return authorization.botUserId !== undefined && authorization.botId !== undefined
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
};
|
|
553
|
-
});
|
|
649
|
+
return authorization.botUserId !== undefined && authorization.botId !== undefined ?
|
|
650
|
+
Promise.resolve({ botUserId: authorization.botUserId, botId: authorization.botId }) :
|
|
651
|
+
client.auth.test({ token: authorization.botToken }).then((result) => ({
|
|
652
|
+
botUserId: result.user_id,
|
|
653
|
+
botId: result.bot_id,
|
|
654
|
+
}));
|
|
554
655
|
}
|
|
555
656
|
async function buildAuthorizeResult(isEnterpriseInstall, authTestResult, authorization) {
|
|
556
657
|
return { isEnterpriseInstall, botToken: authorization.botToken, ...(await authTestResult) };
|
|
@@ -562,9 +663,7 @@ function singleAuthorization(client, authorization, tokenVerificationEnabled) {
|
|
|
562
663
|
if (tokenVerificationEnabled) {
|
|
563
664
|
// call auth.test immediately
|
|
564
665
|
cachedAuthTestResult = runAuthTestForBotToken(client, authorization);
|
|
565
|
-
return async ({ isEnterpriseInstall }) =>
|
|
566
|
-
return buildAuthorizeResult(isEnterpriseInstall, cachedAuthTestResult, authorization);
|
|
567
|
-
};
|
|
666
|
+
return async ({ isEnterpriseInstall }) => buildAuthorizeResult(isEnterpriseInstall, cachedAuthTestResult, authorization);
|
|
568
667
|
}
|
|
569
668
|
return async ({ isEnterpriseInstall }) => {
|
|
570
669
|
// hold off calling auth.test API until the first access to authorize function
|
|
@@ -593,6 +692,10 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
593
692
|
if (type === helpers_1.IncomingEventType.Command) {
|
|
594
693
|
return body.team_id;
|
|
595
694
|
}
|
|
695
|
+
if (type === helpers_1.IncomingEventType.Subscription) {
|
|
696
|
+
const bodyAsSubscriptionInteraction = body;
|
|
697
|
+
return bodyAsSubscriptionInteraction.team.id;
|
|
698
|
+
}
|
|
596
699
|
if (type === helpers_1.IncomingEventType.Action ||
|
|
597
700
|
type === helpers_1.IncomingEventType.Options ||
|
|
598
701
|
type === helpers_1.IncomingEventType.ViewAction ||
|
|
@@ -606,7 +709,7 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
606
709
|
// This is the only place where this function might return undefined
|
|
607
710
|
return bodyAsActionOrOptionsOrViewActionOrShortcut.user.team_id;
|
|
608
711
|
}
|
|
609
|
-
return helpers_1.assertNever(type);
|
|
712
|
+
return (0, helpers_1.assertNever)(type);
|
|
610
713
|
})();
|
|
611
714
|
const enterpriseId = (() => {
|
|
612
715
|
if (type === helpers_1.IncomingEventType.Event) {
|
|
@@ -621,6 +724,10 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
621
724
|
if (type === helpers_1.IncomingEventType.Command) {
|
|
622
725
|
return body.enterprise_id;
|
|
623
726
|
}
|
|
727
|
+
if (type === helpers_1.IncomingEventType.Subscription) {
|
|
728
|
+
const bodyAsSubscriptionInteraction = body;
|
|
729
|
+
return bodyAsSubscriptionInteraction.team.enterprise_id;
|
|
730
|
+
}
|
|
624
731
|
if (type === helpers_1.IncomingEventType.Action ||
|
|
625
732
|
type === helpers_1.IncomingEventType.Options ||
|
|
626
733
|
type === helpers_1.IncomingEventType.ViewAction ||
|
|
@@ -638,7 +745,7 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
638
745
|
}
|
|
639
746
|
return undefined;
|
|
640
747
|
}
|
|
641
|
-
return helpers_1.assertNever(type);
|
|
748
|
+
return (0, helpers_1.assertNever)(type);
|
|
642
749
|
})();
|
|
643
750
|
const userId = (() => {
|
|
644
751
|
if (type === helpers_1.IncomingEventType.Event) {
|
|
@@ -660,6 +767,10 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
660
767
|
}
|
|
661
768
|
return undefined;
|
|
662
769
|
}
|
|
770
|
+
if (type === helpers_1.IncomingEventType.Subscription) {
|
|
771
|
+
const bodyAsSubscriptionInteraction = body;
|
|
772
|
+
return bodyAsSubscriptionInteraction.user.id;
|
|
773
|
+
}
|
|
663
774
|
if (type === helpers_1.IncomingEventType.Action ||
|
|
664
775
|
type === helpers_1.IncomingEventType.Options ||
|
|
665
776
|
type === helpers_1.IncomingEventType.ViewAction ||
|
|
@@ -671,7 +782,7 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
671
782
|
if (type === helpers_1.IncomingEventType.Command) {
|
|
672
783
|
return body.user_id;
|
|
673
784
|
}
|
|
674
|
-
return helpers_1.assertNever(type);
|
|
785
|
+
return (0, helpers_1.assertNever)(type);
|
|
675
786
|
})();
|
|
676
787
|
return {
|
|
677
788
|
userId,
|
|
@@ -688,13 +799,18 @@ function isBodyWithTypeEnterpriseInstall(body, type) {
|
|
|
688
799
|
return !!bodyAsEvent.authorizations[0].is_enterprise_install;
|
|
689
800
|
}
|
|
690
801
|
}
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
return body.is_enterprise_install === 'true';
|
|
802
|
+
if (type === helpers_1.IncomingEventType.Subscription) {
|
|
803
|
+
return body.team.enterprise_id !== undefined;
|
|
694
804
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
805
|
+
if ('is_enterprise_install' in body) {
|
|
806
|
+
// command payloads have this property set as a string
|
|
807
|
+
if (typeof body.is_enterprise_install === 'string') {
|
|
808
|
+
return body.is_enterprise_install === 'true';
|
|
809
|
+
}
|
|
810
|
+
// all remaining types have a boolean property
|
|
811
|
+
if (body.is_enterprise_install !== undefined) {
|
|
812
|
+
return body.is_enterprise_install;
|
|
813
|
+
}
|
|
698
814
|
}
|
|
699
815
|
// as a fallback we assume it's a single team installation (but this should never happen)
|
|
700
816
|
return false;
|
|
@@ -706,17 +822,14 @@ function isBlockActionOrInteractiveMessageBody(body) {
|
|
|
706
822
|
function selectToken(context) {
|
|
707
823
|
return context.botToken !== undefined ? context.botToken : context.userToken;
|
|
708
824
|
}
|
|
709
|
-
function buildRespondFn(axiosInstance,
|
|
825
|
+
function buildRespondFn(axiosInstance, responseUrl) {
|
|
710
826
|
return async (message) => {
|
|
711
827
|
const normalizedArgs = typeof message === 'string' ? { text: message } : message;
|
|
712
|
-
return axiosInstance.post(
|
|
828
|
+
return axiosInstance.post(responseUrl, normalizedArgs);
|
|
713
829
|
};
|
|
714
830
|
}
|
|
715
831
|
// ----------------------------
|
|
716
|
-
// For listener registration methods
|
|
717
|
-
const validViewTypes = ['view_closed', 'view_submission'];
|
|
718
|
-
// ----------------------------
|
|
719
832
|
// Instrumentation
|
|
720
833
|
// Don't change the position of the following code
|
|
721
|
-
web_api_1.addAppMetadata({ name: packageJson.name, version: packageJson.version });
|
|
834
|
+
(0, web_api_1.addAppMetadata)({ name: packageJson.name, version: packageJson.version });
|
|
722
835
|
//# sourceMappingURL=App.js.map
|