Skip to content
This repository was archived by the owner on Mar 10, 2020. It is now read-only.

Commit 621973c

Browse files
author
Alan Shaw
authored
refactor: convert config API to async await (#1155)
BREAKING CHANGE: Errors returned from request failures are now all [`HTTPError`](https://github.com/sindresorhus/ky/blob/c0d9d2bb07e4c122a08f019b39e9c55a4c9324f3/index.js#L117-L123)s which carry a `response` property. This is a [`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) that can be used to inspect _all_ information relating to the HTTP response. This means that the `err.status` or `err.statusCode` property should now be accessed via `err.response.status`. License: MIT Signed-off-by: Alan Shaw <alan.shaw@protocol.ai>
1 parent 14c5b9e commit 621973c

File tree

11 files changed

+106
-116
lines changed

11 files changed

+106
-116
lines changed

src/config/get.js

+21-33
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,27 @@
11
'use strict'
22

3-
const promisify = require('promisify-es6')
3+
const configure = require('../lib/configure')
44

5-
const toObject = function (res, callback) {
6-
if (Buffer.isBuffer(res)) {
7-
callback(null, JSON.parse(res.toString()))
8-
} else {
9-
callback(null, res)
10-
}
11-
}
12-
13-
module.exports = (send) => {
14-
return promisify((key, callback) => {
15-
if (typeof key === 'function') {
16-
callback = key
17-
key = undefined
5+
module.exports = configure(({ ky }) => {
6+
return async (key, options) => {
7+
if (key && typeof key === 'object') {
8+
options = key
9+
key = null
1810
}
1911

20-
if (!key) {
21-
send.andTransform({
22-
path: 'config/show',
23-
buffer: true
24-
}, toObject, callback)
25-
return
26-
}
12+
options = options || {}
2713

28-
send.andTransform({
29-
path: 'config',
30-
args: key,
31-
buffer: true
32-
}, toObject, (err, response) => {
33-
if (err) {
34-
return callback(err)
35-
}
36-
callback(null, response.Value)
37-
})
38-
})
39-
}
14+
const searchParams = new URLSearchParams(options.searchParams)
15+
if (key) searchParams.set('arg', key)
16+
17+
const url = key ? 'config' : 'config/show'
18+
const data = await ky.get(url, {
19+
timeout: options.timeout,
20+
signal: options.signal,
21+
headers: options.headers,
22+
searchParams
23+
}).json()
24+
25+
return key ? data.Value : data
26+
}
27+
})

src/config/index.js

+8-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
'use strict'
22

3-
module.exports = (send, config) => {
4-
return {
5-
get: require('./get')(send),
6-
set: require('./set')(send),
7-
replace: require('./replace')(send),
8-
profiles: {
9-
apply: require('./profiles/apply')(config),
10-
list: require('./profiles/list')(config)
11-
}
12-
}
13-
}
3+
const callbackify = require('callbackify')
4+
5+
module.exports = config => ({
6+
get: callbackify.variadic(require('./get')(config)),
7+
set: callbackify.variadic(require('./set')(config)),
8+
replace: callbackify.variadic(require('./replace')(config)),
9+
profiles: require('./profiles')(config)
10+
})

src/config/profiles/apply.js

+9-12
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,24 @@
11
'use strict'
22

3-
const callbackify = require('callbackify')
43
const configure = require('../../lib/configure')
54

65
module.exports = configure(({ ky }) => {
7-
return callbackify.variadic(async (profile, options) => {
6+
return async (profile, options) => {
87
options = options || {}
98

9+
const searchParams = new URLSearchParams(options.searchParams)
10+
searchParams.set('arg', profile)
11+
if (options.dryRun != null) searchParams.set('dry-run', options.dryRun)
12+
1013
const res = await ky.post('config/profile/apply', {
1114
timeout: options.timeout,
1215
signal: options.signal,
1316
headers: options.headers,
14-
searchParams: {
15-
arg: profile,
16-
// can only pass strings or numbers as values https://github.com/sindresorhus/ky/issues/182
17-
'dry-run': options.dryRun ? 'true' : 'false'
18-
}
19-
})
20-
21-
const parsed = await res.json()
17+
searchParams
18+
}).json()
2219

2320
return {
24-
original: parsed.OldCfg, updated: parsed.NewCfg
21+
original: res.OldCfg, updated: res.NewCfg
2522
}
26-
})
23+
}
2724
})

src/config/profiles/index.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
'use strict'
2+
3+
const callbackify = require('callbackify')
4+
5+
module.exports = config => ({
6+
apply: callbackify.variadic(require('./apply')(config)),
7+
list: callbackify.variadic(require('./list')(config))
8+
})

src/config/profiles/list.js

+6-9
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
11
'use strict'
22

3-
const callbackify = require('callbackify')
43
const configure = require('../../lib/configure')
54
const toCamel = require('../../lib/object-to-camel')
65

76
module.exports = configure(({ ky }) => {
8-
return callbackify.variadic(async (options) => {
7+
return async (options) => {
98
options = options || {}
109

1110
const res = await ky.get('config/profile/list', {
1211
timeout: options.timeout,
1312
signal: options.signal,
14-
headers: options.headers
15-
})
13+
headers: options.headers,
14+
searchParams: options.searchParams
15+
}).json()
1616

17-
const parsed = await res.json()
18-
19-
return parsed
20-
.map(profile => toCamel(profile))
21-
})
17+
return res.map(profile => toCamel(profile))
18+
}
2219
})

src/config/replace.js

+16-20
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,21 @@
11
'use strict'
22

3-
const { Readable } = require('readable-stream')
4-
const promisify = require('promisify-es6')
5-
const SendOneFile = require('../utils/send-one-file')
3+
const { Buffer } = require('buffer')
4+
const configure = require('../lib/configure')
5+
const toFormData = require('../lib/buffer-to-form-data')
66

