UNPKG

13.6 kBJavaScriptView Raw
1"use strict";
2/**
3 * @author Juan David Correa
4 */
5Object.defineProperty(exports, "__esModule", { value: true });
6const rx_http_request_1 = require("@akanass/rx-http-request");
7const operators_1 = require("rxjs/operators");
8require("reflect-metadata");
9/**
10 *
11 */
12const pathParamMetadataKey = Symbol('__pathParam__');
13const queryMetadataKey = Symbol('__queryParam__');
14const classMetadataKey = Symbol('__class__');
15const bodyMetadataKey = Symbol('__body__');
16const pathParamPropertyMetadataKey = Symbol('__pathParamProperty__');
17const mapperMetadataKey = Symbol('__mapper__');
18const headersMetadataKey = Symbol('__headers__');
19const beforeMetadataKey = Symbol('__headers__');
20const exceptionHandlerMetadataKey = Symbol('__handlerError__');
21/**
22 *
23 */
24class Http {
25 /**
26 *
27 * @param {T} interceptor
28 */
29 static addInterceptor(interceptor) {
30 this.interceptors.unshift(new interceptor());
31 }
32 /**
33 *
34 * @param {string | Partial<ConfigHttp>} config
35 * @returns {(target) => void}
36 */
37 static client(config) {
38 return target => Reflect.defineMetadata(classMetadataKey, config, target);
39 }
40 /**
41 *
42 * @param {string} url
43 * @param {Function} component
44 * @param {number} statusCodeOk
45 * @returns {Function}
46 */
47 static get(url, component, statusCodeOk = 400) {
48 return this.request('get', url, component, statusCodeOk);
49 }
50 /**
51 *
52 * @param {string} url
53 * @param {Function} component
54 * @param {number} statusCodeOk
55 * @returns {Function}
56 */
57 static post(url, component, statusCodeOk = 400) {
58 return this.request('post', url, component, statusCodeOk);
59 }
60 /**
61 *
62 * @param {string} url
63 * @param {Function} component
64 * @param {number} statusCodeOk
65 * @returns {Function}
66 */
67 static put(url, component, statusCodeOk = 400) {
68 return this.request('put', url, component, statusCodeOk);
69 }
70 /**
71 *
72 * @param {string} url
73 * @param {Function} component
74 * @param {number} statusCodeOk
75 * @returns {Function}
76 */
77 static patch(url, component, statusCodeOk = 400) {
78 return this.request('patch', url, component, statusCodeOk);
79 }
80 /**
81 *
82 * @param {string} url
83 * @param {Function} component
84 * @param {number} statusCodeOk
85 * @returns {Function}
86 */
87 static delete(url, component, statusCodeOk = 400) {
88 return this.request('delete', url, component, statusCodeOk);
89 }
90 /**
91 * @param {string} method
92 * @param {string} url
93 * @param {Function} component
94 * @param {number} statusCodeOk
95 * @returns {(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => void}
96 */
97 static request(method, urlToMatch, component, statusCodeOk) {
98 return (target, propertyKey, descriptor) => {
99 descriptor.value = (...arguments_) => {
100 const mainConfig = Reflect.getMetadata(classMetadataKey, component);
101 const pathParams = Reflect.getMetadata(pathParamMetadataKey, target, propertyKey) || [];
102 const queryParams = Reflect.getMetadata(queryMetadataKey, target, propertyKey) || [];
103 const bodyParams = Reflect.getMetadata(bodyMetadataKey, target, propertyKey) || [];
104 const mapper = Reflect.getMetadata(mapperMetadataKey, target, propertyKey) || null;
105 const especificHeaders = Reflect.getMetadata(headersMetadataKey, target, propertyKey) || null;
106 const before = Reflect.getMetadata(beforeMetadataKey, target, propertyKey) || null;
107 const exceptionHandler = Reflect.getMetadata(exceptionHandlerMetadataKey, target, propertyKey) || null;
108 // Reflect.deleteMetadata(pathParamMetadataKey, target, propertyKey);
109 const headers = new Headers();
110 let mainUrl = String();
111 const argumentsHttp = arguments_;
112 let url = String(urlToMatch);
113 url = UtilsHttp.buildPathParams(pathParams, argumentsHttp, url);
114 const queryParamsUrl = UtilsHttp.buildQueryParams(queryParams, argumentsHttp);
115 if (typeof mainConfig === 'object') {
116 mainUrl = mainConfig.url;
117 UtilsHttp.prepareHeaders(mainConfig.headers, headers);
118 }
119 else
120 mainUrl = mainConfig;
121 mainUrl = mainUrl.concat(url).concat(queryParamsUrl === '?' ? '' : queryParamsUrl);
122 const body_ = method !== 'get' ? UtilsHttp.prepareBody(bodyParams, argumentsHttp) : String();
123 if (especificHeaders)
124 Object.keys(especificHeaders)
125 .forEach(i => headers.set(i, especificHeaders[i]));
126 let request = {
127 url: mainUrl,
128 body: body_,
129 headers: headers.getHeaders(),
130 method: method,
131 };
132 request = before ? before(request) : request;
133 this.interceptors.forEach(i => request = i.intercep(request));
134 return rx_http_request_1.RxHR[method](request.url, {
135 headers: request.headers,
136 body: request.body,
137 qsStringifyOptions: {
138 arrayFormat: 'repeat',
139 },
140 })
141 .pipe(operators_1.map(value => this.mapBodyAndControlError(value, exceptionHandler, statusCodeOk)), operators_1.map(body => mapper ? mapper(body) : body));
142 };
143 };
144 }
145 /**
146 *
147 * @param value
148 * @param {Handler} exceptionHandler
149 * @param statusCodeOk
150 * @returns {any}
151 */
152 static mapBodyAndControlError(value, exceptionHandler, statusCodeOk) {
153 const { body, statusCode, request } = value.response;
154 if (statusCode < statusCodeOk) {
155 return body ? JSON.parse(body) : body;
156 }
157 else if (exceptionHandler) {
158 throw exceptionHandler(body, statusCode, request);
159 }
160 else {
161 if (body && body.message && body.error) {
162 throw new HttpRequestException(body.error, statusCode, body.message);
163 }
164 else {
165 throw new HttpRequestException(JSON.stringify(body), statusCode, String());
166 }
167 }
168 }
169 /**
170 *
171 * @param {string} param
172 * @returns {Function}
173 */
174 static pathParam(param) {
175 return (target, propertyKey, parameterIndex) => {
176 const pathParams = Reflect.getOwnMetadata(pathParamMetadataKey, target, propertyKey) || [];
177 pathParams.unshift({
178 indexArgument: parameterIndex,
179 paramValue: param,
180 });
181 Reflect.defineMetadata(pathParamMetadataKey, pathParams, target, propertyKey);
182 };
183 }
184 /**
185 *
186 * @param {string} param_
187 * @returns {Function}
188 */
189 static query(param_) {
190 return (target, propertyKey, parameterIndex) => {
191 const queryParams = Reflect.getOwnMetadata(queryMetadataKey, target, propertyKey) || [];
192 queryParams.unshift({
193 indexArgument: parameterIndex,
194 paramValue: param_,
195 });
196 Reflect.defineMetadata(queryMetadataKey, queryParams, target, propertyKey);
197 };
198 }
199 /**
200 *
201 * @param {Object} target
202 * @param {string | symbol} propertyKey
203 * @param {number} parameterIndex
204 */
205 static body(target, propertyKey, parameterIndex) {
206 const bodyParams = Reflect.getOwnMetadata(bodyMetadataKey, target, propertyKey) || [];
207 bodyParams.unshift(parameterIndex);
208 Reflect.defineMetadata(bodyMetadataKey, bodyParams, target, propertyKey);
209 }
210 /**
211 *
212 * @param {boolean} enable
213 * @returns {Function}
214 */
215 static pathParamProperty(enable = true) {
216 return (target, propertyName) => Reflect.defineMetadata(pathParamPropertyMetadataKey, { name: propertyName }, target, propertyName);
217 }
218 /**
219 *
220 * @param {Function} mapper
221 * @returns {Function}
222 */
223 static mapper(mapper) {
224 return (target, propertyKey) => Reflect.defineMetadata(mapperMetadataKey, mapper, target, propertyKey);
225 }
226 /**
227 *
228 * @param {{[p: string]: T}} headers
229 * @returns {Function}
230 */
231 static headers(headers) {
232 return (target, propertyKey) => Reflect.defineMetadata(headersMetadataKey, headers, target, propertyKey);
233 }
234 /**
235 *
236 * @param {(request: Request_) => Request_} before_
237 * @returns {(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => void}
238 */
239 static before(before_) {
240 return (target, propertyKey) => Reflect.defineMetadata(beforeMetadataKey, before_, target, propertyKey);
241 }
242 /**
243 *
244 * @param {Handler} handler
245 * @returns {(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) => void}
246 */
247 static handlerError(handler) {
248 return (target, propertyKey) => Reflect.defineMetadata(exceptionHandlerMetadataKey, handler, target, propertyKey);
249 }
250}
251Http.interceptors = [];
252exports.Http = Http;
253/**
254 *
255 */
256class UtilsHttp {
257 /**
258 *
259 * @param obj
260 * @param {Headers} headers
261 */
262 static prepareHeaders(obj, headers) {
263 Object.keys(obj).forEach(key => !headers.has(obj[key]) ? headers.set(key, obj[key]) : null);
264 if (!headers.has('Content-Type')) {
265 headers.set('Content-Type', 'application/json');
266 }
267 }
268 /**
269 *
270 * @param {Param[]} params
271 * @param argumentsHttp
272 * @returns {string}
273 */
274 static buildQueryParams(params, argumentsHttp) {
275 let queryParamsUrl = '?';
276 const ampersan = '&';
277 const empty = String();
278 params = params
279 .filter(param => argumentsHttp[param.indexArgument]);
280 params
281 .forEach((param, index) => {
282 if (typeof argumentsHttp[param.indexArgument] === 'object') {
283 const keys = Object.keys(argumentsHttp[param.indexArgument]) || [];
284 let tempCont = 0;
285 for (const key in argumentsHttp[param.indexArgument]) {
286 queryParamsUrl = queryParamsUrl.concat(`${key}=${argumentsHttp[param.indexArgument][key]}${tempCont === keys.length - 1 ? empty : ampersan}`);
287 tempCont++;
288 }
289 }
290 else {
291 if (!param.paramValue)
292 return;
293 queryParamsUrl = queryParamsUrl.length > 1 ? queryParamsUrl.concat(ampersan) : queryParamsUrl;
294 queryParamsUrl = queryParamsUrl.concat(`${param.paramValue}=${argumentsHttp[param.indexArgument]}${index === params.length - 1 ? empty : ampersan}`);
295 }
296 });
297 return queryParamsUrl;
298 }
299 /**
300 *
301 * @param {Param[]} pathParam
302 * @param argumentsHttp
303 * @param {string} url
304 * @returns {string}
305 */
306 static buildPathParams(pathParam, argumentsHttp, url) {
307 url = url.replace(/\s/g, '').trim();
308 const wrapOpen = '{';
309 const wrapClose = '}';
310 pathParam
311 .filter(param => param.paramValue)
312 .forEach(param => {
313 if (!param.paramValue)
314 return;
315 const pathParam = wrapOpen.concat(param.paramValue.toString()).concat(wrapClose);
316 if (url.includes(pathParam))
317 url = url.replace(pathParam, argumentsHttp[param.indexArgument]);
318 });
319 pathParam
320 .filter(param => !param.paramValue)
321 .map(param => url += `/${argumentsHttp[param.indexArgument]}`);
322 argumentsHttp
323 .filter(arg => typeof arg === 'object')
324 .forEach(obj => {
325 Object.keys(obj).forEach(key => {
326 const keyPathParam = Reflect.getMetadata(pathParamPropertyMetadataKey, obj, key);
327 if (keyPathParam)
328 url = url.replace(`{${keyPathParam.name}}`, obj[keyPathParam.name]);
329 });
330 });
331 return url;
332 }
333 /**
334 *
335 * @param {number[]} params
336 * @param argumentsHttp
337 * @returns {any}
338 */
339 static prepareBody(params, argumentsHttp) {
340 let body = {};
341 params.forEach(i => body = Object.assign({}, body, argumentsHttp[i]));
342 return params.length ? JSON.stringify(body) : String();
343 }
344}
345/**
346 *
347 */
348class HttpRequestException {
349 constructor(error, statusCode, message) {
350 this.error = error;
351 this.statusCode = statusCode;
352 this.message = message;
353 }
354}
355exports.HttpRequestException = HttpRequestException;
356/**
357 *
358 */
359class Headers {
360 constructor() {
361 /**
362 *
363 * @type {Map<any, any>}
364 */
365 this.headers = new Map();
366 }
367 /**
368 *
369 * @param {string} key
370 * @returns {boolean}
371 */
372 has(key) {
373 return this.headers.has(key);
374 }
375 /**
376 *
377 * @param {string} key
378 * @param header
379 * @returns {this}
380 */
381 set(key, header) {
382 this.headers.set(key, header);
383 return this;
384 }
385 /**
386 *
387 * @returns {any}
388 */
389 getHeaders() {
390 const headers = Object();
391 Array.from(this.headers.keys())
392 .forEach(key => headers[key] = this.headers.get(key));
393 return headers;
394 }
395}