Skip to content

Commit

Permalink
version 0.10.10
Browse files Browse the repository at this point in the history
  • Loading branch information
seratch committed Apr 18, 2024
1 parent e8d9fbb commit 1cd15a9
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 70 deletions.
53 changes: 1 addition & 52 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,58 +181,7 @@ cloudflared tunnel --url http://localhost:3000

#### Run with Deno

```typescript
import { SlackApp, SlackEdgeAppEnv } from "https://deno.land/x/slack_edge@0.10.9/mod.ts";

const app = new SlackApp<SlackEdgeAppEnv>({
env: {
SLACK_SIGNING_SECRET: Deno.env.get("SLACK_SIGNING_SECRET")!,
SLACK_BOT_TOKEN: Deno.env.get("SLACK_BOT_TOKEN"),
SLACK_LOGGING_LEVEL: "DEBUG",
},
});

// Add listeners here

await Deno.serve({ port: 3000 }, async (request) => {
return await app.run(request);
});
```

You can run the app by:

```bash
# Terminal A
deno run --watch --allow-net --allow-env my-app.ts
# Terminal B
brew install cloudflare/cloudflare/cloudflared
cloudflared tunnel --url http://localhost:3000
```

#### Run with Deno (Socket Mode: Experimental)

**Important Notice:** The Socket Mode support provided by slack-edge is still experimental and is not designed to handle reconnections for production-grade applications. It is recommended to use this mode only for local development and testing purposes.

Thanks to Deno's built-in WebSocket implementation, you can quickly and easily run a Socket Mode app as below:

```typescript
import { SlackApp, SlackSocketModeAppEnv } from "https://deno.land/x/slack_edge@0.10.9/mod.ts";

const app = new SlackApp<SlackSocketModeAppEnv>({
env: {
SLACK_APP_TOKEN: Deno.env.get("SLACK_APP_TOKEN")!,
SLACK_BOT_TOKEN: Deno.env.get("SLACK_BOT_TOKEN"),
SLACK_LOGGING_LEVEL: "DEBUG",
},
});

// Add listeners here

await app.connect();
setTimeout(() => {}, Number.MAX_SAFE_INTEGER);
```

