breeze-client
Version:
Breeze data management for JavaScript clients
191 lines (186 loc) • 7.1 kB
JavaScript
import { config, core } from 'breeze-client';
/** 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;
}
/** Breeze AJAX adapter using fetch API
* See https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
*/
class AjaxFetchAdapter {
static adapterName = "fetch";
name;
defaultSettings;
requestInterceptor;
constructor() {
this.name = AjaxFetchAdapter.adapterName;
this.defaultSettings = {};
this.requestInterceptor = undefined;
}
static register(breezeConfig) {
breezeConfig = breezeConfig || config;
breezeConfig.registerAdapter("ajax", AjaxFetchAdapter);
return breezeConfig.initializeAdapterInstance("ajax", AjaxFetchAdapter.adapterName, true);
}
initialize() {
}
ajax(config) {
if (!fetch) {
throw new Error("fetch API not supported in this browser");
}
let init = {
method: config.type,
mode: 'cors',
cache: 'no-cache',
credentials: 'include',
headers: {
'Content-Type': config.contentType || 'application/json',
// ...config.headers
// 'Content-Type': 'application/x-www-form-urlencoded',
},
redirect: 'follow',
referrer: 'client', // no-referrer, *client
};
if (config.type !== "GET" && config.type !== "HEAD") {
// body data type must match "Content-Type" header
// let data = config.params || config.data;
let data = config.data;
if (typeof (data) !== "string") {
data = JSON.stringify(data);
}
init.body = data;
}
let url = config.url;
if (!core.isEmpty(config.params)) {
// Hack: Not sure how Fetch handles writing 'search' parameters to the url.
// so this approach takes over the url param writing completely.
url = appendQueryStringParameter(url, encodeParams(config.params));
}
if (!core.isEmpty(this.defaultSettings)) {
let compositeConfig = core.extend({}, this.defaultSettings);
init = core.extend(compositeConfig, init);
// extend is shallow; extend headers separately
let headers = core.extend({}, this.defaultSettings.headers); // copy default headers 1st
init.headers = core.extend(headers, init.headers);
}
let requestInfo = {
adapter: this,
config: init,
dsaConfig: config,
success: successFn,
error: errorFn, // adapter's error callback
};
if (core.isFunction(this.requestInterceptor)) {
let ri = this.requestInterceptor;
ri(requestInfo);
if (ri.oneTime) {
this.requestInterceptor = undefined;
}
}
if (requestInfo.config) { // exists unless requestInterceptor killed it.
fetch(url, requestInfo.config).then(response => {
if (!response.ok) {
response.text().then(s => {
requestInfo.error(response.status, response.statusText, s, response, null);
});
}
else {
response.json().then(j => {
requestInfo.success(j, response.statusText, response);
});
}
}).catch(err => {
requestInfo.error(0, err && err.message || err, null, null, err);
});
}
function successFn(data, statusText, response) {
let httpResponse = {
config: config,
data: data,
getHeaders: getHeadersFn(response),
status: response.status,
statusText: statusText
};
config.success(httpResponse);
}
function errorFn(status, statusText, body, response, errorThrown) {
let httpResponse = {
config: config,
data: body,
error: errorThrown || statusText,
getHeaders: getHeadersFn(response),
status: status,
statusText: statusText
};
config.error(httpResponse);
}
}
}
config.registerAdapter("ajax", AjaxFetchAdapter);
function getHeadersFn(response) {
if (!response || response.status === 0) { // timeout or abort; no headers
return function (headerName) {
return (headerName && headerName.length > 0) ? "" : {};
};
}
else {
return function (headerName) {
if (headerName && headerName.length > 0) {
return response.headers.get(headerName);
}
let hob = {};
response.headers.forEach((val, key) => {
hob[key] = val;
});
return hob;
};
}
}
/**
* Generated bundle index. Do not edit.
*/
export { AjaxFetchAdapter };
//# sourceMappingURL=breeze-client-adapter-ajax-fetch.mjs.map