breeze-client
Version:
Breeze data management for JavaScript clients
247 lines (242 loc) • 9.62 kB
JavaScript
import * as breeze 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;
}
class UriBuilderODataAdapter {
name;
constructor() {
this.name = "odata";
}
static register(config) {
config = config || breeze.config;
config.registerAdapter("uriBuilder", UriBuilderODataAdapter);
return config.initializeAdapterInstance("uriBuilder", "odata", true);
}
initialize() { }
buildUri(entityQuery, metadataStore) {
// force entityType validation;
let entityType = entityQuery._getFromEntityType(metadataStore, false);
if (!entityType) {
// anonymous type but still has naming convention info avail
entityType = new breeze.EntityType(metadataStore);
}
let queryOptions = {};
queryOptions["$filter"] = toWhereODataFragment(entityQuery.wherePredicate);
queryOptions["$orderby"] = toOrderByODataFragment(entityQuery.orderByClause);
if (entityQuery.skipCount) {
queryOptions["$skip"] = entityQuery.skipCount;
}
if (entityQuery.takeCount != null) {
queryOptions["$top"] = entityQuery.takeCount;
}
queryOptions["$expand"] = toExpandODataFragment(entityQuery.expandClause);
queryOptions["$select"] = toSelectODataFragment(entityQuery.selectClause);
if (entityQuery.inlineCountEnabled) {
queryOptions["$inlinecount"] = "allpages";
}
const qoText = toQueryOptionsString(queryOptions);
return appendQueryStringParameter(entityQuery.resourceName, qoText);
// private methods to this func.
function toWhereODataFragment(wherePredicate) {
if (!wherePredicate)
return undefined;
// validation occurs inside of the toODataFragment call here.
let frag = wherePredicate.visit({ entityType: entityType }, toODataFragmentVisitor);
return (frag && frag.length > 0) ? frag : undefined;
}
function toOrderByODataFragment(orderByClause) {
if (!orderByClause)
return undefined;
orderByClause.validate(entityType);
let strings = orderByClause.items.map(function (item) {
return entityType.clientPropertyPathToServer(item.propertyPath, "/") + (item.isDesc ? " desc" : "");
});
// should return something like CompanyName,Address/City desc
return strings.join(',');
}
function toSelectODataFragment(selectClause) {
if (!selectClause)
return undefined;
selectClause.validate(entityType);
let frag = selectClause.propertyPaths.map(function (pp) {
return entityType.clientPropertyPathToServer(pp, "/");
}).join(",");
return frag;
}
function toExpandODataFragment(expandClause) {
if (!expandClause)
return undefined;
// no validate on expand clauses currently.
// expandClause.validate(entityType);
let frag = expandClause.propertyPaths.map(function (pp) {
return entityType.clientPropertyPathToServer(pp, "/");
}).join(",");
return frag;
}
function toQueryOptionsString(queryOptions) {
let qoStrings = [];
for (let qoName in queryOptions) {
let qoValue = queryOptions[qoName];
if (qoValue !== undefined) {
if (qoValue instanceof Array) {
qoValue.forEach(function (qov) {
qoStrings.push(qoName + "=" + encodeURIComponent(qov));
});
}
else {
qoStrings.push(qoName + "=" + encodeURIComponent(qoValue));
}
}
}
if (qoStrings.length > 0) {
return qoStrings.join("&");
}
else {
return "";
}
}
}
}
breeze.Predicate.prototype.toODataFragment = function (context) {
return this.visit(context, toODataFragmentVisitor);
};
let toODataFragmentVisitor = {
passthruPredicate: function () {
return this.value;
},
unaryPredicate: function (context) {
let predVal = this.pred.visit(context);
return odataOpFrom(this) + " " + "(" + predVal + ")";
},
binaryPredicate: function (context) {
let expr1Val = this.expr1.visit(context);
let expr2Val = this.expr2.visit(context);
let prefix = context.prefix;
if (prefix) {
expr1Val = prefix + "/" + expr1Val;
}
let odataOp = odataOpFrom(this);
if (this.op.key === 'in') {
let result = expr2Val.map(function (v) {
return "(" + expr1Val + " eq " + v + ")";
}).join(" or ");
return result;
}
else if (this.op.isFunction) {
if (odataOp === "substringof") {
return odataOp + "(" + expr2Val + "," + expr1Val + ") eq true";
}
else {
return odataOp + "(" + expr1Val + "," + expr2Val + ") eq true";
}
}
else {
return expr1Val + " " + odataOp + " " + expr2Val;
}
},
andOrPredicate: function (context) {
let result = this.preds.map(function (pred) {
let predVal = pred.visit(context);
return "(" + predVal + ")";
}).join(" " + odataOpFrom(this) + " ");
return result;
},
anyAllPredicate: function (context) {
let exprVal = this.expr.visit(context);
if (!this.pred.op) { // added 21-Oct-2016 to fix breeze.js issue #172
return exprVal + "/" + odataOpFrom(this) + "()";
}
let prefix = context.prefix;
if (prefix) {
exprVal = prefix + "/" + exprVal;
prefix = "x" + (parseInt(prefix.substring(1)) + 1);
}
else {
prefix = "x1";
}
// need to create a new context because of 'prefix'
let newContext = breeze.core.extend({}, context);
newContext.entityType = this.expr.dataType;
newContext.prefix = prefix;
let newPredVal = this.pred.visit(newContext);
return exprVal + "/" + odataOpFrom(this) + "(" + prefix + ": " + newPredVal + ")";
},
litExpr: function () {
if (Array.isArray(this.value)) {
return this.value.map(function (v) { return this.dataType.fmtOData(v); }, this);
}
else {
return this.dataType.fmtOData(this.value);
}
},
propExpr: function (context) {
let entityType = context.entityType;
// '/' is the OData path delimiter
return entityType ? entityType.clientPropertyPathToServer(this.propertyPath, "/") : this.propertyPath;
},
fnExpr: function (context) {
let exprVals = this.exprs.map(function (expr) {
return expr.visit(context);
});
return this.fnName + "(" + exprVals.join(",") + ")";
}
};
let _operatorMap = {
'contains': 'substringof'
};
function odataOpFrom(node) {
let op = node.op.key;
let odataOp = _operatorMap[op];
return odataOp || op;
}
breeze.config.registerAdapter("uriBuilder", UriBuilderODataAdapter);
/**
* Generated bundle index. Do not edit.
*/
export { UriBuilderODataAdapter };
//# sourceMappingURL=breeze-client-adapter-uri-builder-odata.mjs.map