devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
568 lines (475 loc) • 15.6 kB
JavaScript
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var Class = require("../../core/class"),
extend = require("../../core/utils/extend").extend,
typeUtils = require("../../core/utils/type"),
each = require("../../core/utils/iterator").each,
ajax = require("../../core/utils/ajax"),
_Guid = require("../../core/guid"),
isDefined = typeUtils.isDefined,
Deferred = require("../../core/utils/deferred").Deferred,
errors = require("../errors").errors,
dataUtils = require("../utils");
var GUID_REGEX = /^(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$/;
var VERBOSE_DATE_REGEX = /^\/Date\((-?\d+)((\+|-)?(\d+)?)\)\/$/;
var ISO8601_DATE_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[-+]{1}\d{2}(:?)(\d{2})?)?$/;
// Request processing
var JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose";
function formatISO8601(date, skipZeroTime, skipTimezone) {
var bag = [];
var pad = function pad(n) {
if (n < 10) {
return "0".concat(n);
}
return String(n);
};
var isZeroTime = function isZeroTime() {
return date.getHours() + date.getMinutes() + date.getSeconds() + date.getMilliseconds() < 1;
};
bag.push(date.getFullYear());
bag.push("-");
bag.push(pad(date.getMonth() + 1));
bag.push("-");
bag.push(pad(date.getDate()));
if (!(skipZeroTime && isZeroTime())) {
bag.push("T");
bag.push(pad(date.getHours()));
bag.push(":");
bag.push(pad(date.getMinutes()));
bag.push(":");
bag.push(pad(date.getSeconds()));
if (date.getMilliseconds()) {
bag.push(".");
bag.push(date.getMilliseconds());
}
if (!skipTimezone) {
bag.push("Z");
}
}
return bag.join("");
}
function parseISO8601(isoString) {
var result = new Date(new Date(0).getTimezoneOffset() * 60 * 1000),
chunks = isoString.replace("Z", "").split("T"),
date = /(\d{4})-(\d{2})-(\d{2})/.exec(chunks[0]),
time = /(\d{2}):(\d{2}):(\d{2})\.?(\d{0,7})?/.exec(chunks[1]);
result.setFullYear(Number(date[1]));
result.setMonth(Number(date[2]) - 1);
result.setDate(Number(date[3]));
if (Array.isArray(time) && time.length) {
result.setHours(Number(time[1]));
result.setMinutes(Number(time[2]));
result.setSeconds(Number(time[3]));
result.setMilliseconds(Number(String(time[4]).substr(0, 3)) || 0);
}
return result;
}
function isAbsoluteUrl(url) {
return (/^(?:[a-z]+:)?\/\//i.test(url)
);
}
function toAbsoluteUrl(basePath, relativePath) {
var part;
var baseParts = stripParams(basePath).split("/");
var relativeParts = relativePath.split("/");
function stripParams(url) {
var index = url.indexOf("?");
if (index > -1) {
return url.substr(0, index);
}
return url;
}
baseParts.pop();
while (relativeParts.length) {
part = relativeParts.shift();
if (part === "..") {
baseParts.pop();
} else {
baseParts.push(part);
}
}
return baseParts.join("/");
}
var param = function param(params) {
var result = [];
for (var name in params) {
result.push(name + "=" + params[name]);
}
return result.join("&");
};
var ajaxOptionsForRequest = function ajaxOptionsForRequest(protocolVersion, request, options) {
request = extend({
async: true,
method: "get",
url: "",
params: {},
payload: null,
headers: {},
timeout: 30000
}, request);
options = options || {};
var beforeSend = options.beforeSend;
if (beforeSend) {
beforeSend(request);
}
var method = (request.method || "get").toLowerCase(),
isGet = method === "get",
useJsonp = isGet && options.jsonp,
params = extend({}, request.params),
ajaxData = isGet ? params : formatPayload(request.payload),
qs = !isGet && param(params),
url = request.url,
contentType = !isGet && JSON_VERBOSE_MIME_TYPE;
if (qs) {
url += (url.indexOf("?") > -1 ? "&" : "?") + qs;
}
if (useJsonp) {
ajaxData["$format"] = "json";
}
return {
url: url,
data: ajaxData,
dataType: useJsonp ? "jsonp" : "json",
jsonp: useJsonp && "$callback",
method: method,
async: request.async,
timeout: request.timeout,
headers: request.headers,
contentType: contentType,
accepts: {
json: [JSON_VERBOSE_MIME_TYPE, "text/plain"].join()
},
xhrFields: {
withCredentials: options.withCredentials
}
};
function formatPayload(payload) {
return JSON.stringify(payload, function (key, value) {
if (!(this[key] instanceof Date)) {
return value;
}
value = formatISO8601(this[key]);
switch (protocolVersion) {
case 2:
return value.substr(0, value.length - 1);
case 3:
case 4:
return value;
default:
throw errors.Error("E4002");
}
});
}
};
var sendRequest = function sendRequest(protocolVersion, request, options) {
var d = new Deferred();
var ajaxOptions = ajaxOptionsForRequest(protocolVersion, request, options);
ajax.sendRequest(ajaxOptions).always(function (obj, textStatus) {
var transformOptions = {
deserializeDates: options.deserializeDates,
fieldTypes: options.fieldTypes
},
tuple = interpretJsonFormat(obj, textStatus, transformOptions),
error = tuple.error,
data = tuple.data,
nextUrl = tuple.nextUrl,
extra;
if (error) {
if (error.message !== dataUtils.XHR_ERROR_UNLOAD) {
d.reject(error);
}
} else if (options.countOnly) {
if (isFinite(tuple.count)) {
d.resolve(tuple.count);
} else {
d.reject(new errors.Error("E4018"));
}
} else if (nextUrl && !options.isPaged) {
if (!isAbsoluteUrl(nextUrl)) {
nextUrl = toAbsoluteUrl(ajaxOptions.url, nextUrl);
}
sendRequest(protocolVersion, { url: nextUrl }, options).fail(d.reject).done(function (nextData) {
d.resolve(data.concat(nextData));
});
} else {
if (isFinite(tuple.count)) {
extra = { totalCount: tuple.count };
}
d.resolve(data, extra);
}
});
return d.promise();
};
var formatDotNetError = function formatDotNetError(errorObj) {
var message,
currentError = errorObj;
if ("message" in errorObj) {
if (errorObj.message.value) {
message = errorObj.message.value;
} else {
message = errorObj.message;
}
}
while (currentError = currentError["innererror"] || currentError["internalexception"]) {
message = currentError.message;
if (currentError["internalexception"] && message.indexOf("inner exception") === -1) {
break;
}
}
return message;
};
// TODO split: decouple HTTP errors from OData errors
var errorFromResponse = function errorFromResponse(obj, textStatus) {
if (textStatus === "nocontent") {
return null; // workaround for http://bugs.jquery.com/ticket/13292
}
var httpStatus = 200,
message = "Unknown error",
response = obj;
if (textStatus !== "success") {
httpStatus = obj.status;
message = dataUtils.errorMessageFromXhr(obj, textStatus);
try {
response = JSON.parse(obj.responseText);
} catch (x) {}
}
var errorObj = response && (
// NOTE: $.Deferred rejected and response contain error message
response.then && response
// NOTE: $.Deferred resolved with odata error
|| response.error || response["odata.error"] || response["@odata.error"]);
if (errorObj) {
message = formatDotNetError(errorObj) || message;
if (httpStatus === 200) {
httpStatus = 500;
}
if (errorObj.code) {
httpStatus = Number(errorObj.code);
}
return extend(Error(message), { httpStatus: httpStatus, errorDetails: errorObj });
} else {
if (httpStatus !== 200) {
return extend(Error(message), { httpStatus: httpStatus });
}
}
};
var interpretJsonFormat = function interpretJsonFormat(obj, textStatus, transformOptions) {
var error = errorFromResponse(obj, textStatus),
value;
if (error) {
return { error: error };
}
if (!typeUtils.isPlainObject(obj)) {
return { data: obj };
}
if ("d" in obj && (Array.isArray(obj.d) || typeUtils.isObject(obj.d))) {
value = interpretVerboseJsonFormat(obj, textStatus);
} else {
value = interpretLightJsonFormat(obj, textStatus);
}
transformTypes(value, transformOptions);
return value;
};
var interpretVerboseJsonFormat = function interpretVerboseJsonFormat(obj) {
var data = obj.d;
if (!isDefined(data)) {
return { error: Error("Malformed or unsupported JSON response received") };
}
data = data;
if (isDefined(data.results)) {
data = data.results;
}
return {
data: data,
nextUrl: obj.d.__next,
count: parseInt(obj.d.__count, 10)
};
};
var interpretLightJsonFormat = function interpretLightJsonFormat(obj) {
var data = obj;
if (isDefined(data.value)) {
data = data.value;
}
return {
data: data,
nextUrl: obj["@odata.nextLink"],
count: parseInt(obj["@odata.count"], 10)
};
};
// Serialization and parsing
/**
* @name EdmLiteral
* @publicName EdmLiteral
* @type object
* @namespace DevExpress.data
* @module data/odata/utils
* @export EdmLiteral
*/
var EdmLiteral = Class.inherit({
/**
* @name EdmLiteralMethods.ctor
* @publicName ctor(value)
* @param1 value:string
*/
ctor: function ctor(value) {
this._value = value;
},
/**
* @name EdmLiteralMethods.valueOf
* @publicName valueOf()
* @return string
*/
valueOf: function valueOf() {
return this._value;
}
});
var transformTypes = function transformTypes(obj, options) {
options = options || {};
each(obj, function (key, value) {
if (value !== null && (typeof value === "undefined" ? "undefined" : _typeof(value)) === "object") {
if ("results" in value) {
obj[key] = value.results;
}
transformTypes(obj[key], options);
} else if (typeof value === "string") {
var fieldTypes = options.fieldTypes,
canBeGuid = !fieldTypes || fieldTypes[key] !== "String";
if (canBeGuid && GUID_REGEX.test(value)) {
obj[key] = new _Guid(value);
}
if (options.deserializeDates !== false) {
if (value.match(VERBOSE_DATE_REGEX)) {
var date = new Date(Number(RegExp.$1) + RegExp.$2 * 60 * 1000);
obj[key] = new Date(date.valueOf() + date.getTimezoneOffset() * 60 * 1000);
} else if (ISO8601_DATE_REGEX.test(value)) {
obj[key] = new Date(parseISO8601(obj[key]).valueOf());
}
}
}
});
};
var serializeDate = function serializeDate(date) {
return "datetime'" + formatISO8601(date, true, true) + "'";
};
var serializeString = function serializeString(value) {
return "'" + value.replace(/'/g, "''") + "'";
};
var serializePropName = function serializePropName(propName) {
if (propName instanceof EdmLiteral) {
return propName.valueOf();
}
return propName.replace(/\./g, "/");
};
var serializeValueV4 = function serializeValueV4(value) {
if (value instanceof Date) {
return formatISO8601(value, false, false);
}
if (value instanceof _Guid) {
return value.valueOf();
}
if (Array.isArray(value)) {
return "[" + value.map(function (item) {
return serializeValueV4(item);
}).join(",") + "]";
}
return serializeValueV2(value);
};
var serializeValueV2 = function serializeValueV2(value) {
if (value instanceof Date) {
return serializeDate(value);
}
if (value instanceof _Guid) {
return "guid'" + value + "'";
}
if (value instanceof EdmLiteral) {
return value.valueOf();
}
if (typeof value === "string") {
return serializeString(value);
}
return String(value);
};
var serializeValue = function serializeValue(value, protocolVersion) {
switch (protocolVersion) {
case 2:
case 3:
return serializeValueV2(value);
case 4:
return serializeValueV4(value);
default:
throw errors.Error("E4002");
}
};
var serializeKey = function serializeKey(key, protocolVersion) {
if (typeUtils.isPlainObject(key)) {
var parts = [];
each(key, function (k, v) {
parts.push(serializePropName(k) + "=" + serializeValue(v, protocolVersion));
});
return parts.join();
}
return serializeValue(key, protocolVersion);
};
/**
* @name Utils.keyConverters
* @publicName odata.keyConverters
* @type object
* @namespace DevExpress.data.utils.odata
* @module data/odata/utils
* @export keyConverters
*/
var keyConverters = {
String: function String(value) {
return value + "";
},
Int32: function Int32(value) {
return Math.floor(value);
},
Int64: function Int64(value) {
if (value instanceof EdmLiteral) {
return value;
}
return new EdmLiteral(value + "L");
},
Guid: function Guid(value) {
if (value instanceof _Guid) {
return value;
}
return new _Guid(value);
},
Boolean: function Boolean(value) {
return !!value;
},
Single: function Single(value) {
if (value instanceof EdmLiteral) {
return value;
}
return new EdmLiteral(value + "f");
},
Decimal: function Decimal(value) {
if (value instanceof EdmLiteral) {
return value;
}
return new EdmLiteral(value + "m");
}
};
var convertPrimitiveValue = function convertPrimitiveValue(type, value) {
if (value === null) return null;
var converter = keyConverters[type];
if (!converter) {
throw errors.Error("E4014", type);
}
return converter(value);
};
exports.sendRequest = sendRequest;
exports.serializePropName = serializePropName;
exports.serializeValue = serializeValue;
exports.serializeKey = serializeKey;
exports.keyConverters = keyConverters;
exports.convertPrimitiveValue = convertPrimitiveValue;
exports.EdmLiteral = EdmLiteral;
///#DEBUG
exports.OData__internals = {
interpretJsonFormat: interpretJsonFormat
};
///#ENDDEBUG
;