7-
function toStream (input) {
8-
return new Readable({
9-
read () {
10-
this.push(input)
11-
this.push(null)
12-
}
13-
})
14-
}
7+
module.exports = configure(({ ky }) => {
8+
return async (config, options) => {
9+
options = options || {}
1510

16-
module.exports = (send) => {
17-
const sendOneFile = SendOneFile(send, 'config/replace')
18-
return promisify((config, callback) => {
19-
if (typeof config === 'object') {
20-
config = toStream(Buffer.from(JSON.stringify(config)))
21-
}
11+
const res = await ky.post('config/replace', {
12+
timeout: options.timeout,
13+
signal: options.signal,
14+
headers: options.headers,
15+
searchParams: options.searchParams,
16+
body: toFormData(Buffer.from(JSON.stringify(config)))
17+
}).text()
2218

23-
sendOneFile(config, {}, callback)
24-
})
25-
}
19+
return res
20+
}
21+
})

src/config/set.js

+23-22
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,36 @@
11
'use strict'
22

3-
const promisify = require('promisify-es6')
3+
const configure = require('../lib/configure')
4+
const toCamel = require('../lib/object-to-camel')
5+
6+
module.exports = configure(({ ky }) => {
7+
return async (key, value, options) => {
8+
options = options || {}
49

5-
module.exports = (send) => {
6-
return promisify((key, value, opts, callback) => {
7-
if (typeof opts === 'function') {
8-
callback = opts
9-
opts = {}
10-
}
1110
if (typeof key !== 'string') {
12-
return callback(new Error('Invalid key type'))
11+
throw new Error('Invalid key type')
1312
}
1413

15-
if (value === undefined || Buffer.isBuffer(value)) {
16-
return callback(new Error('Invalid value type'))
17-
}
14+
const searchParams = new URLSearchParams(options.searchParams)
1815

1916
if (typeof value === 'boolean') {
17+
searchParams.set('bool', true)
2018
value = value.toString()
21-
opts = { bool: true }
2219
} else if (typeof value !== 'string') {
20+
searchParams.set('json', true)
2321
value = JSON.stringify(value)
24-
opts = { json: true }
2522
}
2623

27-
send({
28-
path: 'config',
29-
args: [key, value],
30-
qs: opts,
31-
files: undefined,
32-
buffer: true
33-
}, callback)
34-
})
35-
}
24+
searchParams.set('arg', key)
25+
searchParams.append('arg', value)
26+
27+
const res = await ky.post('config', {
28+
timeout: options.timeout,
29+
signal: options.signal,
30+
headers: options.headers,
31+
searchParams
32+
}).json()
33+
34+
return toCamel(res)
35+
}
36+
})

src/lib/error-handler.js

+9-3
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ module.exports = async function errorHandler (input, options, response) {
3535
} catch (err) {
3636
log('Failed to parse error response', err)
3737
// Failed to extract/parse error message from response
38-
throw new HTTPError(response)
38+
msg = err.message
3939
}
4040

41-
if (!msg) throw new HTTPError(response)
42-
throw Object.assign(new Error(msg), { status: response.status })
41+
const error = new HTTPError(response)
42+
43+
// If we managed to extract a message from the response, use it
44+
if (msg) {
45+
error.message = msg
46+
}
47+
48+
throw error
4349
}

src/utils/load-commands.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ function requireCommands (send, config) {
9292
bitswap: require('../bitswap')(config),
9393
block: require('../block')(config),
9494
bootstrap: require('../bootstrap')(config),
95+
config: require('../config')(config),
9596
dag: require('../dag')(config)
9697
}
9798

@@ -122,7 +123,6 @@ function requireCommands (send, config) {
122123

123124
// Miscellaneous
124125
commands: require('../commands'),
125-
config: require('../config'),
126126
diag: require('../diag'),
127127
id: require('../id'),
128128
key: require('../key'),

test/lib.error-handler.spec.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ describe('lib/error-handler', () => {
2121

2222
const err = await throwsAsync(errorHandler(null, null, res))
2323

24+
expect(err instanceof HTTPError).to.be.true()
2425
expect(err.message).to.eql('boom')
25-
expect(err.status).to.eql(500)
26+
expect(err.response.status).to.eql(500)
2627
})
2728

2829
it('should gracefully fail on parse json', async () => {

test/request-api.spec.js

+3-4
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ describe('error handling', () => {
8181
server.listen(6001, () => {
8282
ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => {
8383
expect(err).to.exist()
84-
expect(err.statusCode).to.equal(403)
84+
expect(err.response.status).to.equal(403)
8585
expect(err.message).to.equal('ipfs method not allowed')
8686
server.close(done)
8787
})
@@ -105,9 +105,8 @@ describe('error handling', () => {
105105
server.listen(6001, () => {
106106
ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => {
107107
expect(err).to.exist()
108-
expect(err.statusCode).to.equal(400)
108+
expect(err.response.status).to.equal(400)
109109
expect(err.message).to.equal('client error')
110-
expect(err.code).to.equal(1)
111110
server.close(done)
112111
})
113112
})
@@ -130,7 +129,7 @@ describe('error handling', () => {
130129
server.listen(6001, () => {
131130
ipfsClient('/ip4/127.0.0.1/tcp/6001').config.replace('test/fixtures/r-config.json', (err) => {
132131
expect(err).to.exist()
133-
expect(err.message).to.include('Invalid JSON')
132+
expect(err.message).to.include('Unexpected token M in JSON at position 2')
134133
server.close(done)
135134
})
136135
})

0 commit comments

Comments
 (0)