-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
138 lines (117 loc) · 4.22 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
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
'use strict';
const pkg = require('./package.json');
const defaults = require('lodash/defaults');
const got = require('got');
const EventEmitter = require('events');
const resources = require('./resources');
const url = require('url');
/**
* Creates a Juno instance.
*
* @param {Object} options Configuration options
* @param {String} options.clientId The juno client id
* @param {String} options.clientSecret The juno client isecret
* @param {String} options.accessToken The persistent OAuth for client
* @param {String} options.resourceToken The resource token
* @param {String} options.baseUrl The base url of Juno API
* @param {String} options.resourceOptions The options for request
* @constructor
* @public
*/
function Juno(options) {
if (!(this instanceof Juno)) return new Juno(options);
if (
!options ||
(!options.accessToken &&
!options.resourceToken &&
(!options.clientId || !options.clientSecret)) ||
(options.accessToken && options.resourceToken && (options.clientId || options.clientSecret))
) {
throw new Error('Missing or invalid options');
}
this._options = defaults(options, { isProd: true });
this._baseUrl = {
hostname: this._options.isProd ? 'api.juno.com.br' : 'sandbox.boletobancario.com',
protocol: 'https:',
};
this._baseHeaders = { 'User-Agent': `${pkg.name}/${pkg.version}`, Accept: 'application/json' };
if (this._options.clientId && this._options.clientSecret) {
const hashBase64 = getClientHash(this._options.clientId, this._options.clientSecret);
this._baseHeaders.Authorization = 'Basic ' + hashBase64;
} else {
this._baseHeaders['X-Api-Version'] = !this._options.apiVersion
? 2
: this._options.apiVersion;
if (this._options.accessToken) {
this._baseHeaders['Authorization'] = 'Bearer ' + this._options.accessToken;
}
if (this._options.resourceToken) {
this._baseHeaders['X-Resource-Token'] = this._options.resourceToken;
}
}
EventEmitter.call(this);
}
Object.setPrototypeOf(Juno.prototype, EventEmitter.prototype);
/**
* Sends a request to a Juno API endpoint.
*
* @param {Object} uri URL object
* @param {String} method HTTP method
* @param {(String|undefined)} key Key name to use for req/res body
* @param {(Object|undefined)} data Request body
* @param {(Object|undefined)} headers Extra headers
* @return {Promise}
* @private
*/
Juno.prototype.request = function request(uri, method, key, data, headers) {
const options = {
headers: { ...headers, ...this._baseHeaders },
responseType: 'json',
retry: 0,
method,
};
if (data) {
options.json = key ? { [key]: data } : data;
}
return got(uri, options).then(
(res) => {
const body = res.body;
if (res.statusCode === 202) {
const retryAfter = res.headers['retry-after'] * 1000 || 0;
const { path, search } = url.URL(res.headers['location']);
return delay(retryAfter).then(() => {
const uriRetry = { path, ...this._baseUrl };
if (search) uriRetry.search = search;
return this.request(uriRetry, 'GET', key);
});
}
return key ? body[key] : body || {};
},
(err) => {
return Promise.reject(err);
}
);
};
resources.registerAll(Juno);
/**
* Returns a promise that resolves after a given amount of time.
*
* @param {Number} ms Amount of milliseconds to wait
* @return {Promise} Promise that resolves after `ms` milliseconds
* @private
*/
function delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
/**
* Returns a hash corresponding to the client, created with base64.
*
* @param {String} clientId The client id, public identifier for apps
* @param {String} clientSecret The client secret, a secret known only to the application and the authorization server
* @return {String} A hash base64 string
* @private
*/
function getClientHash(clientId, clientSecret) {
return Buffer.from(`${clientId}:${clientSecret}`).toString('base64');
}
module.exports = Juno;