Skip to main content
Deno 2 is finally here 🎉️
Learn more
blueprint illustration

Slack Bolt

TypeScript framework to build Slack apps in a flash with the latest platform features. Deno port of @slack/bolt

build status language code size issues license version

View on deno.land

Slack Bolt for Deno - TypeScript framework to build Slack apps with Deno rapidly | Product Hunt




Table of Contents

Usage

import "https://deno.land/x/dotenv@v2.0.0/load.ts"
import { App } from "https://deno.land/x/slack_bolt@1.0.0/mod.ts"

const app = new App({
    signingSecret: Deno.env.get("SLACK_SIGNING_SECRET"),
    token: Deno.env.get("SLACK_BOT_TOKEN"),
    ignoreSelf: true,
})

app.event("message", async ({ event, say }) => {
    console.log(event)
    await say("pong")
})

await app.start({ port: 3000 })
console.log("🦕 ⚡️")

API

Quirks

OpineReciever and HTTPReceiver/SocketModeReciever req/res types are not compatible. This causes trouble when providing a custom callback for built-in oauth failure / success (if you’re not using built-in oauth / not implementing custom callbacks for failure / success, you don’t have to worry about this). This requires a type guard (See simpler alternative below).

import { ServerRequest } from "https://deno.land/std@0.87.0/http/server.ts"
import {
    ParamsDictionary,
    Request as OpineRequest,
    Response as OpineResponse,
} from "https://deno.land/x/opine@1.1.0/mod.ts"

const customCallbackOptions = {
    failure: async (
        req: ServerRequest | OpineRequest<ParamsDictionary, any, any>,
        res?: OpineResponse<any>,
    ) => {
        if (isOpineRequest(req)) {
            // Your custom code here, req is Request<ParamsDictionary, any, any> and res is Response<any> from deno.land/x/opine
            // Example:
            res?.setStatus(500).send(
                "<html><body><h1>OAuth failed!</h1><div>See stderr for errors.</div></body></html>",
            )
        } else {
            // Your custom code here, req is a std/http ServerRequest, res is undefined
            // Example:
            await req.respond({
                status: 500,
                headers: new Headers({
                    "Content-Type": "text/html",
                }),
                body:
                    `<html><body><h1>OAuth failed!</h1><div></div></body></html>`,
            })
        }

        function isOpineRequest(
            _req: ServerRequest | OpineRequest<ParamsDictionary, any, any>,
            res?: OpineResponse<any>,
        ): _req is OpineRequest<ParamsDictionary, any, any> {
            return !!res // If res exists, OpineReciever is being used since only 'req' exists for HTTPReciever and SocketModeReceiver
        }
    },
}

Alternatively, just specify the correct type according to your Receiver (if you don’t specify this, its HTTPReceiver by default)

  • For HTTPReceiver (default) / SocketModeReceiver
import { ServerRequest } from "https://deno.land/std@0.87.0/http/server.ts"
const customCallbackOptions = {
    failure: async (req: ServerRequest) => {
        // Your custom code here
        // Example:
        await req.respond({
            status: 500,
            headers: new Headers({
                "Content-Type": "text/html",
            }),
            body: `<html><body><h1>OAuth failed!</h1><div></div></body></html>`,
        })
    },
}
  • For OpineReceiver
import {
    ParamsDictionary,
    Request as OpineRequest,
    Response as OpineResponse,
} from "https://deno.land/x/opine@1.1.0/mod.ts"

const customCallbackOptions = {
    failure: async (
        req: OpineRequest<ParamsDictionary, any, any>,
        res: OpineResponse<any>,
    ) => {
        // Your custom code here, req is Request<ParamsDictionary, any, any> and res is Response<any> from deno.land/x/opine
        // Example:
        res?.setStatus(500).send(
            "<html><body><h1>OAuth failed!</h1><div>See stderr for errors.</div></body></html>",
        )
    },
}

Supporters

Stargazers repo roster for @khrj/slack-bolt

Forkers repo roster for @khrj/slack-bolt