Skip to content

Commit 54a48a5

Browse files
committed
Update to Async/Await
1 parent 4509c0d commit 54a48a5

File tree

7 files changed

+229
-211
lines changed

7 files changed

+229
-211
lines changed

Diff for: .babelrc

+17-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,19 @@
11
{
2+
"presets": [
3+
["env", {
4+
"targets": {
5+
"node": "0.12"
6+
}
7+
}]
8+
],
29
"compact": false,
3-
"presets": ["es2015"],
4-
"auxiliaryCommentBefore": "istanbul ignore next",
5-
"sourceMaps": "inline"
6-
}
10+
"sourceMaps": "inline",
11+
"plugins": [
12+
"transform-async-to-bluebird",
13+
"transform-promise-to-bluebird",
14+
["transform-runtime", {
15+
"polyfill": false,
16+
"regenerator": true
17+
}]
18+
]
19+
}

Diff for: .eslintrc

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ globals:
1717

1818
parserOptions:
1919
sourceType: "module"
20-
20+
ecmaVersion: 8
21+
2122
rules:
2223
# ERRORS
2324
space-before-blocks: 2

Diff for: package.json

+8-2
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,24 @@
3737
"cibuild": "npm run build"
3838
},
3939
"dependencies": {
40+
"babel-preset-env": "^1.5.1",
4041
"babel-preset-es2015": "^6.6.0",
42+
"bluebird": "^3.5.0",
4143
"body-parser": "^1.15.2",
44+
"chai-as-promised": "^7.1.1",
4245
"debug": "^2.2.0",
4346
"express": "^4.14.0",
4447
"jsonwebtoken": "^7.1.9",
4548
"request": "^2.73.0"
4649
},
4750
"devDependencies": {
48-
"babel-cli": "^6.10.1",
4951
"chai": "^3.5.0",
5052
"eslint": "^3.3.0",
51-
"mocha": "^2.5.3"
53+
"mocha": "^2.5.3",
54+
"babel-cli": "^6.24.1",
55+
"babel-plugin-transform-async-to-bluebird": "^1.1.1",
56+
"babel-plugin-transform-promise-to-bluebird": "^1.1.1",
57+
"babel-plugin-transform-runtime": "^6.23.0"
5258
},
5359
"engines": {
5460
"node": ">=6.9.1",

Diff for: src/app.js

+81-91
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,16 @@ import * as https from 'https';
1111
import * as oauth from './oauth';
1212
import * as ssl from './ssl';
1313
import debug from 'debug';
14+
import Promise from 'bluebird';
1415

1516
// Debug log
1617
const log = debug('watsonwork-echo-app');
1718

19+
const post = Promise.promisify(request.post);
20+
1821
// Echoes Watson Work chat messages containing 'hello' or 'hey' back
1922
// to the space they were sent to
20-
export const echo = (appId, token) => (req, res) => {
23+
export const echo = (appId, token) => async (req, res) => {
2124
// Respond to the Webhook right away, as the response message will
2225
// be sent asynchronously
2326
res.status(201).end();
@@ -38,52 +41,49 @@ export const echo = (appId, token) => (req, res) => {
3841
.filter((word) => /^(hello|hey)$/i.test(word)).length)
3942

4043
// Send the echo message
41-
send(req.body.spaceId,
44+
await send(req.body.spaceId,
4245
util.format(
4346
'Hey %s, did you say %s?',
4447
req.body.userName, req.body.content),
45-
token(),
46-
(err, res) => {
47-
if(!err)
48-
log('Sent message to space %s', req.body.spaceId);
49-
});
48+
token());
49+
log('Sent message to space %s', req.body.spaceId);
5050
};
5151

5252
// Send an app message to the conversation in a space
53-
const send = (spaceId, text, tok, cb) => {
54-
request.post(
55-
'https://api.watsonwork.ibm.com/v1/spaces/' + spaceId + '/messages', {
56-
headers: {
57-
Authorization: 'Bearer ' + tok
58-
},
59-
json: true,
60-
// An App message can specify a color, a title, markdown text and
61-
// an 'actor' useful to show where the message is coming from
62-
body: {
63-
type: 'appMessage',
64-
version: 1.0,
65-
annotations: [{
66-
type: 'generic',
53+
const send = async (spaceId, text, tok) => {
54+
let res;
55+
try {
56+
res = await post(
57+
'https://api.watsonwork.ibm.com/v1/spaces/' + spaceId + '/messages', {
58+
headers: {
59+
Authorization: 'Bearer ' + tok
60+
},
61+
json: true,
62+
// An App message can specify a color, a title, markdown text and
63+
// an 'actor' useful to show where the message is coming from
64+
body: {
65+
type: 'appMessage',
6766
version: 1.0,
68-
69-
color: '#6CB7FB',
70-
title: 'Echo message',
71-
text: text,
72-
73-
actor: {
74-
name: 'Sample echo app'
75-
}
76-
}]
77-
}
78-
}, (err, res) => {
79-
if(err || res.statusCode !== 201) {
80-
log('Error sending message %o', err || res.statusCode);
81-
cb(err || new Error(res.statusCode));
82-
return;
83-
}
84-
log('Send result %d, %o', res.statusCode, res.body);
85-
cb(null, res.body);
86-
});
67+
annotations: [{
68+
type: 'generic',
69+
version: 1.0,
70+
71+
color: '#6CB7FB',
72+
title: 'Echo message',
73+
text: text,
74+
75+
actor: {
76+
name: 'Sample echo app'
77+
}
78+
}]
79+
}
80+
});
81+
log('Send result %d, %o', res.statusCode, res.body);
82+
}
83+
catch(err) {
84+
log('Error sending message %o', err);
85+
}
86+
return res;
8787
};
8888

8989
// Verify Watson Work request signature
@@ -113,67 +113,57 @@ export const challenge = (wsecret) => (req, res, next) => {
113113
};
114114

115115
// Create Express Web app
116-
export const webapp = (appId, secret, wsecret, cb) => {
117-
// Authenticate the app and get an OAuth token
118-
oauth.run(appId, secret, (err, token) => {
119-
if(err) {
120-
cb(err);
121-
return;
122-
}
116+
export const webapp = async (appId, secret, wsecret) => {
123117

124-
// Return the Express Web app
125-
cb(null, express()
118+
// Authenticate the app and get an OAuth token
119+
const token = await oauth.run(appId, secret);
126120

127-
// Configure Express route for the app Webhook
128-
.post('/echo',
121+
// Configure Express route for the app Webhook
122+
return express().post('/echo',
129123

130-
// Verify Watson Work request signature and parse request body
131-
bparser.json({
132-
type: '*/*',
133-
verify: verify(wsecret)
134-
}),
124+
// Verify Watson Work request signature and parse request body
125+
bparser.json({
126+
type: '*/*',
127+
verify: verify(wsecret)
128+
}),
135129

136-
// Handle Watson Work Webhook challenge requests
137-
challenge(wsecret),
130+
// Handle Watson Work Webhook challenge requests
131+
challenge(wsecret),
138132

139-
// Handle Watson Work messages
140-
echo(appId, token)));
141-
});
133+
// Handle Watson Work messages
134+
echo(appId, token));
142135
};
143136

144137
// App main entry point
145-
const main = (argv, env, cb) => {
146-
// Create Express Web app
147-
webapp(
148-
env.ECHO_APP_ID, env.ECHO_APP_SECRET,
149-
env.ECHO_WEBHOOK_SECRET, (err, app) => {
150-
if(err) {
151-
cb(err);
152-
return;
153-
}
154-
155-
if(env.PORT) {
156-
// In a hosting environment like Bluemix for example, HTTPS is
157-
// handled by a reverse proxy in front of the app, just listen
158-
// on the configured HTTP port
159-
log('HTTP server listening on port %d', env.PORT);
160-
http.createServer(app).listen(env.PORT, cb);
161-
}
162-
163-
else
164-
// Listen on the configured HTTPS port, default to 443
165-
ssl.conf(env, (err, conf) => {
166-
if(err) {
167-
cb(err);
168-
return;
169-
}
170-
const port = env.SSLPORT || 443;
171-
log('HTTPS server listening on port %d', port);
172-
https.createServer(conf, app).listen(port, cb);
173-
});
174-
});
138+
const main = async (argv, env, cb) => {
139+
try {
140+
// Create Express Web app
141+
const app = await webapp(
142+
env.ECHO_APP_ID, env.ECHO_APP_SECRET,
143+
env.ECHO_WEBHOOK_SECRET);
144+
cb(null);
145+
if(env.PORT) {
146+
// In a hosting environment like Bluemix for example, HTTPS is
147+
// handled by a reverse proxy in front of the app, just listen
148+
// on the configured HTTP port
149+
log('HTTP server listening on port %d', env.PORT);
150+
http.createServer(app).listen(env.PORT, cb);
151+
}
152+
153+
else {
154+
// Listen on the configured HTTPS port, default to 443
155+
const sslConfig = await ssl.conf(env);
156+
const port = env.SSLPORT || 443;
157+
log('HTTPS server listening on port %D', port);
158+
https.createServer(sslConfig, app).listen(port, cb);
159+
}
160+
}
161+
catch(err) {
162+
cb(err);
163+
}
175164
};
176165

166+
177167
if (require.main === module)
178168
main(process.argv, process.env, (err) => {
179169
if(err) {

Diff for: src/oauth.js

+25-23
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,32 @@
11
// Regularly obtain a fresh OAuth token for the app
2-
32
import * as request from 'request';
43
import * as jsonwebtoken from 'jsonwebtoken';
54
import debug from 'debug';
5+
import Promise from 'bluebird';
66

77
// Setup debug log
88
const log = debug('watsonwork-echo-oauth');
99

10+
// Promisify request's post function
11+
const post = Promise.promisify(request.post);
12+
13+
1014
// Obtain an OAuth token for the app, repeat at regular intervals before the
1115
// token expires. Returns a function that will always return a current
1216
// valid token.
13-
export const run = (appId, secret, cb) => {
17+
export const run = async (appId, secret) => {
1418
let tok;
1519

1620
// Return the current token
1721
const current = () => tok;
1822

1923
// Return the time to live of a token
20-
const ttl = (tok) =>
24+
const ttl = (tok) =>
2125
Math.max(0, jsonwebtoken.decode(tok).exp * 1000 - Date.now());
22-
2326
// Refresh the token
24-
const refresh = (cb) => {
27+
const refresh = async () => {
2528
log('Getting token');
26-
request.post('https://api.watsonwork.ibm.com/oauth/token', {
29+
const res = await post('https://api.watsonwork.ibm.com/oauth/token', {
2730
auth: {
2831
user: appId,
2932
pass: secret
@@ -32,28 +35,27 @@ export const run = (appId, secret, cb) => {
3235
form: {
3336
grant_type: 'client_credentials'
3437
}
35-
}, (err, res) => {
36-
if(err || res.statusCode !== 200) {
37-
log('Error getting token %o', err || res.statusCode);
38-
cb(err || new Error(res.statusCode));
39-
return;
40-
}
38+
});
4139

42-
// Save the fresh token
43-
log('Got new token');
44-
tok = res.body.access_token;
40+
// check the status code of the result
41+
if (res.statusCode !== 200)
42+
throw new Error(res.statusCode);
43+
44+
// Save the fresh token
45+
log('Got new token');
46+
tok = res.body.access_token;
4547

46-
// Schedule next refresh a bit before the token expires
47-
const t = ttl(tok);
48-
log('Token ttl', t);
49-
setTimeout(refresh, Math.max(0, t - 60000)).unref();
48+
// Schedule next refresh a bit before the token expires
49+
const t = ttl(tok);
50+
log('Token ttl', t);
51+
setTimeout(refresh, Math.max(0, t - 60000)).unref();
5052

51-
// Return a function that'll return the current token
52-
cb(undefined, current);
53-
});
53+
54+
// return the current token
55+
return current;
5456
};
5557

5658
// Obtain initial token
57-
setImmediate(() => refresh(cb));
59+
return await refresh();
5860
};
5961

0 commit comments

Comments
 (0)