UNPKG

ng2-resource-rest

Version:

Angular2 resource module with simple decorators

347 lines (346 loc) 15 kB
import { Headers, Request, RequestMethod, RequestOptions, URLSearchParams } from '@angular/http'; import { Observable } from 'rxjs/Rx'; import { ResourceGlobalConfig, TGetParamsMappingType } from './ResourceGlobalConfig'; export function ResourceAction(methodOptions) { methodOptions = methodOptions || {}; if (methodOptions.method === undefined) { methodOptions.method = RequestMethod.Get; } return function (target, propertyKey) { target[propertyKey] = function () { var _this = this; var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var data = args.length ? args[0] : null; var params = args.length > 1 ? args[1] : null; var callback = args.length > 2 ? args[2] : null; if (typeof data === 'function') { callback = data; data = null; } else if (typeof params === 'function') { callback = params; params = null; } var resourceOptions = this.getResourceOptions(); var isGetRequest = methodOptions.method === RequestMethod.Get; var ret = null; var map = methodOptions.map ? methodOptions.map : this.map; var filter = methodOptions.filter ? methodOptions.filter : this.filter; var initObject = methodOptions.initResultObject ? methodOptions.initResultObject : this.initResultObject; if (methodOptions.isLazy) { ret = {}; } else { if (methodOptions.isArray) { ret = []; } else { if (data && data.$resource === this) { // Setting data to ret ret = data; data = data.toJSON ? data.toJSON() : toJSON(data); } else { ret = initObject(); } } } var mainDeferredSubscriber = null; var mainObservable = null; ret.$resolved = false; ret.$observable = Observable.create(function (subscriber) { mainDeferredSubscriber = subscriber; }).flatMap(function () { return mainObservable; }); ret.$abortRequest = function () { ret.$resolved = true; }; ret.$resource = this; function releaseMainDeferredSubscriber() { if (mainDeferredSubscriber) { mainDeferredSubscriber.next(); mainDeferredSubscriber.complete(); mainDeferredSubscriber = null; } } if (!methodOptions.isLazy) { ret.$observable = ret.$observable.publish(); ret.$observable.connect(); } Promise.all([ Promise.resolve(methodOptions.url || this.getUrl(methodOptions)), Promise.resolve(methodOptions.path || this.getPath(methodOptions)), Promise.resolve(methodOptions.headers || this.getHeaders(methodOptions)), Promise.resolve(methodOptions.params || this.getParams(methodOptions)), Promise.resolve(methodOptions.data || this.getData(methodOptions)) ]) .then(function (dataAll) { if (ret.$resolved) { mainObservable = Observable.create(function (observer) { observer.next(null); }); releaseMainDeferredSubscriber(); } var url = dataAll[0] + dataAll[1]; var headers = new Headers(dataAll[2]); var defPathParams = dataAll[3]; var usedPathParams = {}; if (!Array.isArray(data) || params) { if (!Array.isArray(data)) { data = Object.assign({}, dataAll[4], data); } var pathParams = url.match(/{([^}]*)}/g) || []; var _loop_1 = function (i) { var pathParam = pathParams[i]; var pathKey = pathParam.substr(1, pathParam.length - 2); var isMandatory = pathKey[0] === '!'; if (isMandatory) { pathKey = pathKey.substr(1); } var isGetOnly = pathKey[0] === ':'; if (isGetOnly) { pathKey = pathKey.substr(1); } var value = getValueForPath(pathKey, defPathParams, params || data, usedPathParams); if (isGetOnly && !params) { delete data[pathKey]; } if (isNullOrUndefined(value)) { if (isMandatory) { var consoleMsg_1 = "Mandatory " + pathParam + " path parameter is missing"; mainObservable = Observable.create(function (observer) { observer.error(new Error(consoleMsg_1)); }); console.warn(consoleMsg_1); releaseMainDeferredSubscriber(); return { value: void 0 }; } url = url.substr(0, url.indexOf(pathParam)); return "break"; } // Replacing in the url url = url.replace(pathParam, value); }; for (var i = 0; i < pathParams.length; i++) { var state_1 = _loop_1(i); if (typeof state_1 === "object") return state_1.value; if (state_1 === "break") break; } } // Removing double slashed from final url url = url.replace(/\/\/+/g, '/'); if (url.startsWith('http')) { url = url.replace(':/', '://'); } // Remove trailing slash if (typeof methodOptions.removeTrailingSlash === 'undefined') { methodOptions.removeTrailingSlash = _this.removeTrailingSlash(); } if (methodOptions.removeTrailingSlash) { while (url[url.length - 1] === '/') { url = url.substr(0, url.length - 1); } } // Remove mapped params for (var key in defPathParams) { if (defPathParams[key][0] === '@') { delete defPathParams[key]; } } // Default search params or data var body = null; var searchParams; if (isGetRequest) { // GET searchParams = Object.assign({}, defPathParams, data); } else { // NON GET if (data) { var _body = {}; if (methodOptions.rootNode) { _body["" + methodOptions.rootNode] = data; } else { _body = data; } body = JSON.stringify(_body); } searchParams = defPathParams; } // Setting search params var search = new URLSearchParams(); if (!params) { for (var key in searchParams) { if (searchParams.hasOwnProperty(key) && !usedPathParams[key]) { var value = searchParams[key]; appendSearchParams(search, key, value); } } } // Adding TS if needed var tsName = methodOptions.addTimestamp || resourceOptions.addTimestamp; if (tsName) { if (tsName === true) { tsName = 'ts'; } search.append(tsName, '' + new Date().getTime()); } // Removing Content-Type header if no body if (!body) { headers.delete('content-type'); } // Creating request options var requestOptions = new RequestOptions({ method: methodOptions.method, headers: headers, body: body, url: url, search: search, withCredentials: methodOptions.withCredentials || resourceOptions.withCredentials }); // Creating request object var req = new Request(requestOptions); req = methodOptions.requestInterceptor ? methodOptions.requestInterceptor(req, methodOptions) : _this.requestInterceptor(req, methodOptions); if (!req) { mainObservable = Observable.create(function (observer) { observer.error(new Error('Request is null')); }); console.warn('Request is null'); releaseMainDeferredSubscriber(); return; } // Doing the request var requestObservable = _this._request(req, methodOptions); if (methodOptions.isLazy) { mainObservable = requestObservable; } else { mainObservable = Observable.create(function (subscriber) { var reqSubscr = requestObservable.subscribe(function (resp) { if (resp !== null) { if (methodOptions.isArray) { // Expecting array if (!Array.isArray(resp)) { console.error('Returned data should be an array. Received', resp); } else { ret.push.apply(ret, resp .filter(filter) .map(map) .map(function (respItem) { respItem.$resource = _this; return setDataToObject(initObject(), respItem); })); } } else { // Expecting object if (Array.isArray(resp)) { console.error('Returned data should be an object. Received', resp); } else { if (filter(resp)) { setDataToObject(ret, map(resp)); } } } } ret.$resolved = true; subscriber.next(ret); }, function (err) { return subscriber.error(err); }, function () { ret.$resolved = true; subscriber.complete(); if (callback) { callback(ret); } }); ret.$abortRequest = function () { if (ret.$resolved) { return; } reqSubscr.unsubscribe(); ret.$resolved = true; }; }); } releaseMainDeferredSubscriber(); }); return ret; }; }; } export function setDataToObject(ret, resp) { if (ret.$setData) { ret.$setData(resp); } else { Object.assign(ret, resp); } return ret; } export function appendSearchParams(search, key, value) { /// Convert dates to ISO format string if (value instanceof Date) { search.append(key, value.toISOString()); return; } if (typeof value === 'object') { switch (ResourceGlobalConfig.getParamsMappingType) { case TGetParamsMappingType.Plain: if (Array.isArray(value)) { for (var _i = 0, value_1 = value; _i < value_1.length; _i++) { var arr_value = value_1[_i]; search.append(key, arr_value); } } else { search.append(key, JSON.stringify(value)); } break; case TGetParamsMappingType.Bracket: /// Convert object and arrays to query params for (var k in value) { if (value.hasOwnProperty(k)) { appendSearchParams(search, key + '[' + k + ']', value[k]); } } break; } return; } search.append(key, value); } function getValueForPath(key, params, data, usedPathParams) { if (!isNullOrUndefined(data[key]) && typeof data[key] !== 'object') { usedPathParams[key] = true; return data[key]; } if (isNullOrUndefined(params[key])) { return null; } if (params[key][0] === '@') { return getValueForPath(params[key].substr(1), params, data, usedPathParams); } usedPathParams[key] = true; return params[key]; } function isNullOrUndefined(value) { return value === null || value === undefined; } function toJSON(obj) { var retObj = {}; for (var propName in obj) { if (!(obj[propName] instanceof Function) && !(propName.charAt(0) === '$')) { retObj[propName] = obj[propName]; } } return retObj; }