Skip to content

Commit 5285875

Browse files
WilliamBergaminClaude
andauthored
docs: update package READMEs for v8 (#2660)
Co-authored-by: Claude <svc-devxp-claude@slack-corp.com>
1 parent 70e15b8 commit 5285875

6 files changed

Lines changed: 168 additions & 75 deletions

File tree

AGENTS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ Individual packages have their own `AGENTS.md` with package-specific guidance:
107107

108108
Block Kit types are defined in the `@slack/types` package. See `packages/types/AGENTS.md` for detailed steps covering interface definition, discriminated union registration, barrel exports, and type tests.
109109

110+
## Pull Requests
111+
112+
When opening a pull request, use the repository's PR template at `.github/pull_request_template.md` as the PR body — the `gh` CLI does not populate it automatically, so pass the filled-in template explicitly (e.g. via `gh pr create --body-file`). Fill in every section.
113+
110114
## Common Pitfalls
111115

112116
- **Build in dependency order** — see the dependency graph above.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ walk you through building your first Slack app using Node.js.
2121

2222
| Slack API | Use | NPM Package |
2323
|--------------|--------------|-------------------|
24-
| Web API | Send data to or query data from Slack using any of [over 220 methods](https://docs.slack.dev/reference/methods). | [`@slack/web-api`](https://docs.slack.dev/tools/node-slack-sdk/web-api) |
24+
| Web API | Send data to or query data from Slack using any of [over 270 methods](https://docs.slack.dev/reference/methods). | [`@slack/web-api`](https://docs.slack.dev/tools/node-slack-sdk/web-api) |
2525
| OAuth | Set up the authentication flow using V2 OAuth for Slack apps as well as V1 OAuth for classic Slack apps. | [`@slack/oauth`](https://docs.slack.dev/tools/node-slack-sdk/oauth) |
2626
| Incoming Webhooks | Send notifications to a single channel which the user picks on installation. | [`@slack/webhook`](https://docs.slack.dev/tools/node-slack-sdk/webhook) |
2727
| Socket Mode | Listen for incoming messages and a limited set of events happening in Slack, using WebSocket. | [`@slack/socket-mode`](https://docs.slack.dev/tools/node-slack-sdk/socket-mode) |
@@ -51,11 +51,11 @@ package's documentation, linked in the table above.
5151

5252
Your app will interact with the Web API through the `WebClient` object, which is an export from `@slack/web-api`. You
5353
typically instantiate a client with a token you received from Slack. The example below shows how to post a message into
54-
a channel, DM, MPDM, or group. The `WebClient` object makes it simple to call any of the [**over 130 Web API
54+
a channel, DM, MPDM, or group. The `WebClient` object makes it simple to call any of the [**over 270 Web API
5555
methods**](https://docs.slack.dev/reference/methods).
5656

5757
```javascript
58-
const { WebClient } = require('@slack/web-api');
58+
import { WebClient } from '@slack/web-api';
5959

6060
// An access token (from your Slack app or custom integration - xoxp, xoxb)
6161
const token = process.env.SLACK_TOKEN;
@@ -94,7 +94,7 @@ Refer to [the module document page](https://docs.slack.dev/tools/node-slack-sdk/
9494

9595
## Requirements
9696

97-
This package supports Node v18 and higher. It's highly recommended to use [the latest LTS version of
97+
This package supports Node v20 and higher. It's highly recommended to use [the latest LTS version of
9898
node](https://github.com/nodejs/Release#release-schedule), and the documentation is written using syntax and features
9999
from that version.
100100

packages/oauth/README.md

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ It may be helpful to read the tutorials on [getting started](https://docs.slack.
3131
This package exposes an `InstallProvider` class, which sets up the required configuration and exposes methods such as `generateInstallUrl`, `handleCallback`, `authorize` for use within your apps. At a minimum, `InstallProvider` takes a `clientId` and `clientSecret` (both which can be obtained under the **Basic Information** of your app configuration). `InstallProvider` also requires a `stateSecret`, which is used to encode the generated state, and later used to decode that same state to verify it wasn't tampered with during the OAuth flow. **Note**: This example is not ready for production because it only stores installations (tokens) in memory. Please go to the [storing installations in a database](#storing-installations-in-a-database) section to learn how to plug in your own database.
3232

3333
```javascript
34-
const { InstallProvider } = require('@slack/oauth');
34+
import { InstallProvider } from '@slack/oauth';
3535

3636
// initialize the installProvider
3737
const installer = new InstallProvider({
@@ -47,7 +47,7 @@ const installer = new InstallProvider({
4747
</summary>
4848

4949
```javascript
50-
const { InstallProvider } = require('@slack/oauth');
50+
import { InstallProvider } from '@slack/oauth';
5151

5252
// initialize the installProvider
5353
const installer = new InstallProvider({
@@ -98,7 +98,7 @@ installer.generateInstallUrl({
9898
After the user approves the request to install your app (and grants access to the required permissions), Slack will redirect the user to your specified **redirect url**. You can either set the redirect url in the app’s **OAuth and Permissions** page or pass a `redirectUri` when calling `installProvider.generateInstallUrl`. Your HTTP server should handle requests to the redirect URL by calling the `installProvider.handleCallback()` method. The first two arguments (`req`, `res`) to `installProvider.handleCallback` are required. By default, if the installation is successful the user will be redirected back to your App Home in Slack (or redirected back to the last open workspace in your slack app for classic Slack apps). If the installation is not successful the user will be shown an error page.
9999

100100
```javascript
101-
const { createServer } = require('http');
101+
import { createServer } from 'node:http';
102102

103103
const server = createServer((req, res) => {
104104
// our redirect_uri is /slack/oauth_redirect
@@ -291,6 +291,41 @@ const installer = new InstallProvider({
291291
```
292292
---
293293

294+
### Handle errors
295+
296+
Methods on `InstallProvider` reject with an `Error` when something goes wrong. Each kind of error is its own class, all extending the `SlackOAuthError` base class, so you can use an `instanceof` check to decide how to respond. For example, `authorize()` throws an `AuthorizationError` when it can't fetch an installation.
297+
298+
```javascript
299+
import { AuthorizationError } from '@slack/oauth';
300+
301+
try {
302+
await installer.authorize({ teamId, enterpriseId });
303+
} catch (error) {
304+
if (error instanceof AuthorizationError) {
305+
// The underlying error is in `cause`.
306+
console.log(error.cause);
307+
}
308+
}
309+
```
310+
311+
To catch any error thrown by this package, check against the `SlackOAuthError` base class:
312+
313+
```javascript
314+
import { SlackOAuthError } from '@slack/oauth';
315+
316+
try {
317+
const installUrl = await installer.generateInstallUrl({ scopes: ['channels:read'] });
318+
} catch (error) {
319+
if (error instanceof SlackOAuthError) {
320+
console.log(error.code, error.message);
321+
}
322+
}
323+
```
324+
325+
Other error classes include `InstallerInitializationError`, `GenerateInstallUrlError`, `MissingStateError`, `InvalidStateError`, `MissingCodeError`, and `UnknownError`. They all extend `SlackOAuthError`, so an `instanceof SlackOAuthError` check catches any of them.
326+
327+
---
328+
294329
### Setting the log level and using a custom logger
295330

296331
The `InstallProvider` will log interesting information to the console by default. You can use the `logLevel` to decide how
@@ -300,7 +335,7 @@ in development, it's sometimes helpful to set this to the most verbose: `LogLeve
300335

301336
```javascript
302337
// Import LogLevel from the package
303-
const { InstallProvider, LogLevel } = require('@slack/oauth');
338+
import { InstallProvider, LogLevel } from '@slack/oauth';
304339

305340
// Log level is one of the options you can set in the constructor
306341
const installer = new InstallProvider({
@@ -333,7 +368,7 @@ specific methods (known as the `Logger` interface):
333368
A very simple custom logger might ignore the name and level, and write all messages to a file.
334369

335370
```javascript
336-
const { createWriteStream } = require('fs');
371+
import { createWriteStream } from 'node:fs';
337372
const logWritable = createWriteStream('/var/my_log_file'); // Not shown: close this stream
338373

339374
const installer = new InstallProvider({

packages/socket-mode/README.md

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ Note: **Socket Mode** requires the `connections:write` scope. Navigate to your [
2525

2626

2727
```javascript
28-
const { SocketModeClient } = require('@slack/socket-mode');
28+
import { SocketModeClient } from '@slack/socket-mode';
2929

3030
// Read a token from the environment variables
3131
const appToken = process.env.SLACK_APP_TOKEN;
@@ -39,7 +39,7 @@ const client = new SocketModeClient({appToken});
3939
Connecting is as easy as calling the `.start()` method.
4040

4141
```javascript
42-
const { SocketModeClient } = require('@slack/socket-mode');
42+
import { SocketModeClient } from '@slack/socket-mode';
4343
const appToken = process.env.SLACK_APP_TOKEN;
4444

4545
const socketModeClient = new SocketModeClient({appToken});
@@ -59,7 +59,7 @@ The `event` argument passed to the listener is an object. Its contents correspon
5959
event](https://docs.slack.dev/reference/events) it's registered for.
6060

6161
```javascript
62-
const { SocketModeClient } = require('@slack/socket-mode');
62+
import { SocketModeClient } from '@slack/socket-mode';
6363
const appToken = process.env.SLACK_APP_TOKEN;
6464

6565
const socketModeClient = new SocketModeClient({appToken});
@@ -79,10 +79,10 @@ socketModeClient.on('message', (event) => {
7979
To respond to events and send messages back into Slack, we recommend using the `@slack/web-api` package with a [bot token](https://docs.slack.dev/authentication/tokens#bot).
8080

8181
```javascript
82-
const { SocketModeClient } = require('@slack/socket-mode');
83-
const { WebClient } = require('@slack/web-api');
82+
import { SocketModeClient } from '@slack/socket-mode';
83+
import { WebClient } from '@slack/web-api';
8484

85-
const socketModeClient = new SocketModeClient(process.env.SLACK_APP_TOKEN);
85+
const socketModeClient = new SocketModeClient({ appToken: process.env.SLACK_APP_TOKEN });
8686
const webClient = new WebClient(process.env.BOT_TOKEN);
8787

8888
// Attach listeners to events by type. See: https://docs.slack.dev/reference/events/message
@@ -144,13 +144,49 @@ The client also emits events that are part of its lifecycle, but aren't states.
144144

145145
---
146146

147+
### Handle errors
148+
149+
Because the client is an `EventEmitter`, errors are delivered to your `error` listener rather than thrown. Each kind of error is its own class, all extending the `SlackSocketModeError` base class, so you can use an `instanceof` check to decide how to respond.
150+
151+
```javascript
152+
import {
153+
SocketModeClient,
154+
SMWebsocketError,
155+
SMPlatformError,
156+
SMSendWhileDisconnectedError,
157+
} from '@slack/socket-mode';
158+
159+
const client = new SocketModeClient({ appToken: process.env.SLACK_APP_TOKEN });
160+
161+
client.on('error', (error) => {
162+
if (error instanceof SMWebsocketError) {
163+
// A WebSocket connection or protocol failure. The underlying error is on `cause`.
164+
console.log('WebSocket issue:', error.cause);
165+
} else if (error instanceof SMPlatformError) {
166+
// Slack returned an API error. The response is on `data`.
167+
console.log('Platform error:', error.data);
168+
} else if (error instanceof SMSendWhileDisconnectedError) {
169+
// Tried to send a message while the client was disconnected.
170+
console.log('Not connected, will retry...');
171+
}
172+
});
173+
174+
(async () => {
175+
await client.start();
176+
})();
177+
```
178+
179+
Other error classes you might encounter include `SMNoReplyReceivedError` (the server didn't acknowledge a sent message in time) and `SMSendWhileNotReadyError` (a message was sent before the client was fully ready). They all extend `SlackSocketModeError`, so an `instanceof SlackSocketModeError` check catches any of them.
180+
181+
---
182+
147183
### Logging
148184

149185
The `SocketModeClient` will log information to the console by default. You can use the `logLevel` to decide how much or what kind of information should be output. There are a few possible log levels, which you can find in the `LogLevel` export. By default, the value is set to `LogLevel.INFO`. While you're in development, it's sometimes helpful to set this to the most verbose: `LogLevel.DEBUG`.
150186

151187
```javascript
152188
// Import LogLevel from the package
153-
const { SocketModeClient, LogLevel } = require('@slack/socket-mode');
189+
import { SocketModeClient, LogLevel } from '@slack/socket-mode';
154190
const appToken = process.env.SLACK_APP_TOKEN;
155191

156192
// Log level is one of the options you can set in the constructor
@@ -186,7 +222,7 @@ You can also choose to have logs sent to a custom logger using the `logger` opti
186222
A very simple custom logger might ignore the name and level, and write all messages to a file.
187223

188224
```javascript
189-
const { createWriteStream } = require('fs');
225+
import { createWriteStream } from 'node:fs';
190226
const logWritable = createWriteStream('/var/my_log_file'); // Not shown: close this stream
191227

192228
const socketModeClient = new SocketModeClient({

packages/web-api/README.md

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
[![codecov](https://codecov.io/gh/slackapi/node-slack-sdk/graph/badge.svg?token=OcQREPvC7r&flag=web-api)](https://codecov.io/gh/slackapi/node-slack-sdk)
44

55
The `@slack/web-api` package contains a simple, convenient, and configurable HTTP client for making requests to Slack's
6-
[Web API](https://docs.slack.dev/apis/web-api). Use it in your app to call any of the over 130
6+
[Web API](https://docs.slack.dev/apis/web-api). Use it in your app to call any of the over 270
77
[methods](https://docs.slack.dev/reference/methods), and let it handle formatting, queuing, retrying, pagination, and more.
88

99
## Requirements
@@ -37,7 +37,7 @@ begins with `xoxb` or `xoxp`. You get them from each workspace an app is install
3737
help you get your first token for your development workspace.
3838

3939
```javascript
40-
const { WebClient } = require('@slack/web-api');
40+
import { WebClient } from '@slack/web-api';
4141

4242
// Read a token from the environment variables
4343
const token = process.env.SLACK_TOKEN;
@@ -55,7 +55,7 @@ Alternatively, you can create a client without a token, and use it with multiple
5555
`token` when you call a method.
5656

5757
```javascript
58-
const { WebClient } = require('@slack/web-api');
58+
import { WebClient } from '@slack/web-api';
5959

6060
// Initialize a single instance for the whole app
6161
const web = new WebClient();
@@ -137,22 +137,22 @@ call a method, maybe it's been revoked by a user, or maybe you just used a bad a
137137
`Promise` will reject with an `Error`. You should catch the error and use the information it contains to decide how your
138138
app can proceed.
139139

140-
Each error contains a `code` property, which you can check against the `ErrorCode` export to understand the kind of
141-
error you're dealing with. For example, when Slack responds to your app with an error, that is an
142-
`ErrorCode.PlatformError`. These types of errors provide Slack's response body as the `data` property.
140+
Each kind of error is its own class, all extending the `SlackError` base class. Use an `instanceof` check to understand
141+
what kind of error you're dealing with. For example, when Slack responds to your app with an error, that's a
142+
`WebAPIPlatformError`, which provides Slack's response body as the `data` property.
143143

144144
```javascript
145-
// Import ErrorCode from the package
146-
const { WebClient, ErrorCode } = require('@slack/web-api');
145+
// Import the error classes from the package
146+
import { WebClient, WebAPIPlatformError } from '@slack/web-api';
147147

148148
(async () => {
149149

150150
try {
151151
// This method call should fail because we're giving it a bogus user ID to lookup.
152152
const response = await web.users.info({ user: '...' });
153153
} catch (error) {
154-
// Check the code property, and when it's a PlatformError, log the whole response.
155-
if (error.code === ErrorCode.PlatformError) {
154+
// When it's a platform error, log the response Slack sent back.
155+
if (error instanceof WebAPIPlatformError) {
156156
console.log(error.data);
157157
} else {
158158
// Some other error, oh no!
@@ -167,20 +167,14 @@ const { WebClient, ErrorCode } = require('@slack/web-api');
167167
<strong><i>More error types</i></strong>
168168
</summary>
169169

170-
There are a few more types of errors that you might encounter, each with one of these `code`s:
170+
Other error classes you might encounter include the following, though this isn't a complete list. They all extend `SlackError`, so an `instanceof SlackError` check catches any error this package throws.
171171

172-
* `ErrorCode.RequestError`: A request could not be sent. A common reason for this is that your network connection is
173-
not available, or `api.slack.com` could not be reached. This error has an `original` property with more details.
172+
* `WebAPIRequestError`: A request could not be sent. A common reason for this is that your network connection is not available, or `api.slack.com` could not be reached. The underlying error is available on both the standard [`cause`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) property and the `original` property.
174173

175-
* `ErrorCode.RateLimitedError`: The Web API cannot fulfill the API method call because your app has made too many
176-
requests too quickly. This error has a `retryAfter` property with the number of seconds you should wait before trying
177-
again. See [the documentation on rate limit handling](https://docs.slack.dev/tools/node-slack-sdk/web-api/#rate-limits) to
178-
understand how the client will automatically deal with these problems for you.
174+
* `WebAPIRateLimitedError`: The Web API cannot fulfill the API method call because your app has made too many requests too quickly. This error has a `retryAfter` property with the number of seconds you should wait before trying again. See [the documentation on rate limit handling](https://docs.slack.dev/tools/node-slack-sdk/web-api/#rate-limits) to understand how the client will automatically deal with these problems for you.
175+
176+
* `WebAPIHTTPError`: The HTTP response contained an unfamiliar status code. The Web API only responds with `200` (yes, even for errors) or `429` (rate limiting). If you receive this error, it's likely due to a problem with a custom `fetch` implementation or a custom API URL. This error has the `statusCode`, `statusMessage`, `headers`, and `body` properties containing more details.
179177

180-
* `ErrorCode.HTTPError`: The HTTP response contained an unfamiliar status code. The Web API only responds with `200`
181-
(yes, even for errors) or `429` (rate limiting). If you receive this error, it's likely due to a problem with a proxy,
182-
a custom TLS configuration, or a custom API URL. This error has the `statusCode`, `statusMessage`, `headers`, and
183-
`body` properties containing more details.
184178
</details>
185179

186180
---
@@ -262,7 +256,7 @@ in development, it's sometimes helpful to set this to the most verbose: `LogLeve
262256

263257
```javascript
264258
// Import LogLevel from the package
265-
const { WebClient, LogLevel } = require('@slack/web-api');
259+
import { WebClient, LogLevel } from '@slack/web-api';
266260

267261
// Log level is one of the options you can set in the constructor
268262
const web = new WebClient(token, {
@@ -292,7 +286,7 @@ specific methods (known as the `Logger` interface):
292286
A very simple custom logger might ignore the name and level, and write all messages to a file.
293287

294288
```javascript
295-
const { createWriteStream } = require('fs');
289+
import { createWriteStream } from 'node:fs';
296290
const logWritable = createWriteStream('/var/my_log_file'); // Not shown: close this stream
297291

298292
const web = new WebClient(token, {
@@ -321,7 +315,7 @@ You can observe each of the retries in your logs by [setting the log level to DE
321315
following code with your network disconnected, and then re-connect after you see a couple of log messages:
322316

323317
```javascript
324-
const { WebClient, LogLevel } = require('@slack/web-api');
318+
import { WebClient, LogLevel } from '@slack/web-api';
325319

326320
const web = new WebClient('bogus token');
327321

@@ -343,7 +337,7 @@ one that works better for you. The `retryPolicies` export contains a few well kn
343337
your own.
344338

345339
```javascript
346-
const { WebClient, retryPolicies } = require('@slack/web-api');
340+
import { WebClient, retryPolicies } from '@slack/web-api';
347341

348342
const web = new WebClient(token, {
349343
retryConfig: retryPolicies.fiveRetriesInFiveMinutes,
@@ -370,10 +364,8 @@ The [documentation website](https://docs.slack.dev/tools/node-slack-sdk/web-api/
370364
the `WebClient`:
371365

372366
* Upload a file with a `Buffer` or a `ReadableStream`.
373-
* Using a custom agent for proxying
374367
* Rate limit handling
375368
* Request concurrency
376-
* Custom TLS configuration
377369
* Custom API URL
378370
* Exchange an OAuth grant for a token
379371

0 commit comments

Comments
 (0)