ng2-resource-rest
Version:
Angular2 resource module with simple decorators
347 lines (346 loc) • 15 kB
JavaScript
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;
}