Skip to content

feat: expose @slack/web-api options to bolt apps #2484

@zimeg

Description

@zimeg

The @slack/web-api package has neat options for the client! Some of these are available to the top-level App constructor, but others are provided via clientOptions.

At the moment, slackApiUrl is available but not allowAbsoluteUrls or other clientOptions. #2292 is similar!

Example

Following the updates of @slack/web-api in #2473, the following is possible in app setups:

const app = new App({
  token: process.env.SLACK_BOT_TOKEN,
  appToken: process.env.SLACK_APP_TOKEN,
  socketMode: true,
  logLevel: LogLevel.DEBUG,
  clientOptions: {
    allowAbsoluteUrls: false,
  },
});

Which can be tried with:

app.client.apiCall("http://localhost:8080/", { /* ... */ });

But this will cause the tsc compiler to error:

error TS2353: Object literal may only specify known properties, and 'allowAbsoluteUrls' does not exist in type 'Pick<WebClientOptions, "slackApiUrl">'.

Suggestion

I'm wondering if adding these types to clientOptions makes sense?:

  • maxRequestConcurrency
  • retryConfig
  • timeout
  • rejectRateLimitedCalls
  • headers
  • allowAbsoluteUrls
  • attachOriginalToWebAPIRequestError
  • requestInterceptor
  • adapter

IMO the customizations possible are nice, but this might not align with adding options to clientOptions or App 🤔

Another option might prefer to Omit certain options! This is an approach @slack/oauth takes:

https://github.com/slackapi/node-slack-sdk/blob/39b8992dc35f9fbf8d2afc0c00b3ba62326e8c88/packages/oauth/src/install-provider-options.ts#L98

That I think @slack/bolt might be setup well for already, using the same setup!: 🎁 ✨

bolt-js/src/App.ts

Lines 336 to 353 in 11be2fc

/* ------------------------ Set client options ------------------------*/
this.clientOptions = clientOptions !== undefined ? clientOptions : {};
if (agent !== undefined && this.clientOptions.agent === undefined) {
this.clientOptions.agent = agent;
}
if (clientTls !== undefined && this.clientOptions.tls === undefined) {
this.clientOptions.tls = clientTls;
}
if (logLevel !== undefined && logger === undefined) {
// only logLevel is passed
this.clientOptions.logLevel = logLevel;
} else {
// Since v3.4, WebClient starts sharing logger with App
this.clientOptions.logger = this.logger;
}
// The public WebClient instance (app.client)
// Since v3.4, it can have the passed token in the case of single workspace installation.
this.client = new WebClient(token, this.clientOptions);

Reference

Here's the current WebClient constructor options:

https://github.com/slackapi/node-slack-sdk/blob/39b8992dc35f9fbf8d2afc0c00b3ba62326e8c88/packages/web-api/src/WebClient.ts#L265-L284

Here's the current App constructor:

bolt-js/src/App.ts

Lines 104 to 137 in 11be2fc

export interface AppOptions {
signingSecret?: HTTPReceiverOptions['signingSecret'];
endpoints?: HTTPReceiverOptions['endpoints'];
port?: HTTPReceiverOptions['port'];
customRoutes?: HTTPReceiverOptions['customRoutes'];
processBeforeResponse?: HTTPReceiverOptions['processBeforeResponse'];
signatureVerification?: HTTPReceiverOptions['signatureVerification'];
clientId?: HTTPReceiverOptions['clientId'];
clientSecret?: HTTPReceiverOptions['clientSecret'];
stateSecret?: HTTPReceiverOptions['stateSecret']; // required when using default stateStore
redirectUri?: HTTPReceiverOptions['redirectUri'];
installationStore?: HTTPReceiverOptions['installationStore']; // default MemoryInstallationStore
scopes?: HTTPReceiverOptions['scopes'];
installerOptions?: HTTPReceiverOptions['installerOptions'];
agent?: Agent;
clientTls?: Pick<SecureContextOptions, 'pfx' | 'key' | 'passphrase' | 'cert' | 'ca'>;
convoStore?: ConversationStore | false;
token?: AuthorizeResult['botToken']; // either token or authorize
appToken?: string; // TODO should this be included in AuthorizeResult
botId?: AuthorizeResult['botId']; // only used when authorize is not defined, shortcut for fetching
botUserId?: AuthorizeResult['botUserId']; // only used when authorize is not defined, shortcut for fetching
authorize?: Authorize<boolean>; // either token or authorize
receiver?: Receiver;
logger?: Logger;
logLevel?: LogLevel;
ignoreSelf?: boolean;
clientOptions?: Pick<WebClientOptions, 'slackApiUrl'>;
socketMode?: boolean;
developerMode?: boolean;
tokenVerificationEnabled?: boolean;
deferInitialization?: boolean;
extendedErrorHandler?: boolean;
attachFunctionToken?: boolean;
}

Requirements

Please read the Contributing guidelines and Code of Conduct before creating this issue or pull request. By submitting, you are agreeing to those rules.

Metadata

Metadata

Assignees

No one assigned

    Labels

    TypeScript-specificdiscussionM-T: An issue where more input is needed to reach a decisionenhancementM-T: A feature request for new functionalitysemver:patch

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions