From 0b56f25c48934dbdec4d9ee464a57e31f70d1b25 Mon Sep 17 00:00:00 2001 From: Steve Gill Date: Wed, 25 Mar 2020 16:43:07 -0700 Subject: [PATCH 1/2] added migration guide for V2 --- docs/_advanced/error_handling.md | 4 +- docs/_advanced/middleware_global.md | 2 + docs/_advanced/middleware_listener.md | 1 + docs/_basic/listening_actions.md | 1 + docs/_tutorials/hubot_migration.md | 2 +- docs/_tutorials/migration_v2.md | 122 ++++++++++++++++++++++++++ 6 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 docs/_tutorials/migration_v2.md diff --git a/docs/_advanced/error_handling.md b/docs/_advanced/error_handling.md index b2e989ae3..494bdef9c 100644 --- a/docs/_advanced/error_handling.md +++ b/docs/_advanced/error_handling.md @@ -6,9 +6,9 @@ order: 1 ---
-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 `Bolt@2.x`, error handling has improved! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn more.* -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 `error(fn)` method.
```javascript diff --git a/docs/_advanced/middleware_global.md b/docs/_advanced/middleware_global.md index b4b7ecf30..0b05d3034 100644 --- a/docs/_advanced/middleware_global.md +++ b/docs/_advanced/middleware_global.md @@ -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 `Bolt@2.x`, global middleware was updated to support `async` functions! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn more.* ```javascript diff --git a/docs/_advanced/middleware_listener.md b/docs/_advanced/middleware_listener.md index 8a216df5b..f9971d8ec 100644 --- a/docs/_advanced/middleware_listener.md +++ b/docs/_advanced/middleware_listener.md @@ -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 `Bolt@2.x`, listener middleware was updated to support `async` functions! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn more.* ```javascript diff --git a/docs/_basic/listening_actions.md b/docs/_basic/listening_actions.md index c611d473e..667e978a8 100644 --- a/docs/_basic/listening_actions.md +++ b/docs/_basic/listening_actions.md @@ -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 `Bolt@2.x`, 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 more.* ```javascript diff --git a/docs/_tutorials/hubot_migration.md b/docs/_tutorials/hubot_migration.md index 010693206..33ec8ceb7 100644 --- a/docs/_tutorials/hubot_migration.md +++ b/docs/_tutorials/hubot_migration.md @@ -1,6 +1,6 @@ --- title: Migrating Hubot apps -order: 1 +order: 2 slug: hubot-migration lang: en layout: tutorial diff --git a/docs/_tutorials/migration_v2.md b/docs/_tutorials/migration_v2.md new file mode 100644 index 000000000..127d00f53 --- /dev/null +++ b/docs/_tutorials/migration_v2.md @@ -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 + +
+This guide will walk you through the process of updating your app from using `bolt@v1.x` to `bolt@2.x`. +
+ +--- + +## 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); +}); +``` + +Other error related changes include: + +- When your listener doesn’t call `ack` within the 3 section time limit, we log the failure instead of throwing an error. +- If you have multiple errors at once when running middleware, Bolt for Javascript will return a wrapper error with a `code` parameter of `slack_bolt_multiple_listener_error` and an `original` parameter that contains an array of all of the 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('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 + } +} +``` \ No newline at end of file From f9c07d9168b7d7a87fb2de174572048ed42913da Mon Sep 17 00:00:00 2001 From: Steve Gill Date: Thu, 26 Mar 2020 10:25:04 -0700 Subject: [PATCH 2/2] Apply suggestions from code review Co-Authored-By: Ankur Oberoi --- docs/_advanced/error_handling.md | 6 +++--- docs/_advanced/middleware_global.md | 2 +- docs/_advanced/middleware_listener.md | 2 +- docs/_basic/listening_actions.md | 2 +- docs/_tutorials/migration_v2.md | 10 +++++----- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/_advanced/error_handling.md b/docs/_advanced/error_handling.md index 494bdef9c..ff755a528 100644 --- a/docs/_advanced/error_handling.md +++ b/docs/_advanced/error_handling.md @@ -6,9 +6,9 @@ order: 1 ---
-*Note: Since `Bolt@2.x`, error handling has improved! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn more.* +*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 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 `error(fn)` method. +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.
```javascript @@ -16,4 +16,4 @@ 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); }); -``` \ No newline at end of file +``` diff --git a/docs/_advanced/middleware_global.md b/docs/_advanced/middleware_global.md index 0b05d3034..ede26e53b 100644 --- a/docs/_advanced/middleware_global.md +++ b/docs/_advanced/middleware_global.md @@ -12,7 +12,7 @@ Both global and listener middleware must call `await next()` to pass control of 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 `Bolt@2.x`, global middleware was updated to support `async` functions! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn more.* +*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.* ```javascript diff --git a/docs/_advanced/middleware_listener.md b/docs/_advanced/middleware_listener.md index f9971d8ec..8846a97ba 100644 --- a/docs/_advanced/middleware_listener.md +++ b/docs/_advanced/middleware_listener.md @@ -14,7 +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 `Bolt@2.x`, listener middleware was updated to support `async` functions! View the [migration guide for V2](https://slack.dev/bolt/tutorial/migration-v2) to learn more.* +*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.* ```javascript diff --git a/docs/_basic/listening_actions.md b/docs/_basic/listening_actions.md index 667e978a8..03546733d 100644 --- a/docs/_basic/listening_actions.md +++ b/docs/_basic/listening_actions.md @@ -12,7 +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 `Bolt@2.x`, 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 more.* +*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.* ```javascript diff --git a/docs/_tutorials/migration_v2.md b/docs/_tutorials/migration_v2.md index 127d00f53..65f081d75 100644 --- a/docs/_tutorials/migration_v2.md +++ b/docs/_tutorials/migration_v2.md @@ -9,7 +9,7 @@ permalink: /tutorial/migration-v2 # Migrating to v2.x
-This guide will walk you through the process of updating your app from using `bolt@v1.x` to `bolt@2.x`. +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.
--- @@ -66,8 +66,8 @@ app.error((error) => { Other error related changes include: -- When your listener doesn’t call `ack` within the 3 section time limit, we log the failure instead of throwing an error. -- If you have multiple errors at once when running middleware, Bolt for Javascript will return a wrapper error with a `code` parameter of `slack_bolt_multiple_listener_error` and an `original` parameter that contains an array of all of the errors. +- 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 @@ -77,7 +77,7 @@ Other error related changes include: Before: ```javascript -app.action('message-action-callback', ({action, ack, context}) => { +app.action({ callback_id: 'message-action-callback' }, ({action, ack, context}) => { ack(); // Do stuff }) @@ -119,4 +119,4 @@ async function noBotMessages({ message, next }) { // Post processing goes here } } -``` \ No newline at end of file +```