-
Notifications
You must be signed in to change notification settings - Fork 5
/
api.js
132 lines (116 loc) · 4.15 KB
/
api.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
function Api(config) {
this.requests = {};
this.opts = { baseUrl: config.baseUrl, proto: config.baseProto, apiPrefix: config.apiPath, headers: config.defaultHeaders, post: config.post };
}
Api.prototype = {
/**
* Make an API request without path api path prefixing
*
* @param {string} path Full path for request
* @param {object} data Key-value pairs to send to the server
* @param {ApiRequestOptions} opts API request options
* @return {Promise} Promise response for get
*/
raw: function(path, data, opts) {
return new Promise(function(resolve, reject) {
var req = new ApiRequest({path: path})
.using({method: (((typeof data == 'undefined') || data === null) ? 'GET' : 'POST')})
.using(this.opts)
.using(opts);
var httpRequest = new XMLHttpRequest();
httpRequest.addEventListener("load", function() {
if (this.status >= 200 && this.status <= 299)
resolve(this.response);
else
reject(new ToolbarError('API', 'load', this.statusText, { code: this.status, result: this.response, info: { req: req, data: data, url: req.buildUrl(), path: path } }));
});
httpRequest.addEventListener("error", function() {
debug("ERR");
reject(new ToolbarError('API', 'error', this.statusText, { code: this.status, result: this.response, info: { req: req, data: data, url: req.buildUrl(), path: path } }));
});
httpRequest.addEventListener("abort", function() {
debug("ABT");
reject(new ToolbarError('API', 'abort', this.statusText, { code: this.status, result: this.response, info: { req: req, data: data, url: req.buildUrl(), path: path } }));
});
data = data || null;
if (typeof data == 'object')
data = ApiRequest.serializePostData(data);
if (data && req.method == 'GET')
req.addQueryParams(data);
httpRequest.open(req.method, req.buildUrl(), true);
for (var name in req.headers)
if (req.headers[name])
httpRequest.setRequestHeader(name, req.headers[name]);
if (data && req.method != 'GET')
httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded; charset=UTF-8");
try {
var retval = httpRequest.send(data);
} catch (e) {
reject(new ToolbarError('API', 'ex', e));
}
}.bind(this));
},
/**
* Add default headers for API rquests
*
* @param {object} headers Key-value pairs of headers
* @return this
*/
addHeaders: function(headers) {
this.opts.headers = Object.assign(this.opts.headers, headers);
return this
},
getHeaders: function() {
return this.opts.headers;
},
/**
* Make an API GET request
*
* @param {string} path Relative path for request
* @param {object} data Key-value pairs for the query string
* @return {Promise} Promise response for get
*/
get: function(path, data) {
return this.req(path, data, { method: 'GET' });
},
/**
* Make an API request
*
* @param {string} path Relative path for request
* @param {object} data Key-value pairs to send to the server
* @param {ApiRequestOptions} opts API request options
* @return {Promise} Promise response for get
*/
req: function(path, data, opts) {
return this.raw(((opts || {}).apiPrefix || this.opts.apiPrefix) + path, data, opts)
.then(function(response) {
if (this.opts.nonJSONResponse || (opts || {}).nonJSONResponse)
return {response: response, _success: true};
return JSON.parse(response);
}.bind(this));
},
/**
* Make a single API request to an endpoint. If there is currently a request inflight, return that request
*
* @param {string} path Relative path for request
* @param {object} data Key-value pairs to send to the server
* @param {ApiRequestOptions} opts API request options
* @return {Promise} Promise response for get
*/
once: function(path, data, opts) {
if (this.requests[path]) {
debug('INFLIGHT', path);
return this.requests[path]; //Promise.reject(NOERR);
}
return this.requests[path] = this.req(path, data, opts)
.then(function(results) {
if (this.requests[path])
delete this.requests[path];
return results;
}.bind(this), function(results) {
if (this.requests[path])
delete this.requests[path];
return Promise.reject(results);
}.bind(this));
}
}