-
Notifications
You must be signed in to change notification settings - Fork 37
Add typescript definition file for public API #52
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// Initialize using verification token from environment variables | ||
import { createSlackEventAdapter } from '@slack/events-api'; | ||
|
||
const { PORT, SLACK_VERIFICATION_TOKEN } = { PORT: 8080, SLACK_VERIFICATION_TOKEN: 'test' }; | ||
|
||
const slackEvents = createSlackEventAdapter(SLACK_VERIFICATION_TOKEN); | ||
|
||
// Attach listeners to events by Slack Event "type". See: https://api.slack.com/events/message.im | ||
slackEvents.on('message', (event) => { | ||
console.log(`Received a message event: user ${event.user} in channel ${event.channel} says ${event.text}`); | ||
}); | ||
|
||
// Handle errors (see `errorCodes` export) | ||
slackEvents.on('error', console.error); | ||
|
||
// Start a basic HTTP server | ||
slackEvents.start(PORT).then(() => { | ||
console.log(`server listening on port ${PORT}`); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
// Type definitions for @slack/events-api 1.0 | ||
// Project: https://github.com/@slack/events-api | ||
// Definitions by: Tate Thurston <https://github.com/tatethurston> | ||
// Definitions: <https://github.com/@slack/events-api> | ||
|
||
import * as express from 'express'; | ||
|
||
export function createSlackEventAdapter(verificationToken: string, options?: SlackEventsApi.Options): SlackEventsApi.Adapter; | ||
|
||
export namespace SlackEventsApi { | ||
interface Options { | ||
includeBody?: boolean; | ||
includeHeaders?: boolean; | ||
waitForResponse?: boolean; | ||
} | ||
|
||
interface Adapter { | ||
expressMiddleware: (opts?: ExpressMiddlewareOptions) => ExpressMiddleware; | ||
start: (port: string | number) => Promise<undefined>; | ||
stop: () => Promise<string>; | ||
on: OnEvent & OnError; | ||
} | ||
|
||
type ExpressMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => void; | ||
|
||
interface ExpressMiddlewareOptions { | ||
propagateErrors?: boolean; | ||
} | ||
|
||
interface Event { | ||
type: EventType; | ||
event_ts: string; | ||
// TODO: More constrained shape for the events | ||
// There is conflicting information between | ||
// https://api.slack.com/events-api#event_type_structure and individual | ||
// events. | ||
user?: string; | ||
ts?: string; | ||
item?: any; | ||
[key: string]: any; | ||
} | ||
|
||
interface EventError { | ||
code: ErrorCode; | ||
message: string; | ||
body: object; | ||
} | ||
|
||
type OnEvent = (event: EventType, Handler: EventHandler) => void; | ||
type OnError = (event: "error", Handler: ErrorHandler) => void; | ||
|
||
type EventHandler = ( | ||
event: Event, | ||
body?: SlackEvent, | ||
// TODO: More constrained types for headers and respond | ||
headers?: any, | ||
respond?: any | ||
) => void; | ||
|
||
type ErrorHandler = (error: EventError) => void; | ||
|
||
interface SlackEvent { | ||
token: string; | ||
team_id: string; | ||
api_app_id: string; | ||
event: Event; | ||
type: "event_callback" | "url_verification"; | ||
authed_users: string[]; | ||
event_id: string; | ||
event_time: number; | ||
} | ||
|
||
type ErrorCode = | ||
"SLACKEVENTMIDDLEWARE_NO_BODY_PARSER" | | ||
"SLACKEVENTMIDDLEWARE_TOKEN_VERIFICATION_FAILURE"; | ||
|
||
type EventType = | ||
"app_uninstalled" | | ||
"channel_archive" | | ||
"channel_created" | | ||
"channel_deleted" | | ||
"channel_history_changed" | | ||
"channel_rename" | | ||
"channel_unarchive" | | ||
"dnd_updated" | | ||
"dnd_updated_user" | | ||
"email_domain_changed" | | ||
"emoji_changed" | | ||
"file_change" | | ||
"file_comment_added" | | ||
"file_comment_deleted" | | ||
"file_comment_edited" | | ||
"file_created" | | ||
"file_deleted" | | ||
"file_public" | | ||
"file_shared" | | ||
"file_unshared" | | ||
"grid_migration_finished" | | ||
"grid_migration_started" | | ||
"group_archive" | | ||
"group_close" | | ||
"group_history_changed" | | ||
"group_open" | | ||
"group_rename" | | ||
"group_unarchive" | | ||
"im_close" | | ||
"im_created" | | ||
"im_history_changed" | | ||
"im_open" | | ||
"link_shared" | | ||
"member_joined_channel" | | ||
"member_left_channel" | | ||
"message" | | ||
"message.channels" | | ||
"message.groups" | | ||
"message.im" | | ||
"message.mpim" | | ||
"pin_added" | | ||
"pin_removed" | | ||
"reaction_added" | | ||
"reaction_removed" | | ||
"resources_added" | | ||
"resources_removed" | | ||
"scope_denied" | | ||
"scope_granted" | | ||
"star_added" | | ||
"star_removed" | | ||
"subteam_created" | | ||
"subteam_members_changed" | | ||
"subteam_self_added" | | ||
"subteam_self_removed" | | ||
"subteam_updated" | | ||
"team_domain_change" | | ||
"team_join" | | ||
"team_rename" | | ||
"tokens_revoked" | | ||
"url_verification" | | ||
"user_change"; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. its an interesting choice to essentially deliver the types in a separate package. i'm not certain what the advantages are to this approach over simply adding an is the intention that we would publish two separate modules to npm? if so, i think that would be confusing, and at that point we might as well only offer ambient declarations via DefinitelyTyped. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Typescript's publishing documentation suggests publishing to the @types organization on npm if the package is not written in TypeScript. I believe the intent is to avoid shipping type definitions to those who don't need them. That said, I'm happy to instead add |
||
"name": "@slack/events-api-types", | ||
"version": "1.0.0", | ||
"description": "Slack Events API Typescript definitions", | ||
"main": "index.js", | ||
"scripts": { | ||
"lint": "tslint index.d.ts", | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"author": "[email protected] <[email protected]>", | ||
"license": "ISC", | ||
"devDependencies": { | ||
"@types/express": "^4.11.0", | ||
"@types/node": "^8.5.2", | ||
"dtslint": "^0.2.0", | ||
"tslint": "^5.8.0", | ||
"typescript": "^2.6.2" | ||
}, | ||
"dependencies": { | ||
"@slack/events-api": "git://github.com/tatethurston/node-slack-events-api.git#typescript-definitions" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
{ | ||
"compilerOptions": { | ||
"module": "commonjs", | ||
"lib": [ | ||
"es6" | ||
], | ||
"noImplicitAny": true, | ||
"noImplicitThis": true, | ||
"strictNullChecks": true, | ||
"baseUrl": "../../", | ||
"noEmit": true, | ||
"forceConsistentCasingInFileNames": true | ||
}, | ||
"files": [ | ||
"index.d.ts", | ||
"events-api-tests.ts" | ||
] | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
{ "extends": "dtslint/dt.json" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i have some apprehension to committing an exhaustive list of event types into this repo. these values are bound to change over time, and that means developers would have to deal with a compiler error if an up to date set is not available. we came up with a technique to allow flexibility using generics in this issue. i'd prefer a solution that allowed unknown event types to work without a compiler error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, if that's a goal then we could union String at the end or simply define EventType as a string.