@slack/bolt 4.0.0-nextGen.9 → 4.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -16
- package/dist/App.d.ts +39 -80
- package/dist/App.d.ts.map +1 -1
- package/dist/App.js +223 -234
- package/dist/App.js.map +1 -1
- package/dist/CustomFunction.d.ts +58 -0
- package/dist/CustomFunction.d.ts.map +1 -0
- package/dist/CustomFunction.js +144 -0
- package/dist/CustomFunction.js.map +1 -0
- package/dist/WorkflowStep.d.ts +89 -36
- package/dist/WorkflowStep.d.ts.map +1 -1
- package/dist/WorkflowStep.js +29 -8
- package/dist/WorkflowStep.js.map +1 -1
- package/dist/conversation-store.d.ts +1 -1
- package/dist/conversation-store.d.ts.map +1 -1
- package/dist/conversation-store.js +3 -3
- package/dist/conversation-store.js.map +1 -1
- package/dist/errors.d.ts +12 -7
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +42 -53
- package/dist/errors.js.map +1 -1
- package/dist/helpers.d.ts +16 -3
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +43 -11
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -11
- package/dist/index.js.map +1 -1
- package/dist/middleware/builtin.d.ts +20 -23
- package/dist/middleware/builtin.d.ts.map +1 -1
- package/dist/middleware/builtin.js +93 -110
- package/dist/middleware/builtin.js.map +1 -1
- package/dist/middleware/process.d.ts +3 -3
- package/dist/middleware/process.d.ts.map +1 -1
- package/dist/middleware/process.js +1 -1
- package/dist/middleware/process.js.map +1 -1
- package/dist/receivers/AwsLambdaReceiver.d.ts +77 -16
- package/dist/receivers/AwsLambdaReceiver.d.ts.map +1 -1
- package/dist/receivers/AwsLambdaReceiver.js +53 -25
- package/dist/receivers/AwsLambdaReceiver.js.map +1 -1
- package/dist/receivers/BufferedIncomingMessage.d.ts +2 -1
- package/dist/receivers/BufferedIncomingMessage.d.ts.map +1 -1
- package/dist/receivers/ExpressReceiver.d.ts +13 -13
- package/dist/receivers/ExpressReceiver.d.ts.map +1 -1
- package/dist/receivers/ExpressReceiver.js +70 -70
- package/dist/receivers/ExpressReceiver.js.map +1 -1
- package/dist/receivers/HTTPModuleFunctions.d.ts +18 -20
- package/dist/receivers/HTTPModuleFunctions.d.ts.map +1 -1
- package/dist/receivers/HTTPModuleFunctions.js +189 -171
- package/dist/receivers/HTTPModuleFunctions.js.map +1 -1
- package/dist/receivers/HTTPReceiver.d.ts +14 -14
- package/dist/receivers/HTTPReceiver.d.ts.map +1 -1
- package/dist/receivers/HTTPReceiver.js +102 -48
- package/dist/receivers/HTTPReceiver.js.map +1 -1
- package/dist/receivers/HTTPResponseAck.d.ts +7 -7
- package/dist/receivers/HTTPResponseAck.d.ts.map +1 -1
- package/dist/receivers/HTTPResponseAck.js +37 -5
- package/dist/receivers/HTTPResponseAck.js.map +1 -1
- package/dist/receivers/ParamsIncomingMessage.d.ts +14 -0
- package/dist/receivers/ParamsIncomingMessage.d.ts.map +1 -0
- package/dist/{types/block-suggestion/index.js → receivers/ParamsIncomingMessage.js} +1 -1
- package/dist/receivers/ParamsIncomingMessage.js.map +1 -0
- package/dist/receivers/SocketModeFunctions.d.ts +3 -5
- package/dist/receivers/SocketModeFunctions.d.ts.map +1 -1
- package/dist/receivers/SocketModeFunctions.js +14 -23
- package/dist/receivers/SocketModeFunctions.js.map +1 -1
- package/dist/receivers/SocketModeReceiver.d.ts +10 -9
- package/dist/receivers/SocketModeReceiver.d.ts.map +1 -1
- package/dist/receivers/SocketModeReceiver.js +41 -25
- package/dist/receivers/SocketModeReceiver.js.map +1 -1
- package/dist/receivers/custom-routes.d.ts +4 -3
- package/dist/receivers/custom-routes.d.ts.map +1 -1
- package/dist/receivers/custom-routes.js +10 -9
- package/dist/receivers/custom-routes.js.map +1 -1
- package/dist/receivers/verify-redirect-opts.d.ts +1 -1
- package/dist/receivers/verify-redirect-opts.d.ts.map +1 -1
- package/dist/receivers/verify-redirect-opts.js +3 -3
- package/dist/receivers/verify-redirect-opts.js.map +1 -1
- package/dist/receivers/verify-request.d.ts +1 -12
- package/dist/receivers/verify-request.d.ts.map +1 -1
- package/dist/receivers/verify-request.js +4 -18
- package/dist/receivers/verify-request.js.map +1 -1
- package/dist/types/actions/block-action.d.ts +41 -22
- package/dist/types/actions/block-action.d.ts.map +1 -1
- package/dist/types/actions/dialog-action.d.ts +0 -4
- package/dist/types/actions/dialog-action.d.ts.map +1 -1
- package/dist/types/actions/index.d.ts +25 -11
- package/dist/types/actions/index.d.ts.map +1 -1
- package/dist/types/actions/index.js +1 -0
- package/dist/types/actions/index.js.map +1 -1
- package/dist/types/actions/interactive-message.d.ts +3 -3
- package/dist/types/actions/interactive-message.d.ts.map +1 -1
- package/dist/types/actions/workflow-step-edit.d.ts +7 -7
- package/dist/types/actions/workflow-step-edit.d.ts.map +1 -1
- package/dist/types/command/index.d.ts +1 -2
- package/dist/types/command/index.d.ts.map +1 -1
- package/dist/types/events/index.d.ts +26 -24
- package/dist/types/events/index.d.ts.map +1 -1
- package/dist/types/events/index.js +4 -15
- package/dist/types/events/index.js.map +1 -1
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +0 -2
- package/dist/types/index.js.map +1 -1
- package/dist/types/middleware.d.ts +30 -30
- package/dist/types/middleware.d.ts.map +1 -1
- package/dist/types/middleware.js +3 -0
- package/dist/types/middleware.js.map +1 -1
- package/dist/types/options/index.d.ts +23 -59
- package/dist/types/options/index.d.ts.map +1 -1
- package/dist/types/receiver.d.ts +3 -3
- package/dist/types/receiver.d.ts.map +1 -1
- package/dist/types/shortcuts/global-shortcut.d.ts.map +1 -1
- package/dist/types/shortcuts/index.d.ts +14 -9
- package/dist/types/shortcuts/index.d.ts.map +1 -1
- package/dist/types/shortcuts/message-shortcut.d.ts.map +1 -1
- package/dist/types/utilities.d.ts +23 -13
- package/dist/types/utilities.d.ts.map +1 -1
- package/dist/types/utilities.js +7 -0
- package/dist/types/utilities.js.map +1 -1
- package/dist/types/view/index.d.ts +148 -12
- package/dist/types/view/index.d.ts.map +1 -1
- package/package.json +32 -61
- package/dist/Manifest.d.ts +0 -5
- package/dist/Manifest.d.ts.map +0 -1
- package/dist/Manifest.js +0 -16
- package/dist/Manifest.js.map +0 -1
- package/dist/SlackFunction.d.ts +0 -190
- package/dist/SlackFunction.d.ts.map +0 -1
- package/dist/SlackFunction.js +0 -441
- package/dist/SlackFunction.js.map +0 -1
- package/dist/Subscription.d.ts +0 -61
- package/dist/Subscription.d.ts.map +0 -1
- package/dist/Subscription.js +0 -169
- package/dist/Subscription.js.map +0 -1
- package/dist/cli/check-update.d.ts +0 -3
- package/dist/cli/check-update.d.ts.map +0 -1
- package/dist/cli/check-update.js +0 -13
- package/dist/cli/check-update.js.map +0 -1
- package/dist/cli/get-hooks.d.ts +0 -2
- package/dist/cli/get-hooks.d.ts.map +0 -1
- package/dist/cli/get-hooks.js +0 -19
- package/dist/cli/get-hooks.js.map +0 -1
- package/dist/cli/get-manifest.d.ts +0 -3
- package/dist/cli/get-manifest.d.ts.map +0 -1
- package/dist/cli/get-manifest.js +0 -16
- package/dist/cli/get-manifest.js.map +0 -1
- package/dist/cli/hook-utils/get-check-update-data.d.ts +0 -49
- package/dist/cli/hook-utils/get-check-update-data.d.ts.map +0 -1
- package/dist/cli/hook-utils/get-check-update-data.js +0 -252
- package/dist/cli/hook-utils/get-check-update-data.js.map +0 -1
- package/dist/cli/hook-utils/get-check-update-data.spec.d.ts +0 -2
- package/dist/cli/hook-utils/get-check-update-data.spec.d.ts.map +0 -1
- package/dist/cli/hook-utils/get-check-update-data.spec.js +0 -266
- package/dist/cli/hook-utils/get-check-update-data.spec.js.map +0 -1
- package/dist/cli/hook-utils/get-manifest-data.d.ts +0 -7
- package/dist/cli/hook-utils/get-manifest-data.d.ts.map +0 -1
- package/dist/cli/hook-utils/get-manifest-data.js +0 -30
- package/dist/cli/hook-utils/get-manifest-data.js.map +0 -1
- package/dist/cli/hook-utils/get-manifest-data.spec.d.ts +0 -2
- package/dist/cli/hook-utils/get-manifest-data.spec.d.ts.map +0 -1
- package/dist/cli/hook-utils/get-manifest-data.spec.js +0 -113
- package/dist/cli/hook-utils/get-manifest-data.spec.js.map +0 -1
- package/dist/cli/hook-utils/manifest.d.ts +0 -30
- package/dist/cli/hook-utils/manifest.d.ts.map +0 -1
- package/dist/cli/hook-utils/manifest.js +0 -103
- package/dist/cli/hook-utils/manifest.js.map +0 -1
- package/dist/cli/hook-utils/manifest.spec.d.ts +0 -2
- package/dist/cli/hook-utils/manifest.spec.d.ts.map +0 -1
- package/dist/cli/hook-utils/manifest.spec.js +0 -79
- package/dist/cli/hook-utils/manifest.spec.js.map +0 -1
- package/dist/cli/run.d.ts +0 -2
- package/dist/cli/run.d.ts.map +0 -1
- package/dist/cli/run.js +0 -37
- package/dist/cli/run.js.map +0 -1
- package/dist/cli/start.d.ts +0 -3
- package/dist/cli/start.d.ts.map +0 -1
- package/dist/cli/start.js +0 -40
- package/dist/cli/start.js.map +0 -1
- package/dist/receivers/http-utils.d.ts +0 -5
- package/dist/receivers/http-utils.d.ts.map +0 -1
- package/dist/receivers/http-utils.js +0 -19
- package/dist/receivers/http-utils.js.map +0 -1
- package/dist/receivers/render-html-for-install-path.d.ts +0 -3
- package/dist/receivers/render-html-for-install-path.d.ts.map +0 -1
- package/dist/receivers/render-html-for-install-path.js +0 -32
- package/dist/receivers/render-html-for-install-path.js.map +0 -1
- package/dist/types/block-suggestion/index.d.ts +0 -97
- package/dist/types/block-suggestion/index.d.ts.map +0 -1
- package/dist/types/block-suggestion/index.js.map +0 -1
- package/dist/types/events/base-events.d.ts +0 -1135
- package/dist/types/events/base-events.d.ts.map +0 -1
- package/dist/types/events/base-events.js +0 -5
- package/dist/types/events/base-events.js.map +0 -1
- package/dist/types/events/message-events.d.ts +0 -348
- package/dist/types/events/message-events.d.ts.map +0 -1
- package/dist/types/events/message-events.js +0 -3
- package/dist/types/events/message-events.js.map +0 -1
- package/dist/types/functions/index.d.ts +0 -26
- package/dist/types/functions/index.d.ts.map +0 -1
- package/dist/types/functions/index.js +0 -3
- package/dist/types/functions/index.js.map +0 -1
- package/dist/types/helpers.d.ts +0 -17
- package/dist/types/helpers.d.ts.map +0 -1
- package/dist/types/helpers.js +0 -3
- package/dist/types/helpers.js.map +0 -1
- package/dist/types/subscription/index.d.ts +0 -80
- package/dist/types/subscription/index.d.ts.map +0 -1
- package/dist/types/subscription/index.js +0 -3
- package/dist/types/subscription/index.js.map +0 -1
- package/src/cli/check-update.js +0 -13
- package/src/cli/get-hooks.js +0 -17
- package/src/cli/get-manifest.js +0 -16
- package/src/cli/hook-utils/get-check-update-data.js +0 -292
- package/src/cli/hook-utils/get-manifest-data.js +0 -39
- package/src/cli/hook-utils/manifest.js +0 -108
- package/src/cli/start.js +0 -43
package/dist/App.js
CHANGED
|
@@ -4,29 +4,24 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.LogLevel = void 0;
|
|
7
|
-
const
|
|
8
|
-
const web_api_1 = require("@slack/web-api");
|
|
7
|
+
const node_util_1 = __importDefault(require("node:util"));
|
|
9
8
|
const logger_1 = require("@slack/logger");
|
|
9
|
+
const web_api_1 = require("@slack/web-api");
|
|
10
10
|
const axios_1 = __importDefault(require("axios"));
|
|
11
|
-
const
|
|
12
|
-
const HTTPReceiver_1 = __importDefault(require("./receivers/HTTPReceiver"));
|
|
13
|
-
const builtin_1 = require("./middleware/builtin");
|
|
14
|
-
const process_1 = __importDefault(require("./middleware/process"));
|
|
11
|
+
const CustomFunction_1 = require("./CustomFunction");
|
|
15
12
|
const conversation_store_1 = require("./conversation-store");
|
|
16
|
-
const Subscription_1 = require("./Subscription");
|
|
17
|
-
const helpers_1 = require("./helpers");
|
|
18
13
|
const errors_1 = require("./errors");
|
|
14
|
+
const helpers_1 = require("./helpers");
|
|
15
|
+
const builtin_1 = require("./middleware/builtin");
|
|
16
|
+
const process_1 = __importDefault(require("./middleware/process"));
|
|
17
|
+
const HTTPReceiver_1 = __importDefault(require("./receivers/HTTPReceiver"));
|
|
18
|
+
const SocketModeReceiver_1 = __importDefault(require("./receivers/SocketModeReceiver"));
|
|
19
19
|
const middleware_1 = require("./types/middleware");
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports, import/no-commonjs
|
|
23
|
-
const packageJson = require('../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires
|
|
24
|
-
// ----------------------------
|
|
25
|
-
// For CLI local run use case
|
|
26
|
-
const cliAppTokenOverride = process.env.SLACK_CLI_XAPP;
|
|
27
|
-
const cliBotTokenOverride = process.env.SLACK_CLI_XOXB;
|
|
20
|
+
const utilities_1 = require("./types/utilities");
|
|
21
|
+
const packageJson = require('../package.json');
|
|
28
22
|
// ----------------------------
|
|
29
23
|
// For listener registration methods
|
|
24
|
+
// TODO: we have types for this... consolidate
|
|
30
25
|
const validViewTypes = ['view_closed', 'view_submission'];
|
|
31
26
|
// ----------------------------
|
|
32
27
|
// For the constructor
|
|
@@ -35,9 +30,7 @@ const tokenUsage = 'Apps used in a single workspace can be initialized with a to
|
|
|
35
30
|
var logger_2 = require("@slack/logger");
|
|
36
31
|
Object.defineProperty(exports, "LogLevel", { enumerable: true, get: function () { return logger_2.LogLevel; } });
|
|
37
32
|
class WebClientPool {
|
|
38
|
-
|
|
39
|
-
this.pool = {};
|
|
40
|
-
}
|
|
33
|
+
pool = {};
|
|
41
34
|
getOrCreate(token, clientOptions) {
|
|
42
35
|
const cachedClient = this.pool[token];
|
|
43
36
|
if (typeof cachedClient !== 'undefined') {
|
|
@@ -52,22 +45,53 @@ class WebClientPool {
|
|
|
52
45
|
* A Slack App
|
|
53
46
|
*/
|
|
54
47
|
class App {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
/** Slack Web API client */
|
|
49
|
+
client;
|
|
50
|
+
clientOptions;
|
|
51
|
+
// Some payloads don't have teamId anymore. So we use EnterpriseId in those scenarios
|
|
52
|
+
clients = {};
|
|
53
|
+
/** Receiver - ingests events from the Slack platform */
|
|
54
|
+
receiver;
|
|
55
|
+
/** Logger */
|
|
56
|
+
logger;
|
|
57
|
+
/** Log Level */
|
|
58
|
+
logLevel;
|
|
59
|
+
/** Authorize */
|
|
60
|
+
authorize;
|
|
61
|
+
/** Global middleware chain */
|
|
62
|
+
middleware;
|
|
63
|
+
/** Listener middleware chains */
|
|
64
|
+
listeners;
|
|
65
|
+
errorHandler;
|
|
66
|
+
axios;
|
|
67
|
+
installerOptions;
|
|
68
|
+
socketMode;
|
|
69
|
+
developerMode;
|
|
70
|
+
extendedErrorHandler;
|
|
71
|
+
hasCustomErrorHandler;
|
|
72
|
+
// used when deferInitialization is true
|
|
73
|
+
argToken;
|
|
74
|
+
// used when deferInitialization is true
|
|
75
|
+
argAuthorize;
|
|
76
|
+
// used when deferInitialization is true
|
|
77
|
+
argAuthorization;
|
|
78
|
+
tokenVerificationEnabled;
|
|
79
|
+
initialized;
|
|
80
|
+
attachFunctionToken;
|
|
81
|
+
constructor({ signingSecret = undefined, endpoints = undefined, port = undefined, customRoutes = undefined, agent = undefined, clientTls = undefined, receiver = undefined, convoStore = undefined, token = undefined, appToken = undefined, botId = undefined, botUserId = undefined, authorize = undefined, logger = undefined, logLevel = undefined, ignoreSelf = true, clientOptions = undefined, processBeforeResponse = false, signatureVerification = true, clientId = undefined, clientSecret = undefined, stateSecret = undefined, redirectUri = undefined, installationStore = undefined, scopes = undefined, installerOptions = undefined, socketMode = undefined, developerMode = false, tokenVerificationEnabled = true, extendedErrorHandler = false, deferInitialization = false, attachFunctionToken = true, } = {}) {
|
|
58
82
|
/* ------------------------ Developer mode ----------------------------- */
|
|
59
83
|
this.developerMode = developerMode;
|
|
60
|
-
if (developerMode
|
|
84
|
+
if (developerMode) {
|
|
61
85
|
// Set logLevel to Debug in Developer Mode if one wasn't passed in
|
|
62
|
-
this.logLevel = logLevel
|
|
86
|
+
this.logLevel = logLevel ?? logger_1.LogLevel.DEBUG;
|
|
63
87
|
// Set SocketMode to true if one wasn't passed in
|
|
64
|
-
this.socketMode = socketMode
|
|
88
|
+
this.socketMode = socketMode ?? true;
|
|
65
89
|
}
|
|
66
90
|
else {
|
|
67
91
|
// If devs aren't using Developer Mode or Socket Mode, set it to false
|
|
68
|
-
this.socketMode = socketMode
|
|
92
|
+
this.socketMode = socketMode ?? false;
|
|
69
93
|
// Set logLevel to Info if one wasn't passed in
|
|
70
|
-
this.logLevel = logLevel
|
|
94
|
+
this.logLevel = logLevel ?? logger_1.LogLevel.INFO;
|
|
71
95
|
}
|
|
72
96
|
/* ------------------------ Set logger ----------------------------- */
|
|
73
97
|
if (typeof logger === 'undefined') {
|
|
@@ -86,6 +110,8 @@ class App {
|
|
|
86
110
|
this.hasCustomErrorHandler = false;
|
|
87
111
|
this.errorHandler = defaultErrorHandler(this.logger);
|
|
88
112
|
this.extendedErrorHandler = extendedErrorHandler;
|
|
113
|
+
// Override token with functionBotAccessToken in function-related handlers
|
|
114
|
+
this.attachFunctionToken = attachFunctionToken;
|
|
89
115
|
/* ------------------------ Set client options ------------------------*/
|
|
90
116
|
this.clientOptions = clientOptions !== undefined ? clientOptions : {};
|
|
91
117
|
if (agent !== undefined && this.clientOptions.agent === undefined) {
|
|
@@ -104,7 +130,7 @@ class App {
|
|
|
104
130
|
}
|
|
105
131
|
// The public WebClient instance (app.client)
|
|
106
132
|
// Since v3.4, it can have the passed token in the case of single workspace installation.
|
|
107
|
-
this.client = new web_api_1.WebClient(
|
|
133
|
+
this.client = new web_api_1.WebClient(token, this.clientOptions);
|
|
108
134
|
this.axios = axios_1.default.create({
|
|
109
135
|
httpAgent: agent,
|
|
110
136
|
httpsAgent: agent,
|
|
@@ -138,11 +164,11 @@ class App {
|
|
|
138
164
|
failure: (error, _installOptions, _req, res) => {
|
|
139
165
|
this.logger.debug(error);
|
|
140
166
|
res.writeHead(500, { 'Content-Type': 'text/html' });
|
|
141
|
-
res.end(`<html><body><h1>OAuth failed!</h1><div>${error}</div></body></html>`);
|
|
167
|
+
res.end(`<html><body><h1>OAuth failed!</h1><div>${escapeHtml(error.code)}</div></body></html>`);
|
|
142
168
|
},
|
|
143
169
|
};
|
|
144
170
|
}
|
|
145
|
-
this.receiver = this.initReceiver(receiver, signingSecret, endpoints, port, customRoutes, processBeforeResponse, signatureVerification, clientId, clientSecret, stateSecret, redirectUri, installationStore, scopes,
|
|
171
|
+
this.receiver = this.initReceiver(receiver, signingSecret, endpoints, port, customRoutes, processBeforeResponse, signatureVerification, clientId, clientSecret, stateSecret, redirectUri, installationStore, scopes, appToken, logger);
|
|
146
172
|
/* ------------------------ Set authorize ----------------------------- */
|
|
147
173
|
this.tokenVerificationEnabled = tokenVerificationEnabled;
|
|
148
174
|
let argAuthorization;
|
|
@@ -153,15 +179,7 @@ class App {
|
|
|
153
179
|
botToken: token,
|
|
154
180
|
};
|
|
155
181
|
}
|
|
156
|
-
if (cliBotTokenOverride !== undefined) {
|
|
157
|
-
argAuthorization = {
|
|
158
|
-
botId,
|
|
159
|
-
botUserId,
|
|
160
|
-
botToken: cliBotTokenOverride,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
182
|
if (deferInitialization) {
|
|
164
|
-
// TODO: Deal with this
|
|
165
183
|
this.argToken = token;
|
|
166
184
|
this.argAuthorize = authorize;
|
|
167
185
|
this.argAuthorization = argAuthorization;
|
|
@@ -169,12 +187,12 @@ class App {
|
|
|
169
187
|
// You need to run `await app.init();` on your own
|
|
170
188
|
}
|
|
171
189
|
else {
|
|
172
|
-
this.authorize = this.initAuthorizeInConstructor(
|
|
190
|
+
this.authorize = this.initAuthorizeInConstructor(token, authorize, argAuthorization);
|
|
173
191
|
this.initialized = true;
|
|
174
192
|
}
|
|
175
193
|
// Conditionally use a global middleware that ignores events (including messages) that are sent from this app
|
|
176
194
|
if (ignoreSelf) {
|
|
177
|
-
this.use(
|
|
195
|
+
this.use(builtin_1.ignoreSelf);
|
|
178
196
|
}
|
|
179
197
|
// Use conversation state global middleware
|
|
180
198
|
if (convoStore !== false) {
|
|
@@ -220,6 +238,9 @@ class App {
|
|
|
220
238
|
throw e;
|
|
221
239
|
}
|
|
222
240
|
}
|
|
241
|
+
get webClientOptions() {
|
|
242
|
+
return this.clientOptions;
|
|
243
|
+
}
|
|
223
244
|
/**
|
|
224
245
|
* Register a new middleware, processed in the order registered.
|
|
225
246
|
*
|
|
@@ -229,6 +250,27 @@ class App {
|
|
|
229
250
|
this.middleware.push(m);
|
|
230
251
|
return this;
|
|
231
252
|
}
|
|
253
|
+
/**
|
|
254
|
+
* Register WorkflowStep middleware
|
|
255
|
+
*
|
|
256
|
+
* @param workflowStep global workflow step middleware function
|
|
257
|
+
* @deprecated Steps from Apps are no longer supported and support for them will be removed in the next major bolt-js
|
|
258
|
+
* version.
|
|
259
|
+
*/
|
|
260
|
+
step(workflowStep) {
|
|
261
|
+
const m = workflowStep.getMiddleware();
|
|
262
|
+
this.middleware.push(m);
|
|
263
|
+
return this;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Register CustomFunction middleware
|
|
267
|
+
*/
|
|
268
|
+
function(callbackId, ...listeners) {
|
|
269
|
+
const fn = new CustomFunction_1.CustomFunction(callbackId, listeners, this.webClientOptions);
|
|
270
|
+
const m = fn.getMiddleware();
|
|
271
|
+
this.middleware.push(m);
|
|
272
|
+
return this;
|
|
273
|
+
}
|
|
232
274
|
/**
|
|
233
275
|
* Convenience method to call start on the receiver
|
|
234
276
|
*
|
|
@@ -243,38 +285,10 @@ class App {
|
|
|
243
285
|
// TODO: HTTPReceiver['start'] should be the actual receiver's return type
|
|
244
286
|
return this.receiver.start(...args);
|
|
245
287
|
}
|
|
246
|
-
//
|
|
288
|
+
// biome-ignore lint/suspicious/noExplicitAny: receivers could accept anything as arguments for stop
|
|
247
289
|
stop(...args) {
|
|
248
290
|
return this.receiver.stop(...args);
|
|
249
291
|
}
|
|
250
|
-
/**
|
|
251
|
-
* Register WorkflowStep middleware
|
|
252
|
-
*
|
|
253
|
-
* Not to be confused with next-gen platform Workflows + Functions
|
|
254
|
-
*
|
|
255
|
-
* @param workflowStep global workflow step middleware function
|
|
256
|
-
*/
|
|
257
|
-
step(workflowStep) {
|
|
258
|
-
const m = workflowStep.getMiddleware();
|
|
259
|
-
this.middleware.push(m);
|
|
260
|
-
return this;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Process a subscription event
|
|
264
|
-
*
|
|
265
|
-
* @param listeners middleware that process and react to subscription payloads
|
|
266
|
-
*/
|
|
267
|
-
subscription(options) {
|
|
268
|
-
/*
|
|
269
|
-
* TODO If it becomes possible for users to set a custom unique resource id,
|
|
270
|
-
* custom id should be supplied in place of the default.
|
|
271
|
-
* */
|
|
272
|
-
const defaultId = 'DEFAULTID';
|
|
273
|
-
const s = new Subscription_1.Subscription(defaultId, options);
|
|
274
|
-
const m = s.getMiddleware();
|
|
275
|
-
this.middleware.push(m);
|
|
276
|
-
return this;
|
|
277
|
-
}
|
|
278
292
|
event(eventNameOrPattern, ...listeners) {
|
|
279
293
|
let invalidEventName = false;
|
|
280
294
|
if (typeof eventNameOrPattern === 'string') {
|
|
@@ -286,36 +300,25 @@ class App {
|
|
|
286
300
|
invalidEventName = name.startsWith('message\\.');
|
|
287
301
|
}
|
|
288
302
|
if (invalidEventName) {
|
|
289
|
-
throw new errors_1.AppInitializationError(`Although the document mentions "${eventNameOrPattern}"
|
|
290
|
-
'it is not a valid event type. Use "message" instead. ' +
|
|
291
|
-
'If you want to filter message events, you can use event.channel_type for it.');
|
|
303
|
+
throw new errors_1.AppInitializationError(`Although the document mentions "${eventNameOrPattern}", it is not a valid event type. Use "message" instead. If you want to filter message events, you can use event.channel_type for it.`);
|
|
292
304
|
}
|
|
293
|
-
//
|
|
294
|
-
const _listeners = listeners;
|
|
305
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
306
|
+
const _listeners = listeners;
|
|
295
307
|
this.listeners.push([
|
|
296
308
|
builtin_1.onlyEvents,
|
|
297
309
|
(0, builtin_1.matchEventType)(eventNameOrPattern),
|
|
298
310
|
..._listeners,
|
|
299
311
|
]);
|
|
300
312
|
}
|
|
301
|
-
|
|
302
|
-
* Register a Slack Function
|
|
303
|
-
*
|
|
304
|
-
* @param slackFn a main function to register
|
|
305
|
-
*
|
|
306
|
-
* */
|
|
307
|
-
function(slackFn) {
|
|
308
|
-
const m = slackFn.getMiddleware();
|
|
309
|
-
this.middleware.push(m);
|
|
310
|
-
}
|
|
313
|
+
// TODO: expose a type parameter for overriding the MessageEvent type (just like shortcut() and action() does) https://github.com/slackapi/bolt-js/issues/796
|
|
311
314
|
message(...patternsOrMiddleware) {
|
|
312
315
|
const messageMiddleware = patternsOrMiddleware.map((patternOrMiddleware) => {
|
|
313
|
-
if (typeof patternOrMiddleware === 'string' ||
|
|
316
|
+
if (typeof patternOrMiddleware === 'string' || node_util_1.default.types.isRegExp(patternOrMiddleware)) {
|
|
314
317
|
return (0, builtin_1.matchMessage)(patternOrMiddleware);
|
|
315
318
|
}
|
|
316
319
|
return patternOrMiddleware;
|
|
317
|
-
//
|
|
318
|
-
});
|
|
320
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
321
|
+
});
|
|
319
322
|
this.listeners.push([
|
|
320
323
|
builtin_1.onlyEvents,
|
|
321
324
|
(0, builtin_1.matchEventType)('message'),
|
|
@@ -323,17 +326,18 @@ class App {
|
|
|
323
326
|
]);
|
|
324
327
|
}
|
|
325
328
|
shortcut(callbackIdOrConstraints, ...listeners) {
|
|
326
|
-
const constraints = typeof callbackIdOrConstraints === 'string' ||
|
|
327
|
-
{ callback_id: callbackIdOrConstraints }
|
|
328
|
-
callbackIdOrConstraints;
|
|
329
|
+
const constraints = typeof callbackIdOrConstraints === 'string' || node_util_1.default.types.isRegExp(callbackIdOrConstraints)
|
|
330
|
+
? { callback_id: callbackIdOrConstraints }
|
|
331
|
+
: callbackIdOrConstraints;
|
|
329
332
|
// Fail early if the constraints contain invalid keys
|
|
330
333
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'callback_id' && k !== 'type');
|
|
331
334
|
if (unknownConstraintKeys.length > 0) {
|
|
335
|
+
// TODO:event() will throw an error if you provide an invalid event name; we should align this behaviour.
|
|
332
336
|
this.logger.error(`Slack listener cannot be attached using unknown constraint keys: ${unknownConstraintKeys.join(', ')}`);
|
|
333
337
|
return;
|
|
334
338
|
}
|
|
335
|
-
//
|
|
336
|
-
const _listeners = listeners;
|
|
339
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
340
|
+
const _listeners = listeners;
|
|
337
341
|
this.listeners.push([
|
|
338
342
|
builtin_1.onlyShortcuts,
|
|
339
343
|
(0, builtin_1.matchConstraints)(constraints),
|
|
@@ -342,22 +346,23 @@ class App {
|
|
|
342
346
|
}
|
|
343
347
|
action(actionIdOrConstraints, ...listeners) {
|
|
344
348
|
// Normalize Constraints
|
|
345
|
-
const constraints = typeof actionIdOrConstraints === 'string' ||
|
|
346
|
-
{ action_id: actionIdOrConstraints }
|
|
347
|
-
actionIdOrConstraints;
|
|
349
|
+
const constraints = typeof actionIdOrConstraints === 'string' || node_util_1.default.types.isRegExp(actionIdOrConstraints)
|
|
350
|
+
? { action_id: actionIdOrConstraints }
|
|
351
|
+
: actionIdOrConstraints;
|
|
348
352
|
// Fail early if the constraints contain invalid keys
|
|
349
353
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'action_id' && k !== 'block_id' && k !== 'callback_id' && k !== 'type');
|
|
350
354
|
if (unknownConstraintKeys.length > 0) {
|
|
355
|
+
// TODO:event() will throw an error if you provide an invalid event name; we should align this behaviour.
|
|
351
356
|
this.logger.error(`Action listener cannot be attached using unknown constraint keys: ${unknownConstraintKeys.join(', ')}`);
|
|
352
357
|
return;
|
|
353
358
|
}
|
|
354
|
-
//
|
|
355
|
-
const _listeners = listeners;
|
|
359
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
360
|
+
const _listeners = listeners;
|
|
356
361
|
this.listeners.push([builtin_1.onlyActions, (0, builtin_1.matchConstraints)(constraints), ..._listeners]);
|
|
357
362
|
}
|
|
358
363
|
command(commandName, ...listeners) {
|
|
359
|
-
//
|
|
360
|
-
const _listeners = listeners;
|
|
364
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
365
|
+
const _listeners = listeners;
|
|
361
366
|
this.listeners.push([
|
|
362
367
|
builtin_1.onlyCommands,
|
|
363
368
|
(0, builtin_1.matchCommandName)(commandName),
|
|
@@ -366,17 +371,17 @@ class App {
|
|
|
366
371
|
}
|
|
367
372
|
// TODO: reflect the type in constraints to Source
|
|
368
373
|
options(actionIdOrConstraints, ...listeners) {
|
|
369
|
-
const constraints = typeof actionIdOrConstraints === 'string' ||
|
|
370
|
-
{ action_id: actionIdOrConstraints }
|
|
371
|
-
actionIdOrConstraints;
|
|
372
|
-
//
|
|
373
|
-
const _listeners = listeners;
|
|
374
|
+
const constraints = typeof actionIdOrConstraints === 'string' || node_util_1.default.types.isRegExp(actionIdOrConstraints)
|
|
375
|
+
? { action_id: actionIdOrConstraints }
|
|
376
|
+
: actionIdOrConstraints;
|
|
377
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
378
|
+
const _listeners = listeners;
|
|
374
379
|
this.listeners.push([builtin_1.onlyOptions, (0, builtin_1.matchConstraints)(constraints), ..._listeners]);
|
|
375
380
|
}
|
|
376
381
|
view(callbackIdOrConstraints, ...listeners) {
|
|
377
|
-
const constraints = typeof callbackIdOrConstraints === 'string' ||
|
|
378
|
-
{ callback_id: callbackIdOrConstraints, type: 'view_submission' }
|
|
379
|
-
callbackIdOrConstraints;
|
|
382
|
+
const constraints = typeof callbackIdOrConstraints === 'string' || node_util_1.default.types.isRegExp(callbackIdOrConstraints)
|
|
383
|
+
? { callback_id: callbackIdOrConstraints, type: 'view_submission' }
|
|
384
|
+
: callbackIdOrConstraints;
|
|
380
385
|
// Fail early if the constraints contain invalid keys
|
|
381
386
|
const unknownConstraintKeys = Object.keys(constraints).filter((k) => k !== 'callback_id' && k !== 'type');
|
|
382
387
|
if (unknownConstraintKeys.length > 0) {
|
|
@@ -387,8 +392,8 @@ class App {
|
|
|
387
392
|
this.logger.error(`View listener cannot be attached using unknown view event type: ${constraints.type}`);
|
|
388
393
|
return;
|
|
389
394
|
}
|
|
390
|
-
//
|
|
391
|
-
const _listeners = listeners;
|
|
395
|
+
// biome-ignore lint/suspicious/noExplicitAny: FIXME: workaround for TypeScript 4.7 breaking changes
|
|
396
|
+
const _listeners = listeners;
|
|
392
397
|
this.listeners.push([
|
|
393
398
|
builtin_1.onlyViewActions,
|
|
394
399
|
(0, builtin_1.matchConstraints)(constraints),
|
|
@@ -422,11 +427,10 @@ class App {
|
|
|
422
427
|
// From this point on, we assume that body is not just a key-value map, but one of the types of bodies we expect
|
|
423
428
|
const bodyArg = body;
|
|
424
429
|
// Check if type event with the authorizations object or if it has a top level is_enterprise_install property
|
|
425
|
-
const isEnterpriseInstall = isBodyWithTypeEnterpriseInstall(bodyArg, type);
|
|
430
|
+
const isEnterpriseInstall = (0, helpers_1.isBodyWithTypeEnterpriseInstall)(bodyArg, type);
|
|
426
431
|
const source = buildSource(type, conversationId, bodyArg, isEnterpriseInstall);
|
|
427
|
-
// Get the result of any custom authorize provided
|
|
428
432
|
let authorizeResult;
|
|
429
|
-
if (type === helpers_1.IncomingEventType.Event && isEventTypeToSkipAuthorize(event
|
|
433
|
+
if (type === helpers_1.IncomingEventType.Event && (0, helpers_1.isEventTypeToSkipAuthorize)(event)) {
|
|
430
434
|
authorizeResult = {
|
|
431
435
|
enterpriseId: source.enterpriseId,
|
|
432
436
|
teamId: source.teamId,
|
|
@@ -437,12 +441,10 @@ class App {
|
|
|
437
441
|
authorizeResult = await this.authorize(source, bodyArg);
|
|
438
442
|
}
|
|
439
443
|
catch (error) {
|
|
440
|
-
//
|
|
444
|
+
// biome-ignore lint/suspicious/noExplicitAny: errors can be anything
|
|
441
445
|
const e = error;
|
|
442
446
|
this.logger.warn('Authorization of incoming event did not succeed. No listeners will be called.');
|
|
443
447
|
e.code = errors_1.ErrorCode.AuthorizationError;
|
|
444
|
-
// disabling due to https://github.com/typescript-eslint/typescript-eslint/issues/1277
|
|
445
|
-
// eslint-disable-next-line consistent-return
|
|
446
448
|
return this.handleError({
|
|
447
449
|
error: e,
|
|
448
450
|
logger: this.logger,
|
|
@@ -453,6 +455,10 @@ class App {
|
|
|
453
455
|
});
|
|
454
456
|
}
|
|
455
457
|
}
|
|
458
|
+
// Try to set userId from AuthorizeResult before using one from source
|
|
459
|
+
if (authorizeResult.userId === undefined && source.userId !== undefined) {
|
|
460
|
+
authorizeResult.userId = source.userId;
|
|
461
|
+
}
|
|
456
462
|
// Try to set teamId from AuthorizeResult before using one from source
|
|
457
463
|
if (authorizeResult.teamId === undefined && source.teamId !== undefined) {
|
|
458
464
|
authorizeResult.teamId = source.teamId;
|
|
@@ -461,7 +467,6 @@ class App {
|
|
|
461
467
|
if (authorizeResult.enterpriseId === undefined && source.enterpriseId !== undefined) {
|
|
462
468
|
authorizeResult.enterpriseId = source.enterpriseId;
|
|
463
469
|
}
|
|
464
|
-
// Try to set custom properties if they exist
|
|
465
470
|
if (typeof event.customProperties !== 'undefined') {
|
|
466
471
|
const customProps = event.customProperties;
|
|
467
472
|
const builtinKeyDetected = middleware_1.contextBuiltinKeys.find((key) => key in customProps);
|
|
@@ -469,49 +474,45 @@ class App {
|
|
|
469
474
|
throw new errors_1.InvalidCustomPropertyError('customProperties cannot have the same names with the built-in ones');
|
|
470
475
|
}
|
|
471
476
|
}
|
|
472
|
-
/**
|
|
473
|
-
* Set the Slack Function Bot Access Token if it exists in event payload to the context.
|
|
474
|
-
*
|
|
475
|
-
* A bot_access_token will exist in any payload that has been generated
|
|
476
|
-
* in the context of a Slack Function execution. This includes function_execution
|
|
477
|
-
* events themselves, as well as interactivity payloads (e.g. block_actions, views).
|
|
478
|
-
*
|
|
479
|
-
* This token must be used for further Slack API calls which are relevant to this
|
|
480
|
-
* Slack Function execution in order for any interactivity context data to be
|
|
481
|
-
* properly sent by Slack.
|
|
482
|
-
*
|
|
483
|
-
* Bolt will set this value in the event Context and
|
|
484
|
-
* use this token in place of any other token (for example the token
|
|
485
|
-
* that the App was configured with) to initialize the Web Client.
|
|
486
|
-
*
|
|
487
|
-
* Sometimes the bot_access_token is located in the event
|
|
488
|
-
* Sometimes it is located directly in the body.
|
|
489
|
-
*/
|
|
490
|
-
let slackFunctionBotAccessToken = body.bot_access_token;
|
|
491
|
-
if (slackFunctionBotAccessToken === undefined && 'event' in body) {
|
|
492
|
-
slackFunctionBotAccessToken = body.event.bot_access_token;
|
|
493
|
-
}
|
|
494
|
-
// Declare the event context
|
|
495
477
|
const context = {
|
|
496
478
|
...authorizeResult,
|
|
497
479
|
...event.customProperties,
|
|
498
|
-
slackFunctionBotAccessToken,
|
|
499
480
|
isEnterpriseInstall,
|
|
500
481
|
retryNum: event.retryNum,
|
|
501
482
|
retryReason: event.retryReason,
|
|
502
483
|
};
|
|
484
|
+
// Extract function-related information and augment context
|
|
485
|
+
const { functionExecutionId, functionBotAccessToken, functionInputs } = extractFunctionContext(body);
|
|
486
|
+
if (functionExecutionId) {
|
|
487
|
+
context.functionExecutionId = functionExecutionId;
|
|
488
|
+
if (functionInputs) {
|
|
489
|
+
context.functionInputs = functionInputs;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
// Attach and make available the JIT/function-related token on context
|
|
493
|
+
if (this.attachFunctionToken) {
|
|
494
|
+
if (functionBotAccessToken) {
|
|
495
|
+
context.functionBotAccessToken = functionBotAccessToken;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
503
498
|
// Factory for say() utility
|
|
504
499
|
const createSay = (channelId) => {
|
|
505
500
|
const token = selectToken(context);
|
|
506
501
|
return (message) => {
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
{
|
|
502
|
+
let postMessageArguments;
|
|
503
|
+
if (typeof message === 'string') {
|
|
504
|
+
postMessageArguments = { token, text: message, channel: channelId };
|
|
505
|
+
}
|
|
506
|
+
else {
|
|
507
|
+
postMessageArguments = { ...message, token, channel: channelId };
|
|
508
|
+
}
|
|
510
509
|
return this.client.chat.postMessage(postMessageArguments);
|
|
511
510
|
};
|
|
512
511
|
};
|
|
513
512
|
// Set body and payload
|
|
514
513
|
// TODO: this value should eventually conform to AnyMiddlewareArgs
|
|
514
|
+
// TODO: remove workflow step stuff in bolt v5
|
|
515
|
+
// TODO: can we instead use type predicates in these switch cases to allow for narrowing of the body simultaneously? we have isEvent, isView, isShortcut, isAction already in types/utilities / helpers
|
|
515
516
|
let payload;
|
|
516
517
|
switch (type) {
|
|
517
518
|
case helpers_1.IncomingEventType.Event:
|
|
@@ -523,8 +524,7 @@ class App {
|
|
|
523
524
|
case helpers_1.IncomingEventType.Shortcut:
|
|
524
525
|
payload = bodyArg;
|
|
525
526
|
break;
|
|
526
|
-
//
|
|
527
|
-
// @ts-ignore: Fallthrough case in switch
|
|
527
|
+
// biome-ignore lint/suspicious/noFallthroughSwitchClause: usually not great, but we do it here
|
|
528
528
|
case helpers_1.IncomingEventType.Action:
|
|
529
529
|
if (isBlockActionOrInteractiveMessageBody(bodyArg)) {
|
|
530
530
|
const { actions } = bodyArg;
|
|
@@ -536,10 +536,13 @@ class App {
|
|
|
536
536
|
payload = bodyArg;
|
|
537
537
|
break;
|
|
538
538
|
}
|
|
539
|
+
// NOTE: the following doesn't work because... distributive?
|
|
540
|
+
// const listenerArgs: Partial<AnyMiddlewareArgs> = {
|
|
539
541
|
const listenerArgs = {
|
|
540
542
|
body: bodyArg,
|
|
541
543
|
payload,
|
|
542
544
|
};
|
|
545
|
+
// TODO: can we instead use type predicates in these switch cases to allow for narrowing of the body simultaneously? we have isEvent, isView, isShortcut, isAction already in types/utilities / helpers
|
|
543
546
|
// Set aliases
|
|
544
547
|
if (type === helpers_1.IncomingEventType.Event) {
|
|
545
548
|
const eventListenerArgs = listenerArgs;
|
|
@@ -589,16 +592,24 @@ class App {
|
|
|
589
592
|
// Events API requests are acknowledged right away, since there's no data expected
|
|
590
593
|
await ack();
|
|
591
594
|
}
|
|
592
|
-
// Get
|
|
595
|
+
// Get the client arg
|
|
593
596
|
let { client } = this;
|
|
594
|
-
|
|
597
|
+
// If functionBotAccessToken exists on context, the incoming event is function-related *and* the
|
|
598
|
+
// user has `attachFunctionToken` enabled. In that case, subsequent calls with the client should
|
|
599
|
+
// use the function-related/JIT token in lieu of the botToken or userToken.
|
|
600
|
+
const token = context.functionBotAccessToken ? context.functionBotAccessToken : selectToken(context);
|
|
601
|
+
// Add complete() and fail() utilities for function-related interactivity
|
|
602
|
+
if (type === helpers_1.IncomingEventType.Action && context.functionExecutionId !== undefined) {
|
|
603
|
+
listenerArgs.complete = CustomFunction_1.CustomFunction.createFunctionComplete(context, client);
|
|
604
|
+
listenerArgs.fail = CustomFunction_1.CustomFunction.createFunctionFail(context, client);
|
|
605
|
+
listenerArgs.inputs = context.functionInputs;
|
|
606
|
+
}
|
|
595
607
|
if (token !== undefined) {
|
|
596
|
-
let pool;
|
|
608
|
+
let pool = undefined;
|
|
597
609
|
const clientOptionsCopy = { ...this.clientOptions };
|
|
598
610
|
if (authorizeResult.teamId !== undefined) {
|
|
599
611
|
pool = this.clients[authorizeResult.teamId];
|
|
600
612
|
if (pool === undefined) {
|
|
601
|
-
// eslint-disable-next-line no-multi-assign
|
|
602
613
|
pool = this.clients[authorizeResult.teamId] = new WebClientPool();
|
|
603
614
|
}
|
|
604
615
|
// Add teamId to clientOptions so it can be automatically added to web-api calls
|
|
@@ -607,7 +618,6 @@ class App {
|
|
|
607
618
|
else if (authorizeResult.enterpriseId !== undefined) {
|
|
608
619
|
pool = this.clients[authorizeResult.enterpriseId];
|
|
609
620
|
if (pool === undefined) {
|
|
610
|
-
// eslint-disable-next-line no-multi-assign
|
|
611
621
|
pool = this.clients[authorizeResult.enterpriseId] = new WebClientPool();
|
|
612
622
|
}
|
|
613
623
|
}
|
|
@@ -623,26 +633,27 @@ class App {
|
|
|
623
633
|
const listenerResults = this.listeners.map(async (origListenerMiddleware) => {
|
|
624
634
|
// Copy the array so modifications don't affect the original
|
|
625
635
|
const listenerMiddleware = [...origListenerMiddleware];
|
|
626
|
-
// Don't process the last item in the listenerMiddleware array - it
|
|
636
|
+
// Don't process the last item in the listenerMiddleware array - it will be passed a no-op next fn
|
|
627
637
|
const listener = listenerMiddleware.pop();
|
|
628
638
|
if (listener === undefined) {
|
|
629
639
|
return undefined;
|
|
630
640
|
}
|
|
631
641
|
return (0, process_1.default)(listenerMiddleware, listenerArgs, context, client, this.logger,
|
|
632
642
|
// When all the listener middleware are done processing,
|
|
633
|
-
// `listener` here will be called
|
|
643
|
+
// `listener` here will be called with a noop `next` fn
|
|
634
644
|
async () => listener({
|
|
635
645
|
...listenerArgs,
|
|
636
646
|
context,
|
|
637
647
|
client,
|
|
638
648
|
logger: this.logger,
|
|
639
|
-
|
|
649
|
+
next: () => { },
|
|
640
650
|
}));
|
|
641
651
|
});
|
|
642
|
-
const settledListenerResults = await allSettled(listenerResults);
|
|
643
|
-
const rejectedListenerResults = settledListenerResults.filter(
|
|
652
|
+
const settledListenerResults = await Promise.allSettled(listenerResults);
|
|
653
|
+
const rejectedListenerResults = settledListenerResults.filter(utilities_1.isRejected);
|
|
644
654
|
if (rejectedListenerResults.length === 1) {
|
|
645
655
|
throw rejectedListenerResults[0].reason;
|
|
656
|
+
// biome-ignore lint/style/noUselessElse: I think this is a biome issue actually...
|
|
646
657
|
}
|
|
647
658
|
else if (rejectedListenerResults.length > 1) {
|
|
648
659
|
throw new errors_1.MultipleListenerError(rejectedListenerResults.map((rlr) => rlr.reason));
|
|
@@ -650,10 +661,8 @@ class App {
|
|
|
650
661
|
});
|
|
651
662
|
}
|
|
652
663
|
catch (error) {
|
|
653
|
-
//
|
|
664
|
+
// biome-ignore lint/suspicious/noExplicitAny: errors can be anything
|
|
654
665
|
const e = error;
|
|
655
|
-
// disabling due to https://github.com/typescript-eslint/typescript-eslint/issues/1277
|
|
656
|
-
// eslint-disable-next-line consistent-return
|
|
657
666
|
return this.handleError({
|
|
658
667
|
context,
|
|
659
668
|
error: e,
|
|
@@ -667,9 +676,9 @@ class App {
|
|
|
667
676
|
*/
|
|
668
677
|
handleError(args) {
|
|
669
678
|
const { error, ...rest } = args;
|
|
670
|
-
return this.extendedErrorHandler && this.hasCustomErrorHandler
|
|
671
|
-
this.errorHandler({ error: (0, errors_1.asCodedError)(error), ...rest })
|
|
672
|
-
this.errorHandler((0, errors_1.asCodedError)(error));
|
|
679
|
+
return this.extendedErrorHandler && this.hasCustomErrorHandler
|
|
680
|
+
? this.errorHandler({ error: (0, errors_1.asCodedError)(error), ...rest })
|
|
681
|
+
: this.errorHandler((0, errors_1.asCodedError)(error));
|
|
673
682
|
}
|
|
674
683
|
// ---------------------
|
|
675
684
|
// Private methods for initialization
|
|
@@ -677,35 +686,29 @@ class App {
|
|
|
677
686
|
initReceiver(receiver, signingSecret, endpoints, port, customRoutes, processBeforeResponse, signatureVerification, clientId, clientSecret, stateSecret, redirectUri, installationStore, scopes, appToken, logger) {
|
|
678
687
|
if (receiver !== undefined) {
|
|
679
688
|
// Custom receiver supplied
|
|
680
|
-
if (this.socketMode === true) {
|
|
681
|
-
// socketMode = true should result in SocketModeReceiver being used as receiver
|
|
682
|
-
// TODO: Add case for when socketMode = true and receiver = SocketModeReceiver
|
|
683
|
-
// as this should not result in an error
|
|
689
|
+
if (this.socketMode === true && !(receiver instanceof SocketModeReceiver_1.default)) {
|
|
684
690
|
throw new errors_1.AppInitializationError('You cannot supply a custom receiver when socketMode is set to true.');
|
|
685
691
|
}
|
|
686
692
|
return receiver;
|
|
687
693
|
}
|
|
688
694
|
if (this.socketMode === true) {
|
|
689
|
-
if (
|
|
695
|
+
if (appToken === undefined) {
|
|
690
696
|
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');
|
|
691
697
|
}
|
|
692
698
|
this.logger.debug('Initializing SocketModeReceiver');
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
customRoutes,
|
|
707
|
-
});
|
|
708
|
-
}
|
|
699
|
+
return new SocketModeReceiver_1.default({
|
|
700
|
+
appToken,
|
|
701
|
+
clientId,
|
|
702
|
+
clientSecret,
|
|
703
|
+
stateSecret,
|
|
704
|
+
redirectUri,
|
|
705
|
+
installationStore,
|
|
706
|
+
scopes,
|
|
707
|
+
logger,
|
|
708
|
+
logLevel: this.logLevel,
|
|
709
|
+
installerOptions: this.installerOptions,
|
|
710
|
+
customRoutes,
|
|
711
|
+
});
|
|
709
712
|
}
|
|
710
713
|
if (signatureVerification === true && signingSecret === undefined) {
|
|
711
714
|
// Using default receiver HTTPReceiver, signature verification enabled, missing signingSecret
|
|
@@ -734,8 +737,7 @@ class App {
|
|
|
734
737
|
initAuthorizeIfNoTokenIsGiven(token, authorize) {
|
|
735
738
|
let usingOauth = false;
|
|
736
739
|
const httpReceiver = this.receiver;
|
|
737
|
-
if (httpReceiver.installer !== undefined &&
|
|
738
|
-
httpReceiver.installer.authorize !== undefined) {
|
|
740
|
+
if (httpReceiver.installer !== undefined && httpReceiver.installer.authorize !== undefined) {
|
|
739
741
|
// This supports using the built-in HTTPReceiver, declaring your own HTTPReceiver
|
|
740
742
|
// and theoretically, doing a fully custom (non-Express.js) receiver that implements OAuth
|
|
741
743
|
usingOauth = true;
|
|
@@ -747,14 +749,17 @@ class App {
|
|
|
747
749
|
return undefined;
|
|
748
750
|
}
|
|
749
751
|
if (authorize === undefined && !usingOauth) {
|
|
750
|
-
throw new errors_1.AppInitializationError(`${tokenUsage} \n\nSince you have not provided a token or authorize, you might be missing one or more required oauth installer options. See https://slack.dev/bolt-js/concepts
|
|
752
|
+
throw new errors_1.AppInitializationError(`${tokenUsage} \n\nSince you have not provided a token or authorize, you might be missing one or more required oauth installer options. See https://slack.dev/bolt-js/concepts/authenticating-oauth for these required fields.\n`);
|
|
753
|
+
// biome-ignore lint/style/noUselessElse: I think this is a biome issue actually...
|
|
751
754
|
}
|
|
752
755
|
else if (authorize !== undefined && usingOauth) {
|
|
753
756
|
throw new errors_1.AppInitializationError(`You cannot provide both authorize and oauth installer options. ${tokenUsage}`);
|
|
757
|
+
// biome-ignore lint/style/noUselessElse: I think this is a biome issue actually...
|
|
754
758
|
}
|
|
755
759
|
else if (authorize === undefined && usingOauth) {
|
|
756
|
-
//
|
|
760
|
+
// biome-ignore lint/style/noNonNullAssertion: we know installer is truthy here
|
|
757
761
|
return httpReceiver.installer.authorize;
|
|
762
|
+
// biome-ignore lint/style/noUselessElse: I think this is a biome issue actually...
|
|
758
763
|
}
|
|
759
764
|
else if (authorize !== undefined && !usingOauth) {
|
|
760
765
|
return authorize;
|
|
@@ -786,9 +791,9 @@ function defaultErrorHandler(logger) {
|
|
|
786
791
|
// singleAuthorization
|
|
787
792
|
function runAuthTestForBotToken(client, authorization) {
|
|
788
793
|
// TODO: warn when something needed isn't found
|
|
789
|
-
return authorization.botUserId !== undefined && authorization.botId !== undefined
|
|
790
|
-
Promise.resolve({ botUserId: authorization.botUserId, botId: authorization.botId })
|
|
791
|
-
client.auth.test({ token: authorization.botToken }).then((result) => ({
|
|
794
|
+
return authorization.botUserId !== undefined && authorization.botId !== undefined
|
|
795
|
+
? Promise.resolve({ botUserId: authorization.botUserId, botId: authorization.botId })
|
|
796
|
+
: client.auth.test({ token: authorization.botToken }).then((result) => ({
|
|
792
797
|
botUserId: result.user_id,
|
|
793
798
|
botId: result.bot_id,
|
|
794
799
|
}));
|
|
@@ -832,10 +837,6 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
832
837
|
if (type === helpers_1.IncomingEventType.Command) {
|
|
833
838
|
return body.team_id;
|
|
834
839
|
}
|
|
835
|
-
if (type === helpers_1.IncomingEventType.Subscription) {
|
|
836
|
-
const bodyAsSubscriptionInteraction = body;
|
|
837
|
-
return bodyAsSubscriptionInteraction.team.id;
|
|
838
|
-
}
|
|
839
840
|
const parseTeamId = (bodyAs) => {
|
|
840
841
|
// When the app is installed using org-wide deployment, team property will be null
|
|
841
842
|
if (typeof bodyAs.team !== 'undefined' && bodyAs.team !== null) {
|
|
@@ -874,10 +875,6 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
874
875
|
if (type === helpers_1.IncomingEventType.Command) {
|
|
875
876
|
return body.enterprise_id;
|
|
876
877
|
}
|
|
877
|
-
if (type === helpers_1.IncomingEventType.Subscription) {
|
|
878
|
-
const bodyAsSubscriptionInteraction = body;
|
|
879
|
-
return bodyAsSubscriptionInteraction.team.enterprise_id;
|
|
880
|
-
}
|
|
881
878
|
if (type === helpers_1.IncomingEventType.Action ||
|
|
882
879
|
type === helpers_1.IncomingEventType.Options ||
|
|
883
880
|
type === helpers_1.IncomingEventType.ViewAction ||
|
|
@@ -917,10 +914,6 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
917
914
|
}
|
|
918
915
|
return undefined;
|
|
919
916
|
}
|
|
920
|
-
if (type === helpers_1.IncomingEventType.Subscription) {
|
|
921
|
-
const bodyAsSubscriptionInteraction = body;
|
|
922
|
-
return bodyAsSubscriptionInteraction.user.id;
|
|
923
|
-
}
|
|
924
917
|
if (type === helpers_1.IncomingEventType.Action ||
|
|
925
918
|
type === helpers_1.IncomingEventType.Options ||
|
|
926
919
|
type === helpers_1.IncomingEventType.ViewAction ||
|
|
@@ -942,38 +935,12 @@ function buildSource(type, channelId, body, isEnterpriseInstall) {
|
|
|
942
935
|
conversationId: channelId,
|
|
943
936
|
};
|
|
944
937
|
}
|
|
945
|
-
function isBodyWithTypeEnterpriseInstall(body, type) {
|
|
946
|
-
if (type === helpers_1.IncomingEventType.Event) {
|
|
947
|
-
const bodyAsEvent = body;
|
|
948
|
-
if (Array.isArray(bodyAsEvent.authorizations) && bodyAsEvent.authorizations[0] !== undefined) {
|
|
949
|
-
return !!bodyAsEvent.authorizations[0].is_enterprise_install;
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
if (type === helpers_1.IncomingEventType.Subscription) {
|
|
953
|
-
return body.team.enterprise_id !== undefined;
|
|
954
|
-
}
|
|
955
|
-
if ('is_enterprise_install' in body) {
|
|
956
|
-
// command payloads have this property set as a string
|
|
957
|
-
if (typeof body.is_enterprise_install === 'string') {
|
|
958
|
-
return body.is_enterprise_install === 'true';
|
|
959
|
-
}
|
|
960
|
-
// all remaining types have a boolean property
|
|
961
|
-
if (body.is_enterprise_install !== undefined) {
|
|
962
|
-
return body.is_enterprise_install;
|
|
963
|
-
}
|
|
964
|
-
}
|
|
965
|
-
// as a fallback we assume it's a single team installation (but this should never happen)
|
|
966
|
-
return false;
|
|
967
|
-
}
|
|
968
938
|
function isBlockActionOrInteractiveMessageBody(body) {
|
|
969
939
|
return body.actions !== undefined;
|
|
970
940
|
}
|
|
971
|
-
|
|
972
|
-
* Returns in order of preference, a bot token, bot access token or user token for client, say()
|
|
973
|
-
* */
|
|
941
|
+
// Returns either a bot token or a user token for client, say()
|
|
974
942
|
function selectToken(context) {
|
|
975
|
-
|
|
976
|
-
return (_b = (_a = context.slackFunctionBotAccessToken) !== null && _a !== void 0 ? _a : context.botToken) !== null && _b !== void 0 ? _b : context.userToken;
|
|
943
|
+
return context.botToken !== undefined ? context.botToken : context.userToken;
|
|
977
944
|
}
|
|
978
945
|
function buildRespondFn(axiosInstance, responseUrl) {
|
|
979
946
|
return async (message) => {
|
|
@@ -981,11 +948,33 @@ function buildRespondFn(axiosInstance, responseUrl) {
|
|
|
981
948
|
return axiosInstance.post(responseUrl, normalizedArgs);
|
|
982
949
|
};
|
|
983
950
|
}
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
951
|
+
function escapeHtml(input) {
|
|
952
|
+
if (input) {
|
|
953
|
+
return input
|
|
954
|
+
.replace(/&/g, '&')
|
|
955
|
+
.replace(/</g, '<')
|
|
956
|
+
.replace(/>/g, '>')
|
|
957
|
+
.replace(/"/g, '"')
|
|
958
|
+
.replace(/'/g, ''');
|
|
959
|
+
}
|
|
960
|
+
return '';
|
|
961
|
+
}
|
|
962
|
+
function extractFunctionContext(body) {
|
|
963
|
+
let functionExecutionId = undefined;
|
|
964
|
+
let functionBotAccessToken = undefined;
|
|
965
|
+
let functionInputs = undefined;
|
|
966
|
+
// function_executed event
|
|
967
|
+
if (body.event && body.event.type === 'function_executed' && body.event.function_execution_id) {
|
|
968
|
+
functionExecutionId = body.event.function_execution_id;
|
|
969
|
+
functionBotAccessToken = body.event.bot_access_token;
|
|
970
|
+
}
|
|
971
|
+
// interactivity (block_actions)
|
|
972
|
+
if (body.function_data) {
|
|
973
|
+
functionExecutionId = body.function_data.execution_id;
|
|
974
|
+
functionBotAccessToken = body.bot_access_token;
|
|
975
|
+
functionInputs = body.function_data.inputs;
|
|
976
|
+
}
|
|
977
|
+
return { functionExecutionId, functionBotAccessToken, functionInputs };
|
|
989
978
|
}
|
|
990
979
|
// ----------------------------
|
|
991
980
|
// Instrumentation
|