breeze-bridge-angular
Version:
A bridge that configures Breeze to work with Angular out of the box.
280 lines (273 loc) • 10.7 kB
JavaScript
import { NgModule } from '@angular/core';
import { Headers, Http, Request, RequestOptions, Response } from '@angular/http';
import { config, core as core$1 } from 'breeze-client';
import { map as map$1 } from 'rxjs/operators/map';
/**
* Minimum for breeze breeze Q/ES6 Promise adapter
*/
var Q = {
defer: function () {
var resolve;
var reject;
var promise = new Promise(function (_resolve, _reject) {
resolve = _resolve;
reject = _reject;
});
return {
promise: promise,
resolve: function (value) { resolve(value); },
reject: function (reason) { reject(reason); }
};
},
resolve: function (value) {
var deferred = Q.defer();
deferred.resolve(value);
return deferred.promise;
},
reject: function (reason) {
var deferred = Q.defer();
deferred.reject(reason);
return deferred.promise;
}
};
var AjaxAngularAdapter = (function () {
/**
* @param {?} http
*/
function AjaxAngularAdapter(http$$1) {
this.http = http$$1;
this.name = AjaxAngularAdapter.adapterName;
this.defaultSettings = {};
}
/**
* @return {?}
*/
AjaxAngularAdapter.prototype.initialize = function () { };
/**
* @param {?} config
* @return {?}
*/
AjaxAngularAdapter.prototype.ajax = function (config$$1) {
if (!this.http) {
throw new Error('Unable to locate angular http module for ajax adapter');
}
// merge default DataSetAdapter Settings with config arg
if (!core$1.isEmpty(this.defaultSettings)) {
var /** @type {?} */ compositeConfig = core$1.extend({}, this.defaultSettings);
config$$1 = (core$1.extend(compositeConfig, config$$1));
// extend is shallow; extend headers separately
var /** @type {?} */ headers_1 = core$1.extend({}, this.defaultSettings['headers']); // copy default headers 1st
config$$1['headers'] = core$1.extend(headers_1, config$$1.headers);
}
if (config$$1.crossDomain) {
throw new Error(this.name + ' does not support JSONP (jQuery.ajax:crossDomain) requests');
}
var /** @type {?} */ url = config$$1.url;
if (!core$1.isEmpty(config$$1.params)) {
// Hack: Not sure how Angular handles writing 'search' parameters to the url.
// so this approach takes over the url param writing completely.
var /** @type {?} */ delim = (url.indexOf('?') >= 0) ? '&' : '?';
url = url + delim + encodeParams(config$$1.params);
}
var /** @type {?} */ headers = new Headers(config$$1.headers || {});
if (!headers.has('Content-Type')) {
if (config$$1.type != 'GET' && config$$1.type != 'DELETE' && config$$1.contentType !== false) {
headers.set('Content-Type', /** @type {?} */ (config$$1.contentType) || 'application/json; charset=utf-8');
}
}
// Create the http request body which must be stringified
var /** @type {?} */ body = config$$1.data;
if (body && typeof body !== 'string') {
body = JSON.stringify(body);
}
var /** @type {?} */ reqOptions = new RequestOptions({
url: url,
method: (config$$1.type || 'GET').toUpperCase(),
headers: headers,
body: body,
});
var /** @type {?} */ request = new Request(reqOptions);
var /** @type {?} */ requestInfo = {
adapter: this,
requestOptions: reqOptions,
request: request,
dsaConfig: config$$1,
success: successFn,
error: errorFn // adapter's error callback
};
if (core$1.isFunction(this.requestInterceptor)) {
this.requestInterceptor(requestInfo);
if (this.requestInterceptor['oneTime']) {
this.requestInterceptor = null;
}
}
if (requestInfo.request) {
var /** @type {?} */ fmap = map$1(extractData);
fmap(this.http.request(requestInfo.request))
.forEach(requestInfo.success)
.catch(requestInfo.error);
}
/**
* @param {?} response
* @return {?}
*/
function extractData(response) {
var /** @type {?} */ data;
var /** @type {?} */ dt = requestInfo.dsaConfig.dataType;
// beware:`res.json` and `res.text` will be async some day
if (dt && dt !== 'json') {
data = response.text ? response.text() : null;
}
else {
data = response.json ? response.json() : null;
}
return { data: data, response: response };
}
/**
* @param {?} arg
* @return {?}
*/
function successFn(arg) {
if (arg.response.status < 200 || arg.response.status >= 300) {
throw { data: arg.data, response: arg.response };
}
var /** @type {?} */ httpResponse = {
config: requestInfo.request,
data: arg.data,
getHeaders: makeGetHeaders(arg.response),
status: arg.response.status
};
httpResponse['ngConfig'] = requestInfo.request;
httpResponse['statusText'] = arg.response.statusText;
httpResponse['response'] = arg.response;
config$$1.success(httpResponse);
}
/**
* @param {?} arg
* @return {?}
*/
function errorFn(arg) {
if (arg instanceof Error) {
throw arg; // program error; nothing we can do
}
else {
var /** @type {?} */ data;
var /** @type {?} */ response;
if (arg instanceof Response) {
response = arg;
try {
data = arg.json();
}
catch (e) {
data = arg.text();
}
}
else {
data = arg.data;
response = arg.response;
}
// Timeout appears as an error with status===0 and no data.
if (response.status === 0 && data == null) {
data = 'timeout';
}
var /** @type {?} */ 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
}
var /** @type {?} */ httpResponse = {
config: requestInfo.request,
data: data,
getHeaders: makeGetHeaders(response),
status: response.status
};
httpResponse['ngConfig'] = requestInfo.request;
httpResponse['statusText'] = response.statusText;
httpResponse['response'] = response;
config$$1.error(httpResponse); // send error to breeze error handler
}
}
};
return AjaxAngularAdapter;
}());
AjaxAngularAdapter.adapterName = 'angular';
/**
* @param {?} obj
* @return {?}
*/
function encodeParams(obj) {
var /** @type {?} */ query = '';
var /** @type {?} */ subValue, /** @type {?} */ innerObj, /** @type {?} */ fullSubName;
for (var /** @type {?} */ name_1 in obj) {
if (!obj.hasOwnProperty(name_1)) {
continue;
}
var /** @type {?} */ value = obj[name_1];
if (value instanceof Array) {
for (var /** @type {?} */ i = 0; i < value.length; ++i) {
subValue = value[i];
fullSubName = name_1 + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += encodeParams(innerObj) + '&';
}
}
else if (value && value.toISOString) {
query += encodeURIComponent(name_1) + '=' + encodeURIComponent(value.toISOString()) + '&';
}
else if (value instanceof Object) {
for (var /** @type {?} */ subName in value) {
if (obj.hasOwnProperty(name_1)) {
subValue = value[subName];
fullSubName = name_1 + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += encodeParams(innerObj) + '&';
}
}
}
else if (value === null) {
query += encodeURIComponent(name_1) + '=&';
}
else if (value !== undefined) {
query += encodeURIComponent(name_1) + '=' + encodeURIComponent(value) + '&';
}
}
return query.length ? query.substr(0, query.length - 1) : query;
}
/**
* @param {?} res
* @return {?}
*/
function makeGetHeaders(res) {
var /** @type {?} */ headers = res.headers;
return function getHeaders(headerName) { return headers.getAll(headerName).join('\r\n'); };
}
var BreezeBridgeAngularModule = (function () {
/**
* @param {?} http
*/
function BreezeBridgeAngularModule(http$$1) {
this.http = http$$1;
// Configure Breeze for Angular ... exactly once.
// config breeze to use the native 'backingStore' modeling adapter appropriate for Ng
// 'backingStore' is the Breeze default but we set it here to be explicit.
config.initializeAdapterInstance('modelLibrary', 'backingStore', true);
config.setQ(Q);
config.registerAdapter('ajax', function () { return new AjaxAngularAdapter(http$$1); });
config.initializeAdapterInstance('ajax', AjaxAngularAdapter.adapterName, true);
}
return BreezeBridgeAngularModule;
}());
BreezeBridgeAngularModule.decorators = [
{ type: NgModule },
];
/**
* @nocollapse
*/
BreezeBridgeAngularModule.ctorParameters = function () { return [
{ type: Http, },
]; };
export { Q, BreezeBridgeAngularModule, AjaxAngularAdapter };