-
Notifications
You must be signed in to change notification settings - Fork 116
/
index.js
104 lines (89 loc) · 2.66 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
/* globals fetch, Headers */
/* istanbul ignore next */
if (!process.browser) {
global.fetch = require('node-fetch')
global.Headers = global.fetch.Headers
}
const caseless = require('caseless')
const toTypedArray = require('typedarray-to-buffer')
const makeHeaders = obj => new Headers(obj)
function makeBody (value) {
// TODO: Streams support.
if (typeof value === 'string') {
value = Buffer.from(value)
}
/* Can't test Blob types in Node.js */
/* istanbul ignore else */
if (Buffer.isBuffer(value)) {
value = toTypedArray(value)
}
return value
}
class R2 {
constructor (...args) {
this.opts = { method: 'GET' }
this._headers = {}
this._caseless = caseless(this._headers)
let failSet = () => {
throw new Error('Cannot set read-only property.')
}
const resolveResWith = way => resp => resp.clone()[way]()
/* formData isn't implemented in the shim yet */
const ways = ['json', 'text', 'arrayBuffer', 'blob', 'formData']
ways.forEach(way =>
Object.defineProperty(this, way, {
get: () => this.response.then(resolveResWith(way)),
set: failSet
})
)
this._args(...args)
this.response = Promise.resolve().then(() => this._request())
}
_args (...args) {
let opts = this.opts
if (typeof args[0] === 'string') {
opts.url = args.shift()
}
if (typeof args[0] === 'object') {
opts = Object.assign(opts, args.shift())
}
this.setHeaders(opts.headers)
this.opts = opts
}
method (verb, ...args) {
this.opts.method = verb.toUpperCase()
this._args(...args)
return this
}
_request () {
let url = this.opts.url
delete this.opts.url
if (this.opts.json) {
this.opts.body = JSON.stringify(this.opts.json)
this.setHeader('content-type', 'application/json')
delete this.opts.json
}
if (this.opts.body) {
this.opts.body = makeBody(this.opts.body)
}
// TODO: formData API.
this.opts.headers = makeHeaders(this._headers)
return fetch(url, this.opts)
}
setHeaders (obj = {}) {
for (let key in obj) {
this._caseless.set(key, obj[key])
}
return this
}
setHeader (key, value) {
this.setHeaders({ [key]: value })
}
}
module.exports = (...args) => new R2(...args)
module.exports.put = (...args) => new R2().method('put', ...args)
module.exports.get = (...args) => new R2().method('get', ...args)
module.exports.post = (...args) => new R2().method('post', ...args)
module.exports.head = (...args) => new R2().method('head', ...args)
module.exports.patch = (...args) => new R2().method('patch', ...args)
module.exports.delete = (...args) => new R2().method('delete', ...args)