devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
543 lines (541 loc) • 19.8 kB
JavaScript
/**
* DevExtreme (cjs/__internal/data/odata/m_utils.js)
* Version: 24.2.6
* Build date: Mon Mar 17 2025
*
* Copyright (c) 2012 - 2025 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.serializeValue = exports.serializePropName = exports.serializeKey = exports.sendRequest = exports.keyConverters = exports.generateSelect = exports.generateExpand = exports.formatFunctionInvocationUrl = exports.escapeServiceOperationParams = exports.convertPrimitiveValue = exports.EdmLiteral = void 0;
var _errors = require("../../../common/data/errors");
var _utils = require("../../../common/data/utils");
var _class = _interopRequireDefault(require("../../../core/class"));
var _guid = _interopRequireDefault(require("../../../core/guid"));
var _ajax = _interopRequireDefault(require("../../../core/utils/ajax"));
var _common = require("../../../core/utils/common");
var _deferred = require("../../../core/utils/deferred");
var _extend = require("../../../core/utils/extend");
var _iterator = require("../../../core/utils/iterator");
var _string = require("../../../core/utils/string");
var _type = require("../../../core/utils/type");
function _interopRequireDefault(e) {
return e && e.__esModule ? e : {
default: e
}
}
const 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})$/;
const VERBOSE_DATE_REGEX = /^\/Date\((-?\d+)((\+|-)?(\d+)?)\)\/$/;
const ISO8601_DATE_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[-+]{1}\d{2}(:?)(\d{2})?)?$/;
const JSON_VERBOSE_MIME_TYPE = "application/json;odata=verbose";
const makeArray = value => "string" === (0, _type.type)(value) ? value.split() : value;
const hasDot = x => /\./.test(x);
const pad = (text, length, right) => {
text = String(text);
while (text.length < length) {
text = right ? `${text}0` : `0${text}`
}
return text
};
const formatISO8601 = (date, skipZeroTime, skipTimezone) => {
const bag = [];
const padLeft2 = text => pad(text, 2);
bag.push(date.getFullYear());
bag.push("-");
bag.push(padLeft2(date.getMonth() + 1));
bag.push("-");
bag.push(padLeft2(date.getDate()));
if (!(skipZeroTime && date.getHours() + date.getMinutes() + date.getSeconds() + date.getMilliseconds() < 1)) {
bag.push("T");
bag.push(padLeft2(date.getHours()));
bag.push(":");
bag.push(padLeft2(date.getMinutes()));
bag.push(":");
bag.push(padLeft2(date.getSeconds()));
if (date.getMilliseconds()) {
bag.push(".");
bag.push(pad(date.getMilliseconds(), 3))
}
if (!skipTimezone) {
bag.push("Z")
}
}
return bag.join("")
};
const parseISO8601 = isoString => {
const result = new Date(60 * new Date(0).getTimezoneOffset() * 1e3);
const chunks = isoString.replace("Z", "").split("T");
const date = /(\d{4})-(\d{2})-(\d{2})/.exec(chunks[0]);
const 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]));
let fractional = (time[4] || "").slice(0, 3);
fractional = pad(fractional, 3, true);
result.setMilliseconds(Number(fractional))
}
return result
};
const isAbsoluteUrl = url => /^(?:[a-z]+:)?\/{2,2}/i.test(url);
const stripParams = url => {
const index = url.indexOf("?");
if (index > -1) {
return url.substr(0, index)
}
return url
};
const toAbsoluteUrl = (basePath, relativePath) => {
let part;
const baseParts = stripParams(basePath).split("/");
const relativeParts = relativePath.split("/");
baseParts.pop();
while (relativeParts.length) {
part = relativeParts.shift();
if (".." === part) {
baseParts.pop()
} else {
baseParts.push(part)
}
}
return baseParts.join("/")
};
const param = params => {
const result = [];
for (const name in params) {
result.push(`${name}=${params[name]}`)
}
return result.join("&")
};
const ajaxOptionsForRequest = function(protocolVersion, request) {
var _options$beforeSend;
let options = arguments.length > 2 && void 0 !== arguments[2] ? arguments[2] : {};
request = (0, _extend.extend)({
async: true,
method: "get",
url: "",
params: {},
payload: null,
headers: {},
timeout: 3e4
}, request);
null === (_options$beforeSend = options.beforeSend) || void 0 === _options$beforeSend || _options$beforeSend.call(options, request);
const {
async: async,
timeout: timeout,
headers: headers
} = request;
let {
url: url,
method: method
} = request;
const {
jsonp: jsonp,
withCredentials: withCredentials
} = options;
method = (method || "get").toLowerCase();
const isGet = "get" === method;
const useJsonp = isGet && jsonp;
const params = (0, _extend.extend)({}, request.params);
const ajaxData = isGet ? params : (payload = request.payload, 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.errors.Error("E4002")
}
})));
var payload;
const qs = !isGet && param(params);
const 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: async,
timeout: timeout,
headers: headers,
contentType: contentType,
accepts: {
json: [JSON_VERBOSE_MIME_TYPE, "text/plain"].join()
},
xhrFields: {
withCredentials: withCredentials
}
}
};
const sendRequest = (protocolVersion, request, options) => {
const {
deserializeDates: deserializeDates,
fieldTypes: fieldTypes,
countOnly: countOnly,
isPaged: isPaged
} = options;
const d = new _deferred.Deferred;
const ajaxOptions = ajaxOptionsForRequest(protocolVersion, request, options);
_ajax.default.sendRequest(ajaxOptions).always(((obj, textStatus) => {
const transformOptions = {
deserializeDates: deserializeDates,
fieldTypes: fieldTypes
};
const tuple = interpretJsonFormat(obj, textStatus, transformOptions, ajaxOptions);
const {
error: error,
data: data,
count: count
} = tuple;
let {
nextUrl: nextUrl
} = tuple;
if (error) {
if (error.message !== _utils.XHR_ERROR_UNLOAD) {
d.reject(error)
}
} else if (countOnly) {
if (isFinite(count)) {
d.resolve(count)
} else {
d.reject(_errors.errors.Error("E4018"))
}
} else if (nextUrl && !isPaged) {
if (!isAbsoluteUrl(nextUrl)) {
nextUrl = toAbsoluteUrl(ajaxOptions.url, nextUrl)
}
sendRequest(protocolVersion, {
url: nextUrl
}, options).fail(d.reject).done((nextData => d.resolve(data.concat(nextData))))
} else {
const extra = isFinite(count) ? {
totalCount: count
} : void 0;
d.resolve(data, extra)
}
}));
return d.promise()
};
exports.sendRequest = sendRequest;
const formatDotNetError = errorObj => {
let message;
let currentMessage;
let currentError = errorObj;
if ("message" in errorObj) {
var _errorObj$message;
message = (null === (_errorObj$message = errorObj.message) || void 0 === _errorObj$message ? void 0 : _errorObj$message.value) || errorObj.message
}
while (currentError = currentError.innererror || currentError.internalexception) {
currentMessage = currentError.message;
message = currentMessage ?? message;
if (currentError.internalexception && -1 === message.indexOf("inner exception")) {
break
}
}
return message
};
const errorFromResponse = (obj, textStatus, ajaxOptions) => {
var _response, _response2, _response3, _response4;
if ("nocontent" === textStatus) {
return null
}
let message = "Unknown error";
let response = obj;
let httpStatus = 200;
const errorData = {
requestOptions: ajaxOptions
};
if ("success" !== textStatus) {
const {
status: status,
responseText: responseText
} = obj;
httpStatus = status;
message = (0, _utils.errorMessageFromXhr)(obj, textStatus);
try {
response = JSON.parse(responseText)
} catch (x) {}
}
const errorObj = (null === (_response = response) || void 0 === _response ? void 0 : _response.then) || (null === (_response2 = response) || void 0 === _response2 ? void 0 : _response2.error) || (null === (_response3 = response) || void 0 === _response3 ? void 0 : _response3["odata.error"]) || (null === (_response4 = response) || void 0 === _response4 ? void 0 : _response4["@odata.error"]);
if (errorObj) {
message = formatDotNetError(errorObj) || message;
errorData.errorDetails = errorObj;
if (200 === httpStatus) {
httpStatus = 500
}
const customCode = Number(errorObj.code);
if (isFinite(customCode) && customCode >= 400) {
httpStatus = customCode
}
}
if (httpStatus >= 400 || 0 === httpStatus) {
errorData.httpStatus = httpStatus;
return (0, _extend.extend)(Error(message), errorData)
}
return null
};
const interpretJsonFormat = (obj, textStatus, transformOptions, ajaxOptions) => {
const error = errorFromResponse(obj, textStatus, ajaxOptions);
if (error) {
return {
error: error
}
}
if (!(0, _type.isPlainObject)(obj)) {
return {
data: obj
}
}
const value = "d" in obj && (Array.isArray(obj.d) || (0, _type.isObject)(obj.d)) ? interpretVerboseJsonFormat(obj) : interpretLightJsonFormat(obj);
transformTypes(value, transformOptions);
return value
};
const interpretVerboseJsonFormat = _ref => {
let {
d: data
} = _ref;
if (!(0, _type.isDefined)(data)) {
return {
error: Error("Malformed or unsupported JSON response received")
}
}
return {
data: data.results ?? data,
nextUrl: data.__next,
count: parseInt(data.__count, 10)
}
};
const interpretLightJsonFormat = obj => ({
data: obj.value ?? obj,
nextUrl: obj["@odata.nextLink"],
count: parseInt(obj["@odata.count"], 10)
});
const EdmLiteral = exports.EdmLiteral = _class.default.inherit({
ctor(value) {
this._value = value
},
valueOf() {
return this._value
}
});
const transformTypes = function(obj) {
let options = arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {};
(0, _iterator.each)(obj, ((key, value) => {
if (null !== value && "object" === typeof value) {
if ("results" in value) {
obj[key] = value.results
}
transformTypes(obj[key], options)
} else if ("string" === typeof value) {
const {
fieldTypes: fieldTypes,
deserializeDates: deserializeDates
} = options;
const canBeGuid = !fieldTypes || "String" !== fieldTypes[key];
if (canBeGuid && GUID_REGEX.test(value)) {
obj[key] = new _guid.default(value)
}
if (false !== deserializeDates) {
if (VERBOSE_DATE_REGEX.exec(value)) {
const date = new Date(Number(RegExp.$1) + 60 * RegExp.$2 * 1e3);
obj[key] = new Date(date.valueOf() + 60 * date.getTimezoneOffset() * 1e3)
} else if (ISO8601_DATE_REGEX.test(value)) {
obj[key] = new Date(parseISO8601(obj[key]).valueOf())
}
}
}
}))
};
const serializeDate = date => `datetime'${formatISO8601(date,true,true)}'`;
const serializeString = value => `'${value.replace(/'/g,"''")}'`;
const serializePropName = propName => propName instanceof EdmLiteral ? propName.valueOf() : propName.replace(/\./g, "/");
exports.serializePropName = serializePropName;
const serializeValueV4 = value => {
if (value instanceof Date) {
return formatISO8601(value, false, false)
}
if (value instanceof _guid.default) {
return value.valueOf()
}
if (Array.isArray(value)) {
return `[${value.map((item=>serializeValueV4(item))).join(",")}]`
}
return serializeValueV2(value)
};
const serializeValueV2 = value => {
if (value instanceof Date) {
return serializeDate(value)
}
if (value instanceof _guid.default) {
return `guid'${value}'`
}
if (value instanceof EdmLiteral) {
return value.valueOf()
}
if ("string" === typeof value) {
return serializeString(value)
}
return String(value)
};
const serializeValue = (value, protocolVersion) => {
switch (protocolVersion) {
case 2:
case 3:
return serializeValueV2(value);
case 4:
return serializeValueV4(value);
default:
throw _errors.errors.Error("E4002")
}
};
exports.serializeValue = serializeValue;
const serializeKey = (key, protocolVersion) => {
if ((0, _type.isPlainObject)(key)) {
const parts = [];
(0, _iterator.each)(key, ((k, v) => parts.push(`${serializePropName(k)}=${serializeValue(v,protocolVersion)}`)));
return parts.join()
}
return serializeValue(key, protocolVersion)
};
exports.serializeKey = serializeKey;
const keyConverters = exports.keyConverters = {
String: value => `${value}`,
Int32: value => Math.floor(value),
Int64: value => value instanceof EdmLiteral ? value : new EdmLiteral(`${value}L`),
Guid: value => value instanceof _guid.default ? value : new _guid.default(value),
Boolean: value => !!value,
Single: value => value instanceof EdmLiteral ? value : new EdmLiteral(`${value}f`),
Decimal: value => value instanceof EdmLiteral ? value : new EdmLiteral(`${value}m`)
};
const convertPrimitiveValue = (type, value) => {
if (null === value) {
return null
}
const converter = keyConverters[type];
if (!converter) {
throw _errors.errors.Error("E4014", type)
}
return converter(value)
};
exports.convertPrimitiveValue = convertPrimitiveValue;
const generateSelect = (oDataVersion, select) => {
if (!select) {
return
}
return oDataVersion < 4 ? serializePropName(select.join()) : (0, _common.grep)(select, hasDot, true).join()
};
exports.generateSelect = generateSelect;
const formatCore = hash => {
let result = "";
const selectValue = [];
const expandValue = [];
(0, _iterator.each)(hash, ((key, value) => {
if (Array.isArray(value)) {
[].push.apply(selectValue, value)
}
if ((0, _type.isPlainObject)(value)) {
expandValue.push(`${key}${formatCore(value)}`)
}
}));
if (selectValue.length || expandValue.length) {
result += "(";
if (selectValue.length) {
result += `$select=${(0,_iterator.map)(selectValue,serializePropName).join()}`
}
if (expandValue.length) {
if (selectValue.length) {
result += ";"
}
result += `$expand=${(0,_iterator.map)(expandValue,serializePropName).join()}`
}
result += ")"
}
return result
};
const format = hash => {
const result = [];
(0, _iterator.each)(hash, ((key, value) => result.push(`${key}${formatCore(value)}`)));
return result.join()
};
const parseCore = (exprParts, root, stepper) => {
const result = stepper(root, exprParts.shift(), exprParts);
if (false === result) {
return
}
parseCore(exprParts, result, stepper)
};
const parseTree = (exprs, root, stepper) => (0, _iterator.each)(exprs, ((_, x) => parseCore(x.split("."), root, stepper)));
const generatorV2 = (expand, select) => {
const hash = {};
if (expand) {
(0, _iterator.each)(makeArray(expand), (function() {
hash[serializePropName(this)] = 1
}))
}
if (select) {
(0, _iterator.each)(makeArray(select), (function() {
const path = this.split(".");
if (path.length < 2) {
return
}
path.pop();
hash[serializePropName(path.join("."))] = 1
}))
}
return (0, _iterator.map)(hash, ((_, v) => v)).join()
};
const generatorV4 = (expand, select) => {
const hash = {};
if (expand || select) {
if (expand) {
parseTree(makeArray(expand), hash, ((node, key, path) => {
node[key] = node[key] || {};
return !path.length ? false : node[key]
}))
}
if (select) {
parseTree((0, _common.grep)(makeArray(select), hasDot), hash, ((node, key, path) => {
if (!path.length) {
node[key] = node[key] || [];
node[key].push(key);
return false
}
return node[key] = node[key] || {}
}))
}
return format(hash)
}
};
const generateExpand = (oDataVersion, expand, select) => oDataVersion < 4 ? generatorV2(expand, select) : generatorV4(expand, select);
exports.generateExpand = generateExpand;
const formatFunctionInvocationUrl = (baseUrl, args) => (0, _string.format)("{0}({1})", baseUrl, (0, _iterator.map)(args || {}, ((value, key) => (0, _string.format)("{0}={1}", key, value))).join(","));
exports.formatFunctionInvocationUrl = formatFunctionInvocationUrl;
const escapeServiceOperationParams = (params, version) => {
if (!params) {
return params
}
const result = {};
(0, _iterator.each)(params, ((k, v) => {
result[k] = serializeValue(v, version)
}));
return result
};
exports.escapeServiceOperationParams = escapeServiceOperationParams;