1 | # Mainframe JavaScript SDK for bots
|
2 |
|
3 | - [Installation](#installation)
|
4 | - [Example](#example)
|
5 | - [Data types](#types)
|
6 | - [API](#api)
|
7 | - [`createConfig`](#createconfig)
|
8 | - [`createContext`](#createcontext)
|
9 | - [`createRouter`](#createrouter)
|
10 | - [`createServer`](#createserver)
|
11 | - [`log`](#log)
|
12 | - [`startServer`](#startserver)
|
13 | - [Usage](#usage)
|
14 | - [Basic usage](#basic-usage) - the easiest way to get started
|
15 | - [With custom route handlers](#adding-custom-route-handlers) - when you need custom routes
|
16 | - [Using an existing Koa app](#using-an-existing-koa-app) - giving you the flexibility to implement what you need
|
17 | - [License](#license)
|
18 |
|
19 | ## Installation
|
20 |
|
21 | ```sh
|
22 | npm install @mainframe/bot-sdk # npm
|
23 | yarn add @mainframe/bot-sdk # Yarn
|
24 | ```
|
25 |
|
26 | ## Example
|
27 |
|
28 | ```js
|
29 | const { startServer } = require('@mainframe/bot-sdk')
|
30 |
|
31 | startServer(
|
32 | {
|
33 | conversation_added({ conversation_id }, { sendMessage }) {
|
34 | sendMessage({ conversation_id, message: 'Hello world' })
|
35 | },
|
36 | },
|
37 | {
|
38 | mainframe_secret: '<my bot secret>',
|
39 | port: 3000,
|
40 | },
|
41 | )
|
42 | ```
|
43 |
|
44 | ## Types
|
45 |
|
46 | The SDK uses the following [Flow types](https://flow.org/en/docs/types/):
|
47 |
|
48 | ```js
|
49 | type PartialConfig = {
|
50 | +mainframe_secret: string,
|
51 | +mainframe_url: string,
|
52 | +port: number,
|
53 | }
|
54 |
|
55 | type Config = {|
|
56 | +mainframe_secret: string,
|
57 | +mainframe_url: string,
|
58 | +port: number,
|
59 | |}
|
60 |
|
61 | type ClientContext = {|
|
62 | +user: {
|
63 | +id: string,
|
64 | +username: string,
|
65 | +name: string,
|
66 | },
|
67 | +conversation?: {
|
68 | +id: string,
|
69 | +subject: ?string,
|
70 | +type: 'bot' | 'direct' | 'default' | 'space',
|
71 | },
|
72 | +organization?: {
|
73 | +id: string,
|
74 | +username: string,
|
75 | +name: string,
|
76 | },
|
77 | +subscription?: {
|
78 | +id?: string,
|
79 | +token: string,
|
80 | },
|
81 | |}
|
82 |
|
83 | type PostPayload = {|
|
84 | +user_id: string,
|
85 | +data: Object,
|
86 | +context: ClientContext,
|
87 | |}
|
88 |
|
89 | type BotContext = {|
|
90 | +config: Config,
|
91 | +callMainframe: (endpoint: string, data?: Object) => Promise<void | Object>,
|
92 | +sendMessage: (payload: {
|
93 | conversation_id: string,
|
94 | message?: string,
|
95 | data?: Object,
|
96 | }) => Promise<void>,
|
97 | +setupSubscription: (payload: {
|
98 | subscription_token: string,
|
99 | label: string,
|
100 | }) => Promise<{ subscription_id: string }>,
|
101 | +editSubscription: (payload: {
|
102 | subscription_token: string,
|
103 | label?: string,
|
104 | }) => Promise<{ subscription_id: string }>,
|
105 | |}
|
106 |
|
107 | type BotResponse = {|
|
108 | success: boolean,
|
109 | message?: string,
|
110 | data?: Object,
|
111 | |}
|
112 |
|
113 | type Handlers = {|
|
114 | enable?: (payload: { user_id: string }) => void,
|
115 | disable?: (payload: { user_id: string }) => void,
|
116 | conversation_added?: (payload: {
|
117 | user_id: string,
|
118 | conversation_id: string,
|
119 | }) => void,
|
120 | conversation_removed?: (payload: {
|
121 | user_id: string,
|
122 | conversation_id: string,
|
123 | }) => void,
|
124 | edit_subscription?: (payload: {
|
125 | user_id: string,
|
126 | conversation_id: string,
|
127 | subscription_id: string,
|
128 | }) => void,
|
129 | delete_subscription?: (payload: { subscription_id: string }) => void,
|
130 | post?: (payload: PostPayload) => BotResponse | Promise<BotResponse>,
|
131 | |}
|
132 | ```
|
133 |
|
134 | ## API
|
135 |
|
136 | ### createConfig
|
137 |
|
138 | `createConfig (parameters?: PartialConfig): Config`
|
139 |
|
140 | Creates the configuration using the provided parameters, environment variables or defaults.
|
141 |
|
142 | ### createContext
|
143 |
|
144 | `createContext (config: Config): BotContext`
|
145 |
|
146 | Creates a bot context provided to the handlers, notably to allow to communicate with Mainframe.
|
147 |
|
148 | ### createRouter
|
149 |
|
150 | `createRouter (handlers: Handlers, context: BotContext): Router`
|
151 |
|
152 | Creates a [Koa Router](https://github.com/alexmingoia/koa-router#exp_module_koa-router--Router) implementing HTTP endpoints for the provided handlers.
|
153 |
|
154 | ### createServer
|
155 |
|
156 | `createServer (handlers: Handlers, config: Config): koa$Application`
|
157 |
|
158 | Creates a [Koa Application](http://koajs.com/#application) implementing HTTP endpoints for the provided handlers.
|
159 |
|
160 | ### log
|
161 |
|
162 | `log (...args: Array<mixed>): void`
|
163 |
|
164 | Logs using [debug](https://github.com/visionmedia/debug) with the `mainframe-bot` namespace.
|
165 |
|
166 | ### startServer
|
167 |
|
168 | `startServer (handlers: Handlers, parameters?: PartialConfig): void`
|
169 |
|
170 | Creates a [Koa Application](http://koajs.com/#application) implementing HTTP endpoints for the provided handlers and start listening using the `port` provided in `parameters`, defaulting to `4000`.
|
171 |
|
172 | ## Usage
|
173 |
|
174 | ### Basic usage
|
175 |
|
176 | This SDK uses the [Koa framework](http://koajs.com/) to handle routing the provided handlers to the corresponding [HTTP endpoints used by the Mainframe server](http://developer.mainframe.com/#bot-api).
|
177 | All of these handlers are optional by default and you'll only need to implement them according to the needs of your bot.
|
178 |
|
179 | The simplest way to get started it to call `startServer(handlers)`, for example:
|
180 | ```js
|
181 | const { startServer } = require('@mainframe/bot-sdk')
|
182 |
|
183 | startServer({
|
184 | conversation_added(payload, context) {
|
185 | context.sendMessage({
|
186 | conversation_id: payload.conversation_id,
|
187 | message: 'Hello world',
|
188 | })
|
189 | },
|
190 | })
|
191 | ```
|
192 |
|
193 | All handlers will be called with two arguments: an Object containing the request payload, and the [`BotContext`](types) notably allowing to make requests to Mainframe.
|
194 |
|
195 | `startServer()` also supports providing a configuration Object as second argument, used to create the context. When not provided, the configuration will use the environment variables `MAINFRAME_SECRET`, `MAINFRAME_URL` and `PORT`.
|
196 | The configuration will by default use `https://api.mainframe.com/bots/v1` as Mainframe's API URL and listen on port `4000`.
|
197 | Your bot's `secret` **must be** provided, either directly as `mainframe_secret` in the configuration object, or in the `MAINFRAME_SECRET` environment variable.
|
198 |
|
199 | ### Adding custom route handlers
|
200 |
|
201 | For more advanced use cases, you may want to create the Koa application without listening right-away, this is possible using the `createServer(handlers, config)` function, that will return an [`Application instance`](http://koajs.com/#application).
|
202 | This function expects a `config` Object providing all the configuration values. If you want to automatically use the environment variables or default configuration values, you can use `createConfig(optionalConfig)` that will use the values provided in `optionalConfig`, or default to the environment variables or predefined values.
|
203 |
|
204 | Example:
|
205 |
|
206 | ```js
|
207 | const { createConfig, createServer, log } = require('@mainframe/bot-sdk')
|
208 |
|
209 | const config = createConfig({ mainframe_secret: '<your bot secret>' })
|
210 | const server = createServer(
|
211 | {
|
212 | enable(payload) {
|
213 | log('enabled by user %s', payload.user_id)
|
214 | },
|
215 | },
|
216 | config,
|
217 | )
|
218 |
|
219 | server.get('/', (req, res) => {
|
220 | res.send('Hello')
|
221 | })
|
222 |
|
223 | server.listen(3000)
|
224 | ```
|
225 |
|
226 | ### Using an existing Koa app
|
227 |
|
228 | If you are already using Koa and want to integrate the bot API with even more control, you can do so by using the `createRouter(handlers, context)`, that will return a [`Router instance`](https://github.com/alexmingoia/koa-router#exp_module_koa-router--Router).
|
229 | This function requires a [`BotContext`](#types) to be provided as the second argument, that will be injected to the handlers when called. You can provide a custom implementation of the `context` if you have specific needs, or use `createContext(config)` to create it.
|
230 |
|
231 | Example:
|
232 |
|
233 | ```js
|
234 | const { createConfig, createContext, createRouter, log } = require('@mainframe/bot-sdk')
|
235 | const Koa = require('koa')
|
236 |
|
237 | const app = new Koa()
|
238 |
|
239 | const config = createConfig() // Will use MAINFRAME_SECRET from the environment
|
240 | const context = createContext(config)
|
241 |
|
242 | const api = createRouter(
|
243 | {
|
244 | enable(payload) {
|
245 | log('enabled by user %s', payload.user_id)
|
246 | },
|
247 | },
|
248 | context,
|
249 | )
|
250 |
|
251 | app.use(api.routes())
|
252 |
|
253 | app.listen(3000)
|
254 | ```
|
255 |
|
256 | ## License
|
257 |
|
258 | MIT
|
259 | See [LICENSE](LICENSE) file
|