breeze-client
Version:
Breeze data management for JavaScript clients
195 lines (190 loc) • 8.22 kB
JavaScript
import { HttpHeaders, HttpRequest, HttpResponse } from '@angular/common/http';
import { config, core } from 'breeze-client';
import { filter, map } from 'rxjs/operators';
/** Appends parameter to url, with appropriate delimiter */
function appendQueryStringParameter(url, parameter) {
if (!parameter)
return url;
let separator = url.endsWith("?") ? "" : url.includes("?") ? "&" : "?";
return url + separator + parameter;
}
/** Encodes the object into query string parameters */
function encodeParams(obj) {
let query = '';
let subValue, innerObj, fullSubName;
for (let name in obj) {
if (!obj.hasOwnProperty(name)) {
continue;
}
let value = obj[name];
if (value instanceof Array) {
for (let i = 0; i < value.length; ++i) {
subValue = value[i];
fullSubName = name + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += encodeParams(innerObj) + '&';
}
}
else if (value && value.toISOString) { // a feature of Date-like things
query += encodeURIComponent(name) + '=' + encodeURIComponent(value.toISOString()) + '&';
}
else if (value instanceof Object) {
for (let subName in value) {
if (obj.hasOwnProperty(name)) {
subValue = value[subName];
fullSubName = name + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += encodeParams(innerObj) + '&';
}
}
}
else if (value === null) {
query += encodeURIComponent(name) + '=&';
}
else if (value !== undefined) {
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
}
}
return query.length ? query.substr(0, query.length - 1) : query;
}
class AjaxHttpClientAdapter {
http;
static adapterName = 'httpclient';
name = AjaxHttpClientAdapter.adapterName;
defaultSettings = {};
requestInterceptor;
constructor(http) {
this.http = http;
}
static register(http, breezeConfig) {
breezeConfig = breezeConfig || config;
breezeConfig.registerAdapter("ajax", function () { return new AjaxHttpClientAdapter(http); });
return breezeConfig.initializeAdapterInstance("ajax", AjaxHttpClientAdapter.adapterName, true);
}
initialize() { }
ajax(config) {
if (!this.http) {
throw new Error('Unable to locate angular http module for ajax adapter');
}
// merge default DataSetAdapter Settings with config arg
if (!core.isEmpty(this.defaultSettings)) {
let compositeConfig = core.extend({}, this.defaultSettings);
config = core.extend(compositeConfig, config);
// extend is shallow; extend headers separately
let headers = core.extend({}, this.defaultSettings['headers']); // copy default headers 1st
config['headers'] = core.extend(headers, config.headers);
}
if (config.crossDomain) {
throw new Error(this.name + ' does not support JSONP (crossDomain) requests');
}
// Hack: Not sure how Angular handles writing 'search' parameters to the url.
// so this approach takes over the url param writing completely.
const parameters = core.isEmpty(config.params) ? null : encodeParams(config.params);
const url = appendQueryStringParameter(config.url, parameters);
let headers = new HttpHeaders(config.headers || {});
if (!headers.has('Content-Type')) {
if (config.type !== 'GET' && config.type !== 'DELETE' && !!config.contentType) {
headers = headers.set('Content-Type', config.contentType || 'application/json; charset=utf-8');
}
}
let body = config.data;
let request = new HttpRequest((config.type || 'GET').toUpperCase(), url, body, { headers: headers, responseType: "text" });
let requestInfo = {
adapter: this,
request: request,
dsaConfig: config,
success: successFn,
error: errorFn // adapter's error callback
};
if (core.isFunction(this.requestInterceptor)) {
this.requestInterceptor(requestInfo);
if (this.requestInterceptor['oneTime']) {
this.requestInterceptor = null;
}
}
if (requestInfo.request) { // exists unless requestInterceptor killed it.
const ffilter = filter((response) => response instanceof HttpResponse);
const fmap = map(extractData);
fmap(ffilter(this.http.request(requestInfo.request)))
.forEach(requestInfo.success)
.catch(requestInfo.error);
}
function extractData(event) {
let response = event;
let data;
let dt = requestInfo.dsaConfig.dataType;
// beware:`res.json` and `res.text` will be async some day
if (dt && dt !== 'json') {
data = response.body;
}
else {
data = JSON.parse(response.body);
}
return { data, response };
}
function successFn(arg) {
if (arg.response.status < 200 || arg.response.status >= 300) {
throw { data: arg.data, response: arg.response };
}
let httpResponse = {
config: requestInfo.request,
data: arg.data,
getHeaders: makeGetHeaders(arg.response.headers),
status: arg.response.status
};
httpResponse['ngConfig'] = requestInfo.request;
httpResponse['statusText'] = arg.response.statusText;
httpResponse['response'] = arg.response;
config.success(httpResponse);
}
function errorFn(response) {
if (response instanceof Error) {
throw response; // program error; nothing we can do
}
else {
let data;
if (response.error instanceof HttpResponse) {
data = response.error.body;
}
else if (response.error instanceof Error) {
data = response.error.message;
}
else {
data = response.error;
}
// Timeout appears as an error with status===0 and no data.
if (response.status === 0 && data == null) {
data = 'timeout';
}
let errorMessage = response.status + ": " + response.statusText;
if (data && typeof data === 'object') {
data["message"] = data["message"] || errorMessage; // breeze looks at the message property
}
if (!data) {
data = errorMessage; // Return the error message as data
}
let httpResponse = {
config: requestInfo.request,
data: data,
getHeaders: makeGetHeaders(response.headers),
status: response.status
};
httpResponse['ngConfig'] = requestInfo.request;
httpResponse['statusText'] = response.statusText;
httpResponse['response'] = response;
config.error(httpResponse); // send error to breeze error handler
}
}
}
}
///// Helpers ////
function makeGetHeaders(headers) {
return function getHeaders(headerName) { return headers.getAll(headerName).join('\r\n'); };
}
/**
* Generated bundle index. Do not edit.
*/
export { AjaxHttpClientAdapter };
//# sourceMappingURL=breeze-client-adapter-ajax-httpclient.mjs.map