-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathErpFetch.js
171 lines (162 loc) · 5.85 KB
/
ErpFetch.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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
"use strict"
class HttpErrorResponse extends Error {
constructor (message = 'Something went wrong', response) {
super(message);
this.name = 'HttpErrorResponse';
this.response = response
}
}
export class ErpFetch {
/**
* Fetcher to Odoo Rest API
* @param {string} baseUrl base URL of the REST API
* @param {string} websiteKey Website Key
* @param {object} transport fetch function
*/
constructor (baseUrl, websiteKey, transport) {
this.baseUrl = baseUrl
this.websiteKey = websiteKey
this._fetch = transport || fetch
}
/** @return true if the headers contains a Content-Type */
haveContentType (headers) {
return headers !== null
&& headers !== undefined
&& headers.hasOwnProperty('Content-Type')
&& headers['Content-Type'].length > 0
}
/** @return true if the headers contains a Content-Type 'application/json' */
isJsonContentType (headers) {
return this.haveContentType(headers)
&& headers['Content-Type'].indexOf('application/json') > -1
}
/** @return true if the body seems like JSON and the Content-type is not set yet. */
needsDefaultJsonContentType (headers, body) {
return !this.haveContentType(headers)
&& body !== null
&& body !== undefined
&& !(body instanceof FormData) // object but not JSON
&& !(body instanceof Blob) // object but not JSON
&& !(body instanceof ArrayBuffer) // object but not JSON
&& typeof body !== 'string' // should be text/plain
&& (typeof body === 'object' || typeof body === 'number' || typeof body === 'boolean') // Ok, json
}
/**
* Make HTTP requests to resource
* @param {String} resource the resource that you wish to fetch
* @param {Object} init custom settings that you want to apply to the request (method, headers ...)
* @param {String} responseType 'blob', 'text', 'json', 'arrayBuffer', 'response' (json is the default)
* @returns Promise
*/
fetch (resource, init = {}, responseType = 'json') {
init.headers = {
...init.headers,
...{
"WEBSITE-UNIQUE-KEY": this.websiteKey,
},
}
if (this.isJsonContentType(init.headers)) {
init.body = JSON.stringify(init.body)
}
const request = this._fetch
const url = new URL(resource, this.baseUrl).href
return request(url, init).then((response) => {
if (response.ok) {
if (responseType === 'blob') {
return response.blob()
} else if (responseType === 'text') {
return response.text()
} else if (responseType === 'arrayBuffer') {
return response.arrayBuffer()
} else if (responseType === 'json') {
return response.json()
} else {
return response;
}
} else {
throw new HttpErrorResponse('Http failure response for ' + url + ': ' +
response.status + ' ' + response.statusText, response);
}
})
}
/**
* Post Request to the Rest API
* @param {string} resource API Endpoint
* @param {object} body Body parameters
* @param {object} init custom settings that you want to apply to the request (method, headers ...)
* @param {String} responseType 'blob', 'text', 'json', 'arrayBuffer', 'response' (json is the default)
* @returns Promise
*/
post (resource, body = {}, init = {}, responseType = 'json') {
if (this.needsDefaultJsonContentType(init?.headers, body)) {
init.headers = { ...init.headers, ...{ 'Content-Type': 'application/json' } }
}
return this.fetch(resource, {
...init,
...{ body },
...{ method: "POST" }
}, responseType)
}
/**
* Put Request to the Rest API
* @param {string} resource API Endpoint
* @param {object} body Body parameters
* @param {object} init custom settings that you want to apply to the request (headers ...)
* @param {String} responseType 'blob', 'text', 'json', 'arrayBuffer', 'response' (json is the default)
* @returns Promise
*/
put (resource, body = {}, init = {}, responseType = 'json') {
if (this.needsDefaultJsonContentType(init?.headers, body)) {
init.headers = { ...init.headers, ...{ 'Content-Type': 'application/json' } }
}
return this.fetch(resource, {
...init,
...{ body },
...{ method: "PUT" }
}, responseType)
}
/**
* Post Request to the Rest API
* @param {string} resource API Endpoint
* @param {object} query query string
* @param {object} init custom settings that you want to apply to the request (headers ...)
* @param {String} responseType 'blob', 'text', 'json', 'arrayBuffer', 'response' (json is the default)
* @returns Promise
*/
get (resource, query, init, responseType = 'json') {
let url = resource
if (typeof query === 'object') {
const params = new URLSearchParams(query)
/** Search for Array parameters and split them into duplicate entries */
for (const [key, value] of Object.entries(query)) {
if (Array.isArray(value)) {
params.delete(key);
value.forEach((v) => params.append(key, v));
}
}
url += "?" + params.toString()
}
return this.fetch(url, {
...init,
...{ method: "GET" },
}, responseType)
}
/**
* Delete Request to the Rest API
* @param {string} resource API Endpoint
* @param {object} query query string
* @param {object} init custom settings that you want to apply to the request (headers ...)
* @param {String} responseType 'blob', 'text', 'json', 'arrayBuffer', 'response' (json is the default)
* @returns Promise
*/
delete (resource, body = {}, init = {}, responseType = 'json') {
if (this.needsDefaultJsonContentType(init?.headers, body)) {
init.headers = { ...init.headers, ...{ 'Content-Type': 'application/json' } }
}
return this.fetch(resource, {
...init,
...{ body },
...{ method: "DELETE" },
}, responseType)
}
}