Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added migration guide for Bolt@2.x #442

Merged
merged 2 commits into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions docs/_advanced/error_handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@ order: 1
---

<div class="section-content">
If an error occurs in a listener, it’s recommended you handle it directly. However, there are cases where errors may be triggered after your listener has already returned (such as in `say()`, `respond()`, or if you don't call `ack()` when it's required). By default, these errors will be logged to the console. To handle them yourself, you can attach a global error handler to your app with the `error(fn)` method.
*Note: Since v2, error handling has improved! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn about the changes.*

If you want more control over errors, it’s advised to use the [`chat.postMessage`](https://api.slack.com/methods/chat.postMessage) method attached to your app under the `client` key (instead of `say()` or `respond()`). This returns a `Promise` that can be caught to handle the error.
If an error occurs in a listener, it’s recommended you handle it directly with a `try`/`catch`. However, there still may be cases where errors slip through the cracks. By default, these errors will be logged to the console. To handle them yourself, you can attach a global error handler to your app with the `app.error(fn)` method.
</div>

```javascript
app.error((error) => {
// Check the details of the error to handle cases where you should retry sending a message or stop the app
console.error(error);
});
```
```
2 changes: 2 additions & 0 deletions docs/_advanced/middleware_global.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Global middleware is run for all incoming events before any listener middleware.
Both global and listener middleware must call `await next()` to pass control of the execution chain to the next middleware, or call `throw` to pass an error back up the previously-executed middleware chain.

As an example, let's say your app should only respond to users identified with a corresponding internal authentication service (an SSO provider or LDAP, for example). You may define a global middleware that looks up a user record in the authentication service and errors if the user is not found.

*Note: Since v2, global middleware was updated to support `async` functions! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn about the changes.*
</div>

```javascript
Expand Down
1 change: 1 addition & 0 deletions docs/_advanced/middleware_listener.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ But of course, you can write your own middleware for more custom functionality.

As an example, let’s say your listener should only deal with messages from humans. You can write a listener middleware that excludes any bot messages.

*Note: Since v2, listener middleware was updated to support `async` functions! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn about the changes.*
</div>

```javascript
Expand Down
1 change: 1 addition & 0 deletions docs/_basic/listening_actions.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ Actions can be filtered on an `action_id` of type string or RegExp object. `acti

You’ll notice in all `action()` examples, `ack()` is used. It is required to call the `ack()` function within an action listener to acknowledge that the event was received from Slack. This is discussed in the [acknowledging events section](#acknowledge).

*Note: Since v2, message shortcuts (previously message actions) now use the `shortcut()` method instead of the `action()` method. View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn about the changes.*
</div>

```javascript
Expand Down
2 changes: 1 addition & 1 deletion docs/_tutorials/hubot_migration.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Migrating Hubot apps
order: 1
order: 2
slug: hubot-migration
lang: en
layout: tutorial
Expand Down
122 changes: 122 additions & 0 deletions docs/_tutorials/migration_v2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
---
title: Migrating to V2
order: 1
slug: migration-v2
lang: en
layout: tutorial
permalink: /tutorial/migration-v2
---
# Migrating to v2.x

<div class="section-content">
This guide will walk you through the process of updating your app from using `@slack/bolt@1.x` to `@slack/bolt@2.x`. There are a few changes you'll need to make but for most apps, these changes can be applied in 5 - 15 minutes.
</div>

---

## Upgrading your listeners to `async`

Listeners in your app should updated to `async` functions and `say()`, `respond()`, and `ack()` should be prefaced with `await`.

Before:

```javascript
app.action('some-action-id', ({action, ack, say}) => {
ack();
say('hello world');
})
```

After:

```javascript
app.action('some-action-id', async ({action, ack, say}) => {
await ack();
await say('hello world');
})
```


## Error Handling

The recent changes in Bolt for JavaScript V2 have improved our ability to catch errors and filter them to the global error handler. It is still recommended to manage errors in the listeners themselves instead of letting them propagate to the global handler when possible.

### Handling Errors in Listeners with `try`/`catch`

```javascript
app.action('some-action-id', async ({action, ack, say, logger}) => {
try {
await ack();
await say('hello world');
} catch (error) {
logger.error(error);
// handle error
}
})
```

### Handling Errors with the Global Error Handler

```javascript
app.error((error) => {
// Check the details of the error to handle cases where you should retry sending a message or stop the app
console.error(error);
stevengill marked this conversation as resolved.
Show resolved Hide resolved
});
```

Other error related changes include:

- When your listener doesn’t call `ack` within the 3 second time limit, we log the failure instead of throwing an error.
- If multiple errors occur when processing multiple listeners for a single event, Bolt for Javascript will return a wrapper error with a `code` property of `ErrorCode.MultipleListenerError` and an `originals` property that contains an array of the individual errors.


## Message Shortcuts

[Message shortcuts](https://api.slack.com/interactivity/shortcuts/using#message_shortcuts) (previously referred to as message actions) now use the `shortcut()` method instead of the `action()` method.

Before:

```javascript
app.action({ callback_id: 'message-action-callback' }, ({action, ack, context}) => {
ack();
// Do stuff
})
```

After:

```javascript
app.shortcut('message-action-callback', async ({shortcut, ack, context}) => {
await ack();
// Do stuff
})
```

## Upgrading Middleware

If you wrote a custom middleware, adjust your function to `async` and update `next()` to `await next()`. If your middleware does some post processing, instead of passing a function to `next()`, you can now run it after `await next()`.

Before:

```javascript
function noBotMessages({ message, next }) {
function doAfter() {
// Post processing goes here
}

if (!message.subtype || message.subtype !== 'bot_message') {
next(doAfter);
}
}
```

After:

```javascript
async function noBotMessages({ message, next }) {
if (!message.subtype || message.subtype !== 'bot_message') {
await next();
// Post processing goes here
}
}
```