You can run this app by `deno run --watch --allow-net --allow-env my-app.ts`.
Please refer to [README for the Deno module](https://github.com/seratch/slack-edge/blob/main/src_deno/README.md).


#### Run with Node.js (Socket Mode: Production-ready)
Expand Down
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "slack-edge",
"version": "0.10.9",
"version": "0.10.10",
"description": "Slack app development framework for edge functions with streamlined TypeScript support",
"main": "dist/index.js",
"scripts": {
Expand Down Expand Up @@ -34,7 +34,7 @@
},
"homepage": "https://github.com/seratch/slack-edge#readme",
"dependencies": {
"slack-web-api-client": "^0.10.1"
"slack-web-api-client": "^0.10.5"
},
"devDependencies": {
"@vitest/coverage-v8": "^1.5.0",
Expand Down
2 changes: 1 addition & 1 deletion scripts/deno_source_formatter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
response = Net::HTTP.get_response(URI.parse(web_api_client_url))
latest_web_api_client_url = "https://deno.land#{response['location']}"

Dir.glob(__dir__ + '/../src_deno/**/*').select { |f| File.file? f }.each do |filepath|
Dir.glob(__dir__ + '/../src_deno/**/*.ts').select { |f| File.file? f }.each do |filepath|
output = "";
File.readlines(filepath).each do |line|
if line.include?(' from "')
Expand Down
20 changes: 11 additions & 9 deletions scripts/generate-deno-source.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ src_dir=${script_dir}/../src
src_deno_dir=${script_dir}/../src_deno

npm run format && \
rm -rf ${src_deno_dir}/* && \
cp -pr ${src_dir}/* ${src_deno_dir}/ && \
cd ${script_dir} && \
ruby ./deno_source_formatter.rb && \
cd - && \
cd ${src_deno_dir} && \
deno fmt && \
deno lint && \
deno check ./mod.ts
cp -p ${src_deno_dir}/README.md deno_README.md && \
rm -rf ${src_deno_dir}/* && \
cp -pr ${src_dir}/* ${src_deno_dir}/ && \
mv ./deno_README.md ${src_deno_dir}/README.md && \
cd ${script_dir} && \
ruby ./deno_source_formatter.rb && \
cd - && \
cd ${src_deno_dir} && \
deno fmt && \
deno lint && \
deno check ./mod.ts
135 changes: 135 additions & 0 deletions src_deno/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
## Slack Edge

The **slack-edge** library is a Slack app development framework designed
specifically for the following runtimes:

- [Cloudflare Workers](https://workers.cloudflare.com/)
- [Vercel Edge Functions](https://vercel.com/docs/concepts/functions/edge-functions/quickstart)

Not only does it work with the above, but it also functions with the latest
versions of [Deno](https://deno.com/), [Bun](https://bun.sh/), and
[Node.js](https://nodejs.org/en/about).

This framework draws significant inspiration from Slack's
[Bolt framework](https://api.slack.com/tools/bolt), but its design does not
strictly follow the [bolt-js](https://github.com/slackapi/bolt-js) blueprint.
Key differences include:

- **Edge function ready**: Out-of-the-box edge function (e.g., Cloudflare
Workers) support
- **TypeScript focused**: Enhances type safety and clarifies typings for
developers
- **Lazy listener enabled**:
[bolt-python's lazy listener feature](https://slack.dev/bolt-python/concepts#lazy-listeners)
is provided out of the box
- **Zero additional dependencies**: No other dependencies required beyond
TypeScript types and
[slack-web-api-client](https://github.com/seratch/slack-web-api-client) (our
fetch-function-based Slack API client)

## Getting Started

### Run with Deno

```typescript
import {
SlackApp,
SlackEdgeAppEnv,
} from "https://deno.land/x/slack_edge@0.10.10/mod.ts";

const app = new SlackApp<SlackEdgeAppEnv>({
env: {
SLACK_SIGNING_SECRET: Deno.env.get("SLACK_SIGNING_SECRET")!,
SLACK_BOT_TOKEN: Deno.env.get("SLACK_BOT_TOKEN"),
SLACK_LOGGING_LEVEL: "DEBUG",
},
});

// Add listeners here

await Deno.serve({ port: 3000 }, async (request) => {
return await app.run(request);
});
```

You can run the app by:

```bash
# Terminal A
deno run --watch --allow-net --allow-env my-app.ts
# Terminal B
brew install cloudflare/cloudflare/cloudflared
cloudflared tunnel --url http://localhost:3000
```

### Run with Deno (Socket Mode: Experimental)

**Important Notice:** The Socket Mode support provided by slack-edge is still
experimental and is not designed to handle reconnections for production-grade
applications. It is recommended to use this mode only for local development and
testing purposes.

Thanks to Deno's built-in WebSocket implementation, you can quickly and easily
run a Socket Mode app as below:

```typescript
import {
SlackApp,
SlackSocketModeAppEnv,
} from "https://deno.land/x/slack_edge@0.10.10/mod.ts";

const app = new SlackApp<SlackSocketModeAppEnv>({
env: {
SLACK_APP_TOKEN: Deno.env.get("SLACK_APP_TOKEN")!,
SLACK_BOT_TOKEN: Deno.env.get("SLACK_BOT_TOKEN"),
SLACK_LOGGING_LEVEL: "DEBUG",
},
});

// Add listeners here

await app.connect();
setTimeout(() => {}, Number.MAX_SAFE_INTEGER);
```

You can run this app by `deno run --watch --allow-net --allow-env my-app.ts`.

### Reference

#### Middleware

This framework offers ways to globally customize your app's behavior, like you
do when developing web apps. A common example is to attach extra data to the
`context` object for following listeners.

| Pattern | Description |
| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| app.beforeAuthorize | The passed function does something before calling `authorize()` function. If this method returns `SlackResponse`, the following middleware and listeners won't be executed. |
| app.afterAuthorize / app.use / app.middleware | The passed function does something right after calling `authorize()` function. If this method returns `SlackResponse`, the following middleware and listeners won't be executed. |

#### `ack` / `lazy` Functions

You may be unfamiliar with the "lazy listener" concept in this framework. To
learn more about it, please read bolt-python's documentation:
https://slack.dev/bolt-python/concepts#lazy-listeners

The `ack` function must complete within 3 seconds, while the `lazy` function can
perform time-consuming tasks. It's important to note that not all request
handlers support the ack or lazy functions. For more information, please refer
to the following table, which covers all the patterns in detail.

Starting from v0.9, if desired, you can execute lazy listeners after the
completion of their ack function. To customize the behavior in this manner, you
can pass `startLazyListenerAfterAck: true` as one of the arguments in the `App`
constructor.

| Pattern | Description | `ack` function | `lazy` function |
| ------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------- | --------------- |
| app.command | The passed function handles a slash command request pattern. If the function returns a message, the message will be posted in the channel where the end-user invoked the command. |||
| app.event | The passed function asynchronously does something when an Events API request that matches the constraints comes in. Please note that manually acknowledge a request is unsupported. You can pass only one function, which can be executed as a lazy listener. | x ||
| app.function [**experimental**] | The passed function asynchronously does something when a "function_executed" event request that matches the constraints comes in. Please note that manually acknowledge a request is unsupported. You can pass only one function, which can be executed as a lazy listener. Also, this feature is still in beta so that the details could be changed on the Slack plaform side until it's GAed. | x ||
| app.message / app.anyMessage | The passed function asynchronously does something when an a message event comes in. Please note that manually acknowledge a request is unsupported. You can pass only one function, which can be executed as a lazy listener. If the message pattern argument can be any of string, regexp, and undefined. When you pass undefined, the listener matches all messages. | x ||
| app.shortcut / app.globalShortcut / app.messageShortcut | The passed function handles a global/message shortcut request pattern. Please note that returning a message text in the `ack` function does not work for shortcuts. Instead, you can use `context.respond` for it. |||
| app.action | The passed function handles a user interaction on a Block Kit component such as button clicks, item selection in a select menu, and so on. |||
| app.options | The passed function handles an external data source reqeust for Block Kit select menus. You cannnot respond to this request pattern asynchronously, so slack-edge enables developers to pass only `ack` function, which must complete within 3 seconds, here. || x |
| app.view / app.viewSubmission / app.viewClosed | The passed function handles either a modal data submission or the "Close" button click event. `ack` function can return various `response_action`s (errors, update, push, clear) and their associated data. If you want to simply close the modal, you don't need to return anything. |||

0 comments on commit 1cd15a9

Please sign in to comment.