src/Xrm.Soap.Sdk/js/xrm.soap.sdk.js
(function(global) {
global.Type.registerNamespace("Xrm.Soap.Sdk");
})(this);
(function(global) {
"use strict";
var self = this,
$ = global.$ || global.parent.$,
_ = global._,
trueString = true + "",
falseString = false + "",
notify = function(msg) {
Xrm && Xrm.Utility && Xrm.Utility.alertDialog ? Xrm.Utility.alertDialog(msg) : alert(msg);
},
htmlEncode = function(s) {
if (!s) {
return s;
}
var buffer = "",
encoded = "";
for (var count = 0, cnt = 0, l = s.length; cnt < l; cnt++) {
const c = s.charCodeAt(cnt);
if (c > 96 && c < 123 || c > 64 && c < 91 || c === 32 || c > 47 && c < 58 || c === 46 || c === 44 || c === 45 || c === 95) {
buffer += String.fromCharCode(c);
} else {
buffer += `&#${c};`;
}
if (++count === 500) {
encoded += buffer;
buffer = "";
count = 0;
}
}
if (buffer.length) {
encoded += buffer;
}
return encoded;
},
stringToDate = function(s) {
const b = s.split(/\D/);
return new Date(Date.UTC(b[0], --b[1], b[2], b[3], b[4], b[5]));
},
innerSurrogateAmpersandWorkaround = function(s) {
var buffer = "",
c0,
cnt,
l;
for (cnt = 0, l = s.length; cnt < l; cnt++) {
c0 = s.charCodeAt(cnt);
if (c0 >= 55296 && c0 <= 57343) {
if (cnt + 1 < s.length) {
const c1 = s.charCodeAt(cnt + 1);
if (c1 >= 56320 && c1 <= 57343) {
buffer += `CRMEntityReferenceOpen${((c0 - 55296) * 1024 + (c1 & 1023) + 65536).toString(16)}CRMEntityReferenceClose`;
cnt++;
} else {
buffer += String.fromCharCode(c0);
}
} else {
buffer += String.fromCharCode(c0);
}
} else {
buffer += String.fromCharCode(c0);
}
}
s = buffer;
buffer = "";
for (cnt = 0, l = s.length; cnt < l; cnt++) {
c0 = s.charCodeAt(cnt);
if (c0 >= 55296 && c0 <= 57343) {
buffer += String.fromCharCode(65533);
} else {
buffer += String.fromCharCode(c0);
}
}
return htmlEncode(buffer).replace(/CRMEntityReferenceOpen/g, "&#x").replace(/CRMEntityReferenceClose/g, ";");
},
xmlToString = function(response) {
var xmlString = "";
try {
if (response) {
if (typeof(XMLSerializer) !== "undefined" &&
typeof(response.xml) === "undefined") {
xmlString = (new XMLSerializer()).serializeToString(response[0]);
} else {
if (typeof(response.xml) !== "undefined") {
xmlString = response.xml;
} else if (typeof(response[0].xml) !== "undefined") {
xmlString = response[0].xml;
}
}
}
} catch (ex) {
notify("Cannot convert XML to a string");
}
return xmlString;
},
parseXml = function(xml) {
var notifyAboutNotSupport = function() {
notify("Cannot convert the XML string to a cross-browser XML object.");
};
if (global.DOMParser) {
// code for Mozilla, Firefox, Opera, and other normal browsers
parseXml = function(data) {
try {
const parser = new DOMParser();
return parser.parseFromString(data, "text/xml");
} catch (ex) {
return notifyAboutNotSupport();
}
};
} else {
// IE
parseXml = function(data) {
try {
const xmlDoc = new global.ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async = false;
xmlDoc.loadXML(data);
return xmlDoc;
} catch (ex) {
return notifyAboutNotSupport();
}
};
}
return parseXml(xml);
},
crmXmlDecode = function(s) {
return typeof(s) === "string" ? s : s.toString();
},
crmXmlEncode = function(s) {
const stype = typeof(s);
// ReSharper disable once ConditionIsAlwaysConst - weird IE it's for you
if (stype === "undefined" || stype === "unknown") {
return s;
} else if (stype !== "string") {
s = s.toString();
}
return innerSurrogateAmpersandWorkaround(s);
},
encodeValue = function(value) {
if (value === null || value === "undefined") {
return null;
}
if (value && value.type === "guid") {
return value.value;
}
if (value && typeof(value) === typeof("") && value.slice(0, 1) === "{" && value.slice(-1) === "}") {
value = value.slice(1, -1);
}
return value && typeof(value) === "object" && value.getTime ? value.toISOString() : crmXmlEncode(value);
},
isMetadataArray = (function() {
var arrayElements = [
"Attributes",
"ManyToManyRelationships",
"ManyToOneRelationships",
"OneToManyRelationships",
"Privileges",
"LocalizedLabels",
"Options",
"Targets"
];
if (typeof(Array.prototype.some) === "function") {
return function(elementName) {
return arrayElements.some(function(value, index, array) {
return elementName === array[index];
});
};
} else {
return function(elementName) {
for (var i = 0, l = arrayElements.length; i < l; i++) {
if (elementName === arrayElements[i]) {
return true;
}
}
return false;
};
}
})(),
getNodeName = function(node) {
return typeof(node.baseName) !== "undefined" ? node.baseName : node.localName;
},
objectifyNode = function(node) {
if (node.attributes && node.attributes.length === 1) {
var nil = node.attributes.getNamedItem("i:nil");
if (nil && nil.nodeValue === trueString) {
return null;
}
}
if (node.firstChild && node.firstChild.nodeType === 3) {
var nodeName = getNodeName(node),
nodeValue = node.firstChild.nodeValue,
parseIntFunc = function() {
return parseInt(nodeValue, 10);
},
parseBoolFunc = function() {
return nodeValue === trueString ? true : false;
},
nodeNames = {
ActivityTypeMask: parseIntFunc,
ObjectTypeCode: parseIntFunc,
ColumnNumber: parseIntFunc,
DefaultFormValue: parseIntFunc,
MaxValue: parseIntFunc,
MinValue: parseIntFunc,
MaxLength: parseIntFunc,
Order: parseIntFunc,
Precision: parseIntFunc,
PrecisionSource: parseIntFunc,
LanguageCode: parseIntFunc,
AutoRouteToOwnerQueue: parseBoolFunc,
CanBeChanged: parseBoolFunc,
CanTriggerWorkflow: parseBoolFunc,
IsActivity: parseBoolFunc,
IsActivityParty: parseBoolFunc,
IsAvailableOffline: parseBoolFunc,
IsChildEntity: parseBoolFunc,
IsCustomEntity: parseBoolFunc,
IsCustomOptionSet: parseBoolFunc,
IsDocumentManagementEnabled: parseBoolFunc,
IsEnabledForCharts: parseBoolFunc,
IsGlobal: parseBoolFunc,
IsImportable: parseBoolFunc,
IsIntersect: parseBoolFunc,
IsManaged: parseBoolFunc,
IsReadingPaneEnabled: parseBoolFunc,
IsValidForAdvancedFind: parseBoolFunc,
CanBeSecuredForCreate: parseBoolFunc,
CanBeSecuredForRead: parseBoolFunc,
CanBeSecuredForUpdate: parseBoolFunc,
IsCustomAttribute: parseBoolFunc,
IsPrimaryId: parseBoolFunc,
IsPrimaryName: parseBoolFunc,
IsSecured: parseBoolFunc,
IsValidForCreate: parseBoolFunc,
IsValidForRead: parseBoolFunc,
IsValidForUpdate: parseBoolFunc,
IsCustomRelationship: parseBoolFunc,
CanBeBasic: parseBoolFunc,
CanBeDeep: parseBoolFunc,
CanBeGlobal: parseBoolFunc,
CanBeLocal: parseBoolFunc,
Value: function() {
if (nodeValue === trueString || nodeValue === falseString) {
return nodeValue === trueString ? true : false;
}
if (nodeValue === "ApplicationRequired" ||
nodeValue === "None" ||
nodeValue === "Recommended" ||
nodeValue === "SystemRequired") {
return nodeValue;
} else {
return parseInt(nodeValue, 10);
}
}
};
if (nodeNames.hasOwnProperty(nodeName)) {
return nodeNames[nodeName]();
} else {
return nodeValue;
}
}
var i, l, typeItem;
if (isMetadataArray(getNodeName(node))) {
var arrayValue = [],
counter = 0;
for (i = 0, l = node.childNodes.length; i < l; i++) {
var objectTypeName,
attrs = node.childNodes[i].attributes;
if (attrs && (typeItem = attrs.getNamedItem("i:type"))) {
objectTypeName = typeItem.nodeValue.split(":")[1];
} else {
objectTypeName = getNodeName(node.childNodes[i]);
}
var b = objectifyNode(node.childNodes[i]);
b._type = objectTypeName;
arrayValue[counter++] = b;
}
return arrayValue;
}
if (!node.childNodes.length) {
return null;
}
var c = {};
if ((typeItem = node.attributes.getNamedItem("i:type"))) {
c._type = typeItem.nodeValue.split(":")[1];
}
for (i = 0, l = node.childNodes.length; i < l; i++) {
var childNode = node.childNodes[i];
if (childNode.nodeType === 3) {
c[getNodeName(childNode)] = childNode.nodeValue;
} else {
c[getNodeName(childNode)] = objectifyNode(childNode);
}
}
return c;
},
publishersPrefixes = [""],
context = typeof(global.GetGlobalContext) === "function" ? global.GetGlobalContext() : global.Xrm.Page.context,
loc = global.location,
clientUrl = context.getClientUrl(),
splittedUrl = clientUrl.replace(/^(http|https):\/\/([_a-zA-Z0-9\-\.]+)(:([0-9]{1,5}))?/, loc.protocol + "//" + loc.host).split(/\/+/g),
xrmServiceUrl = "/XRMServices/2011/Organization.svc/web",
contractsXrmNs = "http://schemas.microsoft.com/xrm/2011/Contracts",
contractsCrmNs = "http://schemas.microsoft.com/crm/2011/Contracts",
xrmSoapActionPrefix = contractsXrmNs + "/Services/IOrganizationService/",
xmlSchemaNs = "http://www.w3.org/2001/XMLSchema",
xmlSchemaInstanceNs = xmlSchemaNs + "-instance",
serializationNs = "http://schemas.microsoft.com/2003/10/Serialization/",
arraysNs = serializationNs + "Arrays",
genericNs = "http://schemas.datacontract.org/2004/07/System.Collections.Generic",
metadataNs = "http://schemas.microsoft.com/xrm/2011/Metadata",
utf8Root = "<?xml version='1.0' encoding='utf-8'?>",
orgName = context.getOrgUniqueName(),
compile = _.template,
attributeTemplate = compile("<b:string><%= value %></b:string>"),
noLockTemplate = compile("<a:noLock><%= noLock %></a:noLock>"),
distinctTemplate = compile("<a:distinct><%= distinct %></a:distinct>"),
entityNameTemplate = compile("<a:EntityName><%= name %></a:EntityName>"),
hasOwnProp = Object.prototype.hasOwnProperty,
extend = function(child, base) {
// ReSharper disable once MissingHasOwnPropertyInForeach
for (let key in base) {
if (hasOwnProp.call(base, key)) {
child[key] = base[key];
}
}
const Ctor = function() {
this.constructor = child;
};
Ctor.prototype = base.prototype;
child.prototype = new Ctor();
child.base = base.prototype;
return child;
};
if (loc.host.indexOf("localhost") !== -1) {
splittedUrl[1] = loc.host;
}
this.init = function(prefixes) {
publishersPrefixes = _.union(publishersPrefixes, prefixes);
};
this.ColumnSet = (function() {
const columnsTemplate = compile(`<a:AllColumns><%= allColumns %></a:AllColumns><a:Columns xmlns:b='${arraysNs}'><% _.each(columns, function(column) { %><%= column %><% }) %></a:Columns>`);
const columnSetTemplate = compile("<a:ColumnSet><%= columnSet %></a:ColumnSet>");
const asLinkColumnSetTemplate = compile("<a:Columns><%= columnSet %></a:Columns>");
const simpleColumnSetTemplate = compile(`<columnSet xmlns:a='${contractsXrmNs}'><%= columnSet %></columnSet>`);
const initColumns = function(columns) {
if (columns && columns.length) {
if (columns.length === 1 && $.isArray(columns[0])) {
return columns[0];
} else if (typeof(columns[0]) === "boolean") {
return [columns[0]];
} else {
return columns;
}
}
return [false];
};
const getColumnSetTemplate = function(asLink, simple) {
if (asLink) {
return asLinkColumnSetTemplate;
} else if (simple) {
return simpleColumnSetTemplate;
}
return columnSetTemplate;
};
const getSoap = function(asLink, simple, allColumns, columns) {
return getColumnSetTemplate(asLink, simple)({
columnSet: columnsTemplate({ allColumns: allColumns, columns: columns })
});
};
const ctor = function() {
this.columns = initColumns(arguments);
this.count = this.columns.length;
};
ctor.prototype.addColumn = function(columnName) {
if (typeof(this.columns[0]) !== "boolean") {
this.columns[this.count] = columnName;
this.count++;
}
};
ctor.prototype.serialize = function(asLink, simple) {
if (this.count) {
if (this.columns[0] === true) {
return getSoap(asLink, simple, true, []);
}
let columns = [];
if (this.columns[0] !== false) {
columns = _.map(this.columns, function(column) {
return attributeTemplate({ value: column });
});
}
return getSoap(asLink, simple, false, columns);
} else {
return getSoap(asLink, simple, false, []);
}
};
ctor.getAllColumnsSoap = function(asLink, simple) {
return getSoap(asLink, simple, true, []);
};
return ctor;
})();
this.ConditionOperator = (function() {
return {
Equal: "Equal",
NotEqual: "NotEqual",
GreaterThan: "GreaterThan",
LessThan: "LessThan",
GreaterEqual: "GreaterEqual",
LessEqual: "LessEqual",
Like: "Like",
NotLike: "NotLike",
In: "In",
NotIn: "NotIn",
Between: "Between",
NotBetween: "NotBetween",
Null: "Null",
NotNull: "NotNull",
Yesterday: "Yesterday",
Today: "Today",
Tomorrow: "Tomorrow",
Last7Days: "Last7Days",
Next7Days: "Next7Days",
LastWeek: "LastWeek",
ThisWeek: "ThisWeek",
NextWeek: "NextWeek",
LastMonth: "LastMonth",
ThisMonth: "ThisMonth",
NextMonth: "NextMonth",
On: "On",
OnOrBefore: "OnOrBefore",
OnOrAfter: "OnOrAfter",
LastYear: "LastYear",
ThisYear: "ThisYear",
NextYear: "NextYear",
LastXHours: "LastXHours",
NextXHours: "NextXHours",
LastXDays: "LastXDays",
NextXDays: "NextXDays",
LastXWeeks: "LastXWeeks",
NextXWeeks: "NextXWeeks",
LastXMonths: "LastXMonths",
NextXMonths: "NextXMonths",
LastXYears: "LastXYears",
NextXYears: "NextXYears",
EqualUserId: "EqualUserId",
NotEqualUserId: "NotEqualUserId",
EqualBusinessId: "EqualBusinessId",
NotEqualBusinessId: "NotEqualBusinessId",
ChildOf: "ChildOf",
Mask: "Mask",
NotMask: "NotMask",
MasksSelect: "MasksSelect",
Contains: "Contains",
DoesNotContain: "DoesNotContain",
EqualUserLanguage: "EqualUserLanguage",
NotOn: "NotOn",
OlderThanXMonths: "OlderThanXMonths",
BeginsWith: "BeginsWith",
DoesNotBeginWith: "DoesNotBeginWith",
EndsWith: "EndsWith",
DoesNotEndWith: "DoesNotEndWith",
ThisFiscalYear: "ThisFiscalYear",
ThisFiscalPeriod: "ThisFiscalPeriod",
NextFiscalYear: "NextFiscalYear",
NextFiscalPeriod: "NextFiscalPeriod",
LastFiscalYear: "LastFiscalYear",
LastFiscalPeriod: "LastFiscalPeriod",
LastXFiscalYears: "LastXFiscalYears",
LastXFiscalPeriods: "LastXFiscalPeriods",
NextXFiscalYears: "NextXFiscalYears",
NextXFiscalPeriods: "NextXFiscalPeriods",
InFiscalYear: "InFiscalYear",
InFiscalPeriod: "InFiscalPeriod",
InFiscalPeriodAndYear: "InFiscalPeriodAndYear",
InOrBeforeFiscalPeriodAndYear: "InOrBeforeFiscalPeriodAndYear",
InOrAfterFiscalPeriodAndYear: "InOrAfterFiscalPeriodAndYear",
EqualUserTeams: "EqualUserTeams"
};
})();
this.OrderType = (function() {
return {
Ascending: "Ascending",
Descending: "Descending"
};
})();
this.OrderExpression = (function() {
const orderTemplate = compile("<a:OrderExpression><a:AttributeName><%= attributeName %></a:AttributeName><a:OrderType><%= orderType %></a:OrderType></a:OrderExpression>");
/**
* OrderExpression for use with QueryByAttribute
* @param {String} attributeName
* @param {OrderType} orderType
*/
const ctor = function(attributeName, orderType) {
this.attributeName = attributeName;
this.orderType = !orderType ? self.OrderType.Descending : orderType;
};
ctor.prototype.serialize = function() {
return orderTemplate({
attributeName: this.attributeName,
orderType: this.orderType
});
};
return ctor;
})();
this.ConditionExpression = (function() {
const valueTemplate = compile("<b:anyType i:type='c:<%= type %>' xmlns:c='<%= xmlns %>'><%= value %></b:anyType>");
const valuesTemplate = compile(`<a:Values xmlns:b='${arraysNs}'><% _.each(values, function(value) { %><%= value %><% }) %></a:Values>`);
const conditionExpressionTemplate = compile("<a:ConditionExpression><a:AttributeName><%= attributeName %></a:AttributeName><a:Operator><%= operator %></a:Operator><%= values %></a:ConditionExpression>");
/**
* ConditionExpression for use with QueryByAttribute/QueryExpression
* @param {String} attributeName - Name of ordering by attribute
* @param {ConditionOperator} operator - Condition operator
* @param {Array} values - Condition values
*/
const ctor = function(attributeName, operator, values) {
this.attributeName = attributeName;
this.operator = operator;
this.values = values; // ToDo: param array
};
ctor.prototype.serialize = function() {
if (this.values && this.values.length) {
const values = _.map(this.values, function(value) {
const typed = value.hasOwnProperty("type");
return valueTemplate({
type: typed ? value.type : "string",
xmlns: value instanceof self.StateCode || value instanceof self.StatusCode || !typed ? xmlSchemaNs : serializationNs,
value: value.hasOwnProperty("value") ? value.value : value
});
});
return conditionExpressionTemplate({
attributeName: this.attributeName,
operator: this.operator,
values: valuesTemplate({ values: values })
});
} else {
return conditionExpressionTemplate({
attributeName: this.attributeName,
operator: this.operator,
values: []
});
}
};
return ctor;
})();
this.FilterOperator = (function() {
return {
And: "And",
Or: "Or"
};
})();
this.FilterExpression = (function() {
const template = compile([
"<a:LinkCriteria>",
"<a:Conditions>",
"<% _.each(conditions, function(condition) { %><%= condition %><% }) %>",
"</a:Conditions>",
"<a:FilterOperator>",
"<%= filterOperator %>",
"</a:FilterOperator>",
"</a:LinkCriteria>"
].join(""));
const ctor = function(logicalOperator) {
this.conditions = [];
this.filterOperator = logicalOperator ? logicalOperator : self.FilterOperator.And;
};
/**
* Add condition expression to conditions list
* @param {ConditionExpression} condition
*/
ctor.prototype.addCondition = function(condition) {
condition && condition instanceof self.ConditionExpression && (this.conditions[this.conditions.length] = condition);
};
ctor.prototype.addConditions = function(/* conditions list */) {
if (arguments && arguments.length) {
let count = this.conditions.length;
for (let i = arguments.length; i--;) {
const condition = arguments[i];
condition && condition instanceof self.ConditionExpression && (this.conditions[count++] = condition);
}
}
};
ctor.prototype.setFilterOperator = function(logicalOperator) {
logicalOperator && (this.filterOperator = logicalOperator);
};
ctor.prototype.serialize = function() {
if (!this.conditions.length) {
return template({
conditions: [],
filterOperator: this.filterOperator
});
}
return template({
conditions: _.map(this.conditions, function(condition) {
return condition.serialize();
}),
filterOperator: this.filterOperator
});
};
return ctor;
})();
this.JoinOperator = (function() {
return {
Inner: "Inner",
LeftOuter: "LeftOuter",
Natural: "Natural"
};
})();
this.LinkEntity = (function() {
const template = compile([
"<a:LinkEntity>",
"<%= columns %>",
"<a:EntityAlias i:nil='true'/>",
"<a:JoinOperator>",
"<%= joinOperator %>",
"</a:JoinOperator>",
"<%= linkCriteria %>",
"<a:LinkFromAttributeName>",
"<%= linkFromAttributeName %>",
"</a:LinkFromAttributeName>",
"<a:LinkFromEntityName>",
"<%= linkFromEntityName %>",
"</a:LinkFromEntityName>",
"<a:LinkToAttributeName>",
"<%= linkToAttributeName %>",
"</a:LinkToAttributeName>",
"<a:LinkToEntityName>",
"<%= linkToEntityName %>",
"</a:LinkToEntityName>",
"</a:LinkEntity>"
].join(""));
/**
* LinkEntity like in Microsoft.Xrm.Sdk
* @param {String} linkFromEntityName
* @param {String} linkToEntityName
* @param {String} linkFromAttributeName
* @param {String} linkToAttributeName
* @param {JoinOperator} joinOperator
*/
const ctor = function(linkFromEntityName, linkToEntityName, linkFromAttributeName, linkToAttributeName, joinOperator) {
this.linkFromEntityName = linkFromEntityName;
this.linkToEntityName = linkToEntityName;
this.linkFromAttributeName = linkFromAttributeName;
this.linkToAttributeName = linkToAttributeName;
this.joinOperator = joinOperator;
};
/**
* Set filter expression as link criteria
* @param {FilterExpression} filterExpression - Current filter criteria
*/
ctor.prototype.setLinkCriteria = function(filterExpression) {
this.linkCriteria = filterExpression;
};
ctor.prototype.setColumns = function(columnSet) {
columnSet && columnSet instanceof self.ColumnSet && (this.columns = columnSet);
};
ctor.prototype.serialize = function() {
return template({
columns: (this.columns ? this.columns : new self.ColumnSet(false)).serialize(true),
joinOperator: this.joinOperator,
linkCriteria: this.linkCriteria ? this.linkCriteria.serialize() : "",
linkFromAttributeName: this.linkFromAttributeName,
linkFromEntityName: this.linkFromEntityName,
linkToAttributeName: this.linkToAttributeName,
linkToEntityName: this.linkToEntityName
});
};
return ctor;
})();
this.PageInfo = (function() {
const template = compile([
"<a:PageInfo>",
"<a:Count><%= count %></a:Count>",
"<a:PageNumber><%= pageNumber %></a:PageNumber>",
"<a:PagingCookie i:nil='true'/>",
"<a:ReturnTotalRecordCount><%= returnTotalRecordCount %></a:ReturnTotalRecordCount>",
"</a:PageInfo>"
].join(""));
const ctor = function(count, pageNumber, returnTotalRecordCount) {
this.count = count || 0;
this.pageNumber = pageNumber || 0;
this.returnTotalRecordCount = returnTotalRecordCount || false;
};
ctor.prototype.serialize = function() {
return template({
count: this.count,
pageNumber: this.pageNumber,
returnTotalRecordCount: this.returnTotalRecordCount
});
};
var instance;
ctor.instance = function() {
instance = instance || new self.PageInfo();
return instance;
};
return ctor;
})();
this.QueryByAttribute = (function() {
const queryTemplate = compile(`<query i:type='a:QueryByAttribute' xmlns:a='${contractsXrmNs}'><%= query %></query>`);
const ordersTemplate = compile("<a:Orders><% _.each(orders, function(order) { %><%= order %><% }) %></a:Orders>");
const attributesTemplate = compile(`<a:Attributes xmlns:b='${arraysNs}'><% _.each(attributes, function(attribute) { %><%= attribute %><% }) %></a:Attributes>`);
const valuesTemplate = compile(`<a:Values xmlns:b='${arraysNs}'><% _.each(values, function(value) { %><%= value %><% }) %></a:Values>`);
const valueTemplate = compile(`<b:anyType i:type='c:<%= type %>' xmlns:c='${xmlSchemaNs}'><%= value %></b:anyType>`);
const topCountTemplate = compile("<a:topCount<% if (topCount === null) { %> i:nil='true'<% } %>><%= topCount %></a:topCount>");
/**
* QueryByAttribute like in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Array<String>} attributes
* @param {Array} values
* @param {ColumnSet} columnSet
* @param {Number} topCount
*/
const ctor = function(entityName, attributes, values, columnSet, topCount) {
this.entityName = entityName;
this.attributes = attributes;
this.values = values;
this.columns = columnSet || new self.ColumnSet(false);
this.distinct = false;
this.noLock = false;
this.orders = [];
this.topCount = topCount || null;
this.pageInfo = self.PageInfo.instance();
};
/**
* Add order expression to current query
* @param {OrderExpression} order
*/
ctor.prototype.addOrder = function(order) {
order && order instanceof self.OrderExpression && (this.orders[this.orders.length] = order);
};
/**
* Add order expressions to current query
* @param {Array<OrderExpression>} orders
*/
ctor.prototype.addOrders = function(/* order list */) {
if (arguments && arguments.length) {
let counter = this.orders.length;
for (var i = 0, l = arguments.length; i < l; i++) {
const order = arguments[i];
order && order instanceof self.OrderExpression && (this.orders[counter++] = order);
}
}
};
ctor.prototype.distinct = function(/* value */) {
if (arguments && arguments.length === 1) {
this.distinct = !!arguments[0];
}
return this.distinct;
};
ctor.prototype.noLock = function(/* value */) {
if (arguments && arguments.length === 1) {
this.noLock = !!arguments[0];
}
return this.noLock;
};
ctor.prototype.pageInfo = function(/* value */) {
if (arguments && arguments.length === 1 && arguments[0] instanceof self.PageInfo) {
this.pageInfo = arguments[0];
}
return this.pageInfo;
};
ctor.prototype.serialize = function() {
// ToDo: improve result creation
var result = [];
if (this.attributes.length) {
result.push(attributesTemplate({
attributes: _.map(this.attributes, function(attr) {
return attributeTemplate({ value: attr });
})
}));
}
result.push(this.columns.serialize());
result.push(entityNameTemplate({ name: this.entityName }));
if (this.orders && this.orders.length) {
result.push(ordersTemplate({
orders: _.map(this.orders, function(order) {
return order.serialize();
})
}));
}
result.push(this.pageInfo.serialize());
if (this.attributes.length) {
result.push(valuesTemplate({
values: _.map(this.values, function(value) {
const typed = value.hasOwnProperty("type");
return valueTemplate({
type: typed ? value.type : "string",
value: value.hasOwnProperty("value") ? value.value : value
});
})
}));
}
result.push(distinctTemplate({ distinct: this.distinct }));
result.push(noLockTemplate({ noLock: this.noLock }));
result.push(topCountTemplate({ topCount: this.topCount }));
return queryTemplate({ query: result.join("") });
};
return ctor;
})();
this.QueryExpression = (function() {
const queryTemplate = compile(`<query i:type='a:QueryExpression' xmlns:a='${contractsXrmNs}'><%= query %></query>`);
const criteriaTemplate = compile("<a:Criteria><%= conditions %><a:FilterOperator><%= filterOperator %></a:FilterOperator><a:Filters></a:Filters></a:Criteria>");
const conditionsTemplate = compile("<a:Conditions><% _.each(conditions, function(condition) { %><%= condition.serialize() %><% }) %></a:Conditions>");
const linkEntitiesTemplate = compile("<a:LinkEntities><% _.each(linkEntities, function(entity) { %><%= entity.serialize() %><% }) %></a:LinkEntities>");
const ordersTemplate = compile("<a:Orders><% _.each(orders, function(order) { %><%= order.serialize() %><% }) %></a:Orders>");
const topCountTemplate = compile("<a:topCount <% if (topCount === null) { %> i:nil='true'<% } %>><%= topCount %></a:topCount>");
/**
* QueryByAttribute like in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Array<ConditionExpression>} conditions
* @param {(Array|ColumnSet)} columnSet
*/
const ctor = function(entityName, conditions, columnSet) {
this.entityName = entityName;
this.conditions = conditions;
this.filterOperator = self.FilterOperator.And;
this.columnSet = columnSet || new self.ColumnSet(false);
this.distinct = false;
this.noLock = false;
this.orders = [];
this.linkEntities = [];
this.pageInfo = self.PageInfo.instance();
this.topCount = null;
};
/**
* Add order expression to current query
* @param {OrderExpression} order
*/
ctor.prototype.addOrder = function(order) {
order && order instanceof self.OrderExpression && (this.orders[this.orders.length] = order);
};
ctor.prototype.addOrders = function(/* order list */) {
if (arguments && arguments.length) {
let counter = this.orders.length;
for (var i = 0, l = arguments.length; i < l; i++) {
const order = arguments[i];
order && order instanceof self.OrderExpression && (this.orders[counter++] = order);
}
}
};
/**
* Set filter operator to current query
* @param {OrderExpression} filterOperator
*/
ctor.prototype.setFilterOperator = function(filterOperator) {
filterOperator && (this.filterOperator = filterOperator);
};
/**
* Add linked entity to current query
* @param {LinkEntity} linkEntity
* @returns {Void}
*/
ctor.prototype.addLink = function(linkEntity) {
linkEntity && linkEntity instanceof self.LinkEntity && (this.linkEntities[this.linkEntities.length] = linkEntity);
};
ctor.prototype.addLinks = function(/* linkEntity list */) {
if (arguments && arguments.length) {
let counter = this.linkEntities.length;
for (var i = 0, l = arguments.length; i < l; i++) {
const linkEntity = arguments[i];
linkEntity && linkEntity instanceof self.LinkEntity && (this.linkEntities[counter++] = linkEntity);
}
}
};
ctor.prototype.distinct = function(/* value */) {
if (arguments && arguments.length === 1) {
this.distinct = !!arguments[0];
}
return this.distinct;
};
ctor.prototype.noLock = function(/* value */) {
if (arguments && arguments.length === 1) {
this.noLock = !!arguments[0];
}
return this.noLock;
};
ctor.prototype.pageInfo = function(/* value */) {
if (arguments && arguments.length === 1 && arguments[0] instanceof self.PageInfo) {
this.pageInfo = arguments[0];
}
return this.pageInfo;
};
ctor.prototype.topCount = function(/* value */) {
if (arguments && arguments.length === 1 && typeof(arguments[0]) === "number") {
this.topCount = parseInt(arguments[0], 10);
}
return this.topCount;
};
ctor.prototype.serialize = function() {
// ToDo: improve result accumulation
var result = [this.columnSet ? this.columnSet.serialize() : self.ColumnSet.getAllColumnsSoap()];
result.push(criteriaTemplate({
conditions: this.conditions && this.conditions.length ? conditionsTemplate({ conditions: this.conditions }) : "<a:Conditions/>",
filterOperator: this.filterOperator
}));
result.push(distinctTemplate({ distinct: this.distinct }));
result.push(entityNameTemplate({ name: this.entityName }));
if (this.orders && this.orders.length) {
result.push(ordersTemplate({ orders: this.orders }));
}
if (this.linkEntities && this.linkEntities.length) {
result += linkEntitiesTemplate({ linkEntities: this.linkEntities });
} else {
result.push("<a:LinkEntities/>");
}
result.push(this.pageInfo.serialize());
result.push(noLockTemplate({ noLock: this.noLock }));
result.push(topCountTemplate({ topCount: this.topCount }));
return queryTemplate({ query: result.join("") });
};
return ctor;
})();
this.Entity = (function() {
/**
* Universal class for creating, updating and deleting any entity
* @param {String} logicalName
* @param {Guid} id
*/
const entity = function(logicalName, id) {
this.attributes = {};
this.logicalName = logicalName;
this.id = id && id.type === "guid" ? id : new self.Guid(id || self.Guid.empty());
};
entity.prototype = {
/**
* Get entity attribute by name
* @param {String} name
*/
getAttribute: function(name) {
return this.attributes[name] || null;
},
getAttributeValue: function(name) {
const attr = this.getAttribute(name);
if (attr) {
return attr.hasOwnProperty("value") ? attr.value : attr;
}
return null;
},
/**
* Set entity attribute
* @param {String} name
* @param {any} attribute
*/
setAttribute: function(name, attribute) {
name && (this.attributes[name] = attribute);
},
getName: function() {
if (this.logicalName === "systemuser") {
return this.getAttributeValue("fullname");
}
for (let i = publishersPrefixes.length; i--;) {
const name = this.getAttributeValue(publishersPrefixes[i] + "name");
if (name) {
return name;
}
}
return "";
},
logicalName: function() {
return this.logicalName;
},
getIdValue: function() {
return this.id.value;
},
getId: function(id) {
if (id) {
this.id = id.type === "guid" ? id : new self.Guid(id);
}
return this.id;
},
toEntityReference: function() {
return new self.EntityReference(
this.logicalName(),
this.getId(),
this.getName());
},
toLookupValue: function() {
return [{
id: this.getIdValue(),
name: this.getName(),
entityType: this.logicalName()
}];
},
clone: function() {
const clone = new self.Entity(this.logicalName);
const attributes = this.attributes;
for (let name in attributes) {
if (attributes.hasOwnProperty(name)) {
if (hasOwnProp.call(attributes, name)) {
clone.setAttribute(name, attributes[name]);
}
}
}
if (this.logicalName + "id" in clone.attributes) {
delete clone.attributes[this.logicalName + "id"];
}
return clone;
},
serialize: function() {
var xml = [`<entity xmlns:a='${contractsXrmNs}'>`],
counter = 1;
xml[counter++] = `<a:Attributes xmlns:b='${genericNs}'>`;
// ReSharper disable once MissingHasOwnPropertyInForeach
for (var attributeName in this.attributes) {
var attribute = this.attributes[attributeName];
xml[counter++] = "<a:KeyValuePairOfstringanyType>";
xml[counter++] = `<b:key>${attributeName}</b:key>`;
if (attribute === null || attribute.value === null) {
xml[counter++] = "<b:value i:nil='true'/>";
} else {
var sType = attribute.type ? crmXmlEncode(attribute.type) : typeof(attribute),
value,
encodedValue,
id,
encodedId,
logicalName,
encodedLogicalName;
value = attribute.hasOwnProperty("value") ? attribute.value : attribute;
encodedValue = attributeName === "documentbody" ? value : encodeValue(value);
switch (sType) {
case "OptionSetValue":
xml[counter++] = "<b:value i:type='a:OptionSetValue'>";
xml[counter++] = `<a:Value>${encodedValue}</a:Value></b:value>`;
break;
case "EntityCollection":
xml[counter++] = "<b:value i:type='a:EntityCollection'>";
xml[counter++] = "<a:Entities>";
var collections = $.isArray(value) ? value : [value];
for (var i = 0, l = collections.length; i < l; i++) {
var item = collections[i];
id = item.hasOwnProperty("id") ? item.id : item;
encodedId = encodeValue(id);
logicalName = item.hasOwnProperty("logicalName") ? item.logicalName : item;
encodedLogicalName = encodeValue(logicalName);
xml[counter++] = "<a:Entity>";
xml[counter++] = "<a:Attributes>";
xml[counter++] = "<a:KeyValuePairOfstringanyType>";
xml[counter++] = "<b:key>partyid</b:key>";
xml[counter++] = "<b:value i:type='a:EntityReference'>";
xml[counter++] = `<a:Id>${encodedId}</a:Id>`;
xml[counter++] = `<a:LogicalName>${encodedLogicalName}</a:LogicalName>`;
xml[counter++] = "<a:Name i:nil='true'/>";
xml[counter++] = "</b:value>";
xml[counter++] = "</a:KeyValuePairOfstringanyType>";
xml[counter++] = "</a:Attributes>";
xml[counter++] = "<a:EntityState i:nil='true'/>";
xml[counter++] = "<a:FormattedValues />";
xml[counter++] = `<a:Id>${self.Guid.empty().value}</a:Id>`;
xml[counter++] = "<a:LogicalName>activityparty</a:LogicalName>";
xml[counter++] = "<a:RelatedEntities />";
xml[counter++] = "</a:Entity>";
}
xml[counter++] = "</a:Entities>";
xml[counter++] = "<a:EntityName i:nil='true'/>";
xml[counter++] = "<a:MinActiveRowVersion i:nil='true'/>";
xml[counter++] = "<a:MoreRecords>false</a:MoreRecords>";
xml[counter++] = "<a:PagingCookie i:nil='true'/>";
xml[counter++] = "<a:TotalRecordCount>0</a:TotalRecordCount>";
xml[counter++] = "<a:TotalRecordCountLimitExceeded>false</a:TotalRecordCountLimitExceeded>";
xml[counter++] = "</b:value>";
break;
case "EntityReference":
id = attribute.hasOwnProperty("id") ? attribute.id : attribute;
encodedId = encodeValue(id);
logicalName = attribute.hasOwnProperty("logicalName") ? attribute.logicalName : attribute;
encodedLogicalName = encodeValue(logicalName);
xml[counter++] = "<b:value i:type='a:EntityReference'>";
xml[counter++] = `<a:Id>${encodedId}</a:Id>`;
xml[counter++] = `<a:LogicalName>${encodedLogicalName}</a:LogicalName>`;
xml[counter++] = "<a:Name i:nil='true'/>" + "</b:value>";
break;
case "Money":
xml[counter++] = "<b:value i:type='a:Money'>";
xml[counter++] = `<a:Value>${encodedValue}</a:Value></b:value>`;
break;
case "guid":
xml[counter++] = `<b:value i:type='c:guid' xmlns:c='${serializationNs}'>`;
xml[counter++] = encodedValue + "</b:value>";
break;
case "decimal":
xml[counter++] = `<b:value i:type='c:decimal' xmlns:c='${xmlSchemaNs}'>`;
xml[counter++] = encodedValue + "</b:value>";
break;
case "number":
// eslint-disable-next-line eqeqeq
var oType = parseInt(encodedValue, 10) == encodedValue ? "int" : "double";
xml[counter++] = `<b:value i:type='c:${oType}' xmlns:c='${xmlSchemaNs}'>`;
xml[counter++] = encodedValue + "</b:value>";
break;
default:
sType = typeof(value) === "object" && value.getTime ? "dateTime" : sType;
xml[counter++] = `<b:value i:type='c:${sType}' xmlns:c='${xmlSchemaNs}'>${encodedValue}</b:value>`;
break;
}
}
xml[counter++] = "</a:KeyValuePairOfstringanyType>";
}
xml[counter++] = "</a:Attributes>";
xml[counter++] = "<a:EntityState i:nil='true'/>";
xml[counter++] = `<a:FormattedValues xmlns:b='${genericNs}'/>`;
xml[counter++] = `<a:Id>${encodeValue(this.guid)}</a:Id>`;
xml[counter++] = `<a:LogicalName>${this.logicalName}</a:LogicalName>`;
xml[counter++] = `<a:RelatedEntities xmlns:b='${genericNs}'/>`;
xml[counter++] = "</entity>";
return xml.join("");
}
};
entity.deserialize = function(resultNode) {
var obj = {},
resultNodes = resultNode.childNodes,
instance = new self.Entity(),
getEntityReference = function(nodesList) {
const attrs = _.chain(nodesList).map(function(n) {
return {
name: n.nodeName,
value: $(n).text()
};
}).reduce(function(o, a) {
o[a.name] = a.value;
return o;
}, {}).value();
return new self.EntityReference(attrs["a:LogicalName"], attrs["a:Id"], attrs["a:Name"]);
};
for (var j = 0, rl = resultNodes.length; j < rl; j++) {
var k,
l,
al,
cnl,
attr,
sKey;
switch (resultNodes[j].nodeName) {
case "a:Attributes":
attr = resultNodes[j];
for (k = 0, cnl = attr.childNodes.length; k < cnl; k++) {
sKey = $(attr.childNodes[k].firstChild).text();
var sType = "",
attributes = attr.childNodes[k].childNodes[1].attributes;
for (l = 0, al = attributes.length; l < al; l++) {
if (attributes[l].nodeName === "i:type") {
sType = ($(attributes[l]).val() || "")
.replace("c:", "")
.replace("a:", "");
break;
}
}
var entRef,
nodes,
entCv;
switch (sType) {
case "OptionSetValue":
obj[sKey] = new self.OptionSetValue(parseInt($(attr.childNodes[k].childNodes[1]).text()));
break;
case "EntityReference":
nodes = attr.childNodes[k].childNodes[1].childNodes;
obj[sKey] = getEntityReference(nodes);
break;
case "EntityCollection":
var items = [],
childNodes = attr.childNodes[k].childNodes[1].childNodes[0].childNodes;
for (var y = 0; y < childNodes.length; y++) {
var itemNodes = childNodes[y].childNodes[0].childNodes;
for (var z = 0; z < itemNodes.length; z++) {
if ($(itemNodes[z].childNodes[0]).text() !== "partyid") {
continue;
}
nodes = itemNodes[z].childNodes[1].childNodes;
var itemRef = getEntityReference(nodes);
items[y] = itemRef;
}
}
entRef = new self.EntityCollection(items);
obj[sKey] = entRef;
break;
case "Money":
obj[sKey] = new self.Money(parseFloat($(attr.childNodes[k].childNodes[1]).text()));
break;
case "guid":
obj[sKey] = new self.Guid($(attr.childNodes[k].childNodes[1]).text());
break;
default:
entCv = new self.XrmValue();
entCv.type = sType;
if (entCv.type === "int") {
entCv.value = parseInt($(attr.childNodes[k].childNodes[1]).text());
} else if (entCv.type === "decimal" || entCv.type === "double") {
entCv.value = parseFloat($(attr.childNodes[k].childNodes[1]).text());
} else if (entCv.type === "dateTime") {
entCv.value = stringToDate($(attr.childNodes[k].childNodes[1]).text());
} else if (entCv.type === "boolean") {
entCv.value = ($(attr.childNodes[k].childNodes[1]).text() === "false") ? false : true;
} else if (entCv.type === "AliasedValue") {
var $attr = $(attr).children().eq(k).children().eq(1).children().eq(2),
aliasedType = $attr.attr("i:type");
if (aliasedType === "a:EntityReference") {
entCv = getEntityReference($attr.children());
} else if (aliasedType === "c:boolean") {
entCv.value = $attr.text() === trueString;
} else {
entCv.value = $attr.text();
}
} else {
entCv.value = $(attr.childNodes[k].childNodes[1]).text();
}
obj[sKey] = entCv;
break;
}
}
instance.attributes = obj;
break;
case "a:Id":
instance.id = new self.Guid($(resultNodes[j]).text());
break;
case "a:LogicalName":
instance.logicalName = $(resultNodes[j]).text();
break;
case "a:FormattedValues":
var foVal = resultNodes[j];
for (k = 0, l = foVal.childNodes.length; k < l; k++) {
var childNode = foVal.childNodes[k];
sKey = $(childNode.firstChild).text();
instance.attributes[sKey].formattedValue = $(childNode.childNodes[1]).text();
if (isNaN(instance.attributes[sKey].value) && instance.attributes[sKey].type === "dateTime") {
instance.attributes[sKey].value = new Date(instance.attributes[sKey].formattedValue);
}
}
break;
}
}
return instance;
};
return entity;
})();
this.OptionSetValue = (function() {
/**
* Like OptionSetValue in Microsoft.Xrm.Sdk
* @param {Number} value Value of option
* @param {String} name Name of option
*/
const ctor = function(value, name) {
if (typeof(value) !== "number") {
throw "value must be a number";
}
const nameIsExist = typeof(name) !== "undefined";
if (nameIsExist && typeof(name) !== "string") {
throw "name must be a string";
}
this.value = value;
this.name = nameIsExist ? name : "";
this.type = "OptionSetValue";
};
ctor.prototype.getValue = function() {
return this.value;
};
ctor.prototype.getName = function() {
return this.name;
};
return ctor;
})();
this.Money = (function() {
const ctor = function(value) {
this.value = value;
this.type = "Money";
};
return ctor;
})();
this.Decimal = (function() {
const ctor = function(value) {
this.value = value;
this.type = "decimal";
};
return ctor;
})();
this.Guid = (function() {
const 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 empty = "{00000000-0000-0000-0000-000000000000}";
const ctor = function(value) {
if (typeof(value) === "object" &&
((value instanceof self.Guid) ||
(value instanceof self.XrmValue && value.type === "guid"))) {
this.value = value.value.toUpperCase();
this.type = value.type;
} else {
value = value ? value.toUpperCase() : "";
if (!regex.test(value)) {
throw new TypeError("value must be a valid Guid");
}
if (value.indexOf("{") === 0) {
this.value = value;
} else {
this.value = `{${value}}`;
}
this.type = "guid";
}
};
ctor.prototype.equals = function(other) {
if (!other) {
return false;
}
if (typeof(other) === "object" &&
other instanceof self.XrmValue &&
other.type === "guid") {
return this.equals(self.Guid.tryParse(other.value));
} else if (typeof(other) === "object" && other instanceof self.Guid) {
return this.value === other.value;
} else if (typeof(other) === "string") {
return this.equals(self.Guid.tryParse(other));
}
return false;
};
ctor.prototype.notEquals = function(other) {
return !this.equals(other);
};
ctor.parse = function(value) {
return new self.Guid(value);
};
ctor.tryParse = function(value) {
try {
return new self.Guid(value);
} catch (ex) {
return null;
}
};
ctor.empty = function() {
return new self.Guid(empty);
};
return ctor;
})();
this.EntityCollection = (function() {
const entityCollection = function(value) {
this.value = value;
this.type = "EntityCollection";
};
return entityCollection;
})();
this.EntityReference = (function() {
/**
* Like EntityReference in Microsoft.Xrm.Sdk
* @param {String} logicalName Entity logical name
* @param {Guid} id Entity Id
* @param {String} name Entity name
*/
const ctor = function(logicalName, id, name) {
this.id = id ? new self.Guid(id) : self.Guid.empty();
this.logicalName = logicalName || "";
this.name = name || "";
this.type = "EntityReference";
};
ctor.prototype.getId = function() {
return this.id;
};
ctor.prototype.getIdValue = function() {
return this.id.value;
};
ctor.prototype.getLogicalName = function() {
return this.logicalName;
};
ctor.prototype.getName = function() {
return this.name;
};
ctor.prototype.toLookupValue = function() {
return [{
id: this.getIdValue(),
name: this.getName(),
entityType: this.getLogicalName()
}];
};
ctor.prototype.equals = function(other) {
if (!other) {
return false;
}
if (typeof(other) === "object" && other instanceof self.EntityReference) {
return this.id.equals(other.id);
}
return false;
};
return ctor;
})();
this.StateCode = (function() {
const ctor = function(value) {
this.value = value;
this.type = "int";
};
return ctor;
})();
this.StatusCode = (function() {
const ctor = function(value) {
this.value = value;
this.type = "int";
};
return ctor;
})();
this.XrmValue = (function() {
const ctor = function(value, type) {
this.value = value;
this.type = type;
};
return ctor;
})();
this.RequestParameter = (function() {
const ctor = function(name, value) {
this.name = name;
this.value = value;
};
return ctor;
})();
this.EntityFilters = (function() {
return {
Instance: "Instance",
Entity: "Entity",
Attributes: "Attributes",
Privileges: "Privileges",
Relationships: "Relationships",
All: [
"Relationships",
"Privileges",
"Attributes",
"Entity"
]
};
})();
this.OrganizationRequest = (function() {
/**
* Abstract base class for all requests
*/
const ctor = function() {
this.RequestName = arguments[0] || "";
this.Parameters = arguments[1];
this.RequestId = self.Guid.empty();
};
ctor.prototype.serialize = function() {
return this.template(this.Parameters);
};
return ctor;
})();
this.RetrieveAllEntitiesRequest = (function(base) {
const template = compile([
`<request i:type='a:RetrieveAllEntitiesRequest' xmlns:a='${contractsXrmNs}'>`,
`<a:Parameters xmlns:b='${genericNs}'>`,
"<a:KeyValuePairOfstringanyType>",
"<b:key>EntityFilters</b:key>",
`<b:value i:type='c:EntityFilters' xmlns:c='${metadataNs}'>`,
"<%= entityFilters %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>RetrieveAsIfPublished</b:key>",
`<b:value i:type='c:boolean' xmlns:c='${xmlSchemaNs}'>`,
"<%= retrieveAsIfPublished %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
"<a:RequestId i:nil='true'/>",
"<a:RequestName>RetrieveAllEntities</a:RequestName>",
"</request>"
].join(""));
const ctor = function(entityFilters, retrieveAsIfPublished) {
this.entityFilters = entityFilters;
this.retrieveAsIfPublished = !!retrieveAsIfPublished;
this.template = template;
ctor.base.constructor.call(
this,
"RetrieveAllEntitiesRequest",
{
entityFilters: this.entityFilters,
retrieveAsIfPublished: this.retrieveAsIfPublished
});
};
ctor.prototype.serialize = function() {
return this.base.prototype.serialize.apply(this);
};
extend(ctor, base);
return ctor;
})(self.OrganizationRequest);
this.RetrieveEntityRequest = (function(base) {
const template = compile([
`<request i:type='a:RetrieveEntityRequest' xmlns:a='${contractsXrmNs}'>`,
`<a:Parameters xmlns:b='${genericNs}'>`,
"<a:KeyValuePairOfstringanyType>",
"<b:key>EntityFilters</b:key>",
`<b:value i:type='c:EntityFilters' xmlns:c='${metadataNs}'>`,
"<%= entityFilters %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>MetadataId</b:key>",
`<b:value i:type='c:guid' xmlns:c='${serializationNs}'>`,
self.Guid.empty().value,
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>RetrieveAsIfPublished</b:key>",
`<b:value i:type='c:boolean' xmlns:c='${xmlSchemaNs}'>`,
"<%= retrieveAsIfPublished %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>LogicalName</b:key>",
`<b:value i:type='c:string' xmlns:c='${xmlSchemaNs}'>`,
"<%= logicalName %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
"<a:RequestId i:nil='true'/>",
"<a:RequestName>RetrieveEntity</a:RequestName>",
"</request>"
].join(""));
const ctor = function(logicalName, entityFilters, retrieveAsIfPublished) {
this.logicalName = logicalName;
this.entityFilters = entityFilters;
this.retrieveAsIfPublished = !!retrieveAsIfPublished;
this.template = template;
ctor.base.constructor.call(
this,
"RetrieveEntityRequest",
{
logicalName: this.logicalName,
entityFilters: this.entityFilters,
retrieveAsIfPublished: this.retrieveAsIfPublished
});
};
ctor.prototype.serialize = function() {
return this.base.prototype.serialize.apply(this);
};
extend(ctor, base);
return ctor;
})(self.OrganizationRequest);
this.RetrieveAttributeRequest = (function(base) {
const template = compile([
`<request i:type='a:RetrieveAttributeRequest' xmlns:a='${contractsXrmNs}'>`,
`<a:Parameters xmlns:b='${genericNs}'>`,
"<a:KeyValuePairOfstringanyType>",
"<b:key>EntityLogicalName</b:key>",
`<b:value i:type='c:string' xmlns:c='${xmlSchemaNs}'>`,
"<%= entityLogicalName %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>MetadataId</b:key>",
`<b:value i:type='ser:guid' xmlns:ser='${serializationNs}'>`,
self.Guid.empty().value,
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>RetrieveAsIfPublished</b:key>",
`<b:value i:type='c:boolean' xmlns:c='${xmlSchemaNs}'>`,
"<%= retrieveAsIfPublished %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<b:key>LogicalName</b:key>",
`<b:value i:type='c:string' xmlns:c='${xmlSchemaNs}'>`,
"<%= attributeLogicalName %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
"<a:RequestId i:nil='true' />",
"<a:RequestName>RetrieveAttribute</a:RequestName>",
"</request>"
].join(""));
const ctor = function(entityLogicalName, attributeLogicalName, retrieveAsIfPublished) {
this.entityLogicalName = entityLogicalName;
this.attributeLogicalName = attributeLogicalName;
this.retrieveAsIfPublished = !!retrieveAsIfPublished;
this.template = template;
ctor.base.constructor.call(
this,
"RetrieveAttributeRequest",
{
entityLogicalName: this.entityLogicalName,
attributeLogicalName: this.attributeLogicalName,
retrieveAsIfPublished: this.retrieveAsIfPublished
});
};
ctor.prototype.serialize = function() {
return this.base.prototype.serialize.apply(this);
};
extend(ctor, base);
return ctor;
})(self.OrganizationRequest);
this.SetStateRequest = (function(base) {
const template = compile([
`<request i:type='b:SetStateRequest' xmlns:a='${contractsXrmNs}' xmlns:b='${contractsCrmNs}'>`,
`<a:Parameters xmlns:c='${genericNs}'>`,
"<a:KeyValuePairOfstringanyType>",
"<c:key>EntityMoniker</c:key>",
"<c:value i:type='a:EntityReference'>",
"<a:Id>",
"<%= entityId %>",
"</a:Id>",
"<a:LogicalName>",
"<%= entityName %>",
"</a:LogicalName>",
"<a:Name i:nil='true'/>",
"</c:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<c:key>State</c:key>",
"<c:value i:type='a:OptionSetValue'>",
"<a:Value>",
"<%= state %>",
"</a:Value>",
"</c:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<c:key>Status</c:key>",
"<c:value i:type='a:OptionSetValue'>",
"<a:Value>",
"<%= status %>",
"</a:Value>",
"</c:value>",
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
"<a:RequestId i:nil='true' />",
"<a:RequestName>SetState</a:RequestName>",
"</request>"
].join(""));
const ctor = function(entityName, entityId, state, status) {
this.entityName = entityName;
this.entityId = new self.Guid(entityId);
this.state = state;
this.status = status;
this.template = template;
ctor.base.constructor.call(
this,
"SetStateRequest",
{
entityName: this.entityName,
entityId: this.entityId.value,
state: this.state,
status: this.status
});
};
ctor.prototype.serialize = function() {
return this.base.prototype.serialize.apply(this);
};
extend(ctor, base);
return ctor;
})(self.OrganizationRequest);
this.ExecuteWorkflowRequest = (function(base) {
const template = compile([
`<request i:type='b:ExecuteWorkflowRequest' xmlns:a='${contractsXrmNs}' xmlns:b='${contractsCrmNs}'>`,
`<a:Parameters xmlns:c='${genericNs}'>`,
"<a:KeyValuePairOfstringanyType>",
"<c:key>EntityId</c:key>",
`<c:value i:type='d:guid' xmlns:d='${serializationNs}'>`,
"<%= entityId %>",
"</c:value>",
"</a:KeyValuePairOfstringanyType>",
"<a:KeyValuePairOfstringanyType>",
"<c:key>WorkflowId</c:key>",
`<c:value i:type='d:guid' xmlns:d='${serializationNs}'>`,
"<%= workflowId %>",
"</c:value>",
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
"<a:RequestId i:nil='true'/>",
"<a:RequestName>ExecuteWorkflow</a:RequestName>",
"</request>"
].join(""));
const ctor = function(entityId, workflowId) {
this.entityId = new self.Guid(entityId);
this.workflowId = new self.Guid(workflowId);
this.template = template;
ctor.base.constructor.call(
this,
"ExecuteWorkflowRequest",
{
entityId: this.entityId.value,
workflowId: this.workflowId.value
});
};
ctor.prototype.serialize = function() {
return this.base.prototype.serialize.apply(this);
};
extend(ctor, base);
return ctor;
})(self.OrganizationRequest);
this.RetrieveSharedPrincipalsAndAccessRequest = (function(base) {
const template = compile([
`<request i:type='b:RetrieveSharedPrincipalsAndAccessRequest' xmlns:a='${contractsXrmNs}' xmlns:i='${xmlSchemaInstanceNs}' xmlns:b='${contractsCrmNs}'>`,
`<a:Parameters xmlns:c='${genericNs}'>`,
"<a:KeyValuePairOfstringanyType>",
"<c:key>Target</c:key>",
"<c:value i:type='a:EntityReference'>",
"<a:Id><%= entityId %></a:Id>",
"<a:LogicalName><%= entityName %></a:LogicalName>",
"<a:Name i:nil='true'/>",
"</c:value>",
"</a:KeyValuePairOfstringanyType>",
"</a:Parameters>",
"<a:RequestId i:nil='true'/>",
"<a:RequestName>RetrieveSharedPrincipalsAndAccess</a:RequestName>",
"</request>"
].join(""));
/**
* RetrieveSharedPrincipalsAndAccessRequest like in Microsoft.Xrm.Sdk
*/
const ctor = function(entityName, entityId) {
this.entityName = entityName;
this.entityId = entityId;
this.template = template;
ctor.base.constructor.call(
this,
"RetrieveSharedPrincipalsAndAccessRequest",
{
entityName: this.entityName,
entityId: this.entityId.value
});
};
ctor.prototype.serialize = function() {
return this.base.prototype.serialize.apply(this);
};
extend(ctor, base);
return ctor;
})(self.OrganizationRequest);
this.ExecuteActionRequest = (function(base) {
const template = compile([
`<request xmlns:a='${contractsXrmNs}' xmlns:i='${xmlSchemaInstanceNs}' xmlns:b='${genericNs}'>`,
"<%= parameters %>",
"<a:RequestId i:nil='true'/>",
"<a:RequestName><%= actionName %></a:RequestName>",
"</request>"
].join(""));
const targetTemplate = compile([
"<a:KeyValuePairOfstringanyType>",
"<b:key>Target</b:key>",
"<b:value i:type='a:<%= type %>'>",
"<a:Id><%= id.value %></a:Id>",
"<a:LogicalName><%= logicalName %></a:LogicalName>",
"<a:Name i:nil='true'/>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>"
].join(""));
const parameterTemplate = compile([
"<a:KeyValuePairOfstringanyType>",
"<b:key><%= name %></b:key>",
`<b:value i:type='c:<%= type %>' xmlns:c='${xmlSchemaNs}'>`,
"<%= value %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>"
].join(""));
const emptyParametersTemplate = `<a:Parameters xmlns:c='${xmlSchemaNs}' i:nil='true'/>`;
const parametersTemplate = compile(`<a:Parameters xmlns:c='${xmlSchemaNs}'><% _.each(parameters, function(p) { %><%= p %><% }) %></a:Parameters>`);
const ctor = function(actionName, entityName, entityId, parameters) {
this.actionName = actionName;
this.target = new self.EntityReference(entityName, entityId);
this.parameters = parameters.length ? parametersTemplate({
parameters: _.map(parameters, function(p) {
// ToDo: extract this method to common usage
const typed = p.value ? p.value.hasOwnProperty("type") : false;
return parameterTemplate({
name: p.name,
type: typed ? p.value.type : "string",
value: p.value === undefined ? null : (p.value.hasOwnProperty("value") ? p.value.value : p.value)
});
}).concat(targetTemplate(this.target))
}) : emptyParametersTemplate;
this.template = template;
ctor.base.constructor.call(
this,
"",
{
parameters: this.parameters,
actionName: this.actionName
});
};
ctor.prototype.serialize = function() {
return this.base.prototype.serialize.apply(this);
};
extend(ctor, base);
return ctor;
})(self.OrganizationRequest);
this.ExecuteGlobalActionRequest = (function(base) {
const template = compile([
`<request xmlns:a='${contractsXrmNs}' xmlns:i='${xmlSchemaInstanceNs}' xmlns:b='${genericNs}'>`,
"<%= parameters %>",
"<a:RequestId i:nil='true'/>",
"<a:RequestName><%= actionName %></a:RequestName>",
"</request>"
].join(""));
const parameterTemplate = compile([
"<a:KeyValuePairOfstringanyType>",
"<b:key><%= name %></b:key>",
`<b:value i:type='c:<%= type %>' xmlns:c='${xmlSchemaNs}'>`,
"<%= value %>",
"</b:value>",
"</a:KeyValuePairOfstringanyType>"
].join(""));
const emptyParametersTemplate = `<a:Parameters xmlns:c='${xmlSchemaNs}' i:nil='true'/>`;
const parametersTemplate = compile(`<a:Parameters xmlns:c='${xmlSchemaNs}'><% _.each(parameters, function(p) { %><%= p %><% }) %></a:Parameters>`);
const ctor = function(actionName, parameters) {
this.actionName = actionName;
this.parameters = parameters.length ? parametersTemplate({
parameters: _.map(parameters, function(p) {
// ToDo: extract this method to common usage
const typed = p.value ? p.value.hasOwnProperty("type") : false;
return parameterTemplate({
name: p.name,
type: typed ? p.value.type : "string",
value: p.value === undefined ? null : (p.value.hasOwnProperty("value") ? p.value.value : p.value)
});
})
}) : emptyParametersTemplate;
this.template = template;
ctor.base.constructor.call(
this,
"",
{
actionName: this.actionName,
parameters: this.parameters
});
};
ctor.prototype.serialize = function() {
return this.base.prototype.serialize.apply(this);
};
extend(ctor, base);
return ctor;
})(self.OrganizationRequest);
/**
* Like IOrganizationService in Microsoft.Xrm.Sdk
*/
this.OrganizationService = (function() {
var url = splittedUrl[0] + "//" + splittedUrl[1],
serviceUrl = url + (splittedUrl.length === 3 && splittedUrl[2] === orgName ? (`/${orgName}`) : "") + xrmServiceUrl,
soapTemplate = compile([
utf8Root,
"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>",
"<soap:Body>",
`<<%= soapAction %> xmlns='${contractsXrmNs}/Services' xmlns:i='${xmlSchemaInstanceNs}'>`,
"<%= soapBody %>",
"</<%= soapAction %>>",
"</soap:Body>",
"</soap:Envelope>"
].join("")),
processResponse = function(response) {
if (!response || (response.hasOwnProperty("xml") && !response.xml)) {
return "No response received from the server";
}
const $response = $(response);
const error = $response.find("error").text();
const faultString = $response.find("faultstring").text();
if (!(error === "" && faultString === "")) {
return error !== "" ? $response.find("description").text() : faultString;
}
const currentType = typeof(response);
const ieXmlType = typeof(response.xml);
// ReSharper disable once ConditionIsAlwaysConst
if (currentType !== "object" && (ieXmlType === "undefined" || ieXmlType === "unknown")) {
return parseXml(response);
} else if (currentType === "object") {
return response;
} else {
return parseXml(xmlToString(response));
}
},
executeSync = function(soapBody, soapAction) {
const soapXml = soapTemplate({ soapAction: soapAction, soapBody: soapBody });
const req = new global.XMLHttpRequest();
req.open("POST", serviceUrl, false);
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", xrmSoapActionPrefix + soapAction);
req.send(soapXml);
const parsedResponse = processResponse(req.responseXML);
if (req.status === 200) {
return parsedResponse;
} else {
return Error(parsedResponse);
}
};
const sync = {
/**
* Create like create in Microsoft.Xrm.Sdk
* @param {Entity} entity
*/
create: function(entity) {
const result = executeSync(entity.serialize(), "Create");
return result && !(result instanceof Error) ? $(result).find("CreateResult").text() : result;
},
/**
* Update like update in Microsoft.Xrm.Sdk
* @param {Entity} entity
*/
update: function(entity) {
const result = executeSync(entity.serialize(), "Update");
return result && !(result instanceof Error) ? $(result).find("UpdateResponse").text() : result;
},
/**
* Delete like delete in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Guid} id
*/
"delete": function(entityName, id) {
const request = `<entityName>${entityName}</entityName><id>${new self.Guid(id).value}</id>`;
return executeSync(request, "Delete");
},
/**
* Retrieve like in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Guid} id
* @param {Array|ColumnSet} columnSet
*/
retrieve: function(entityName, id, columnSet) {
const soapBodyTemplate = compile("<entityName><%= entityName %></entityName><id><%= id %></id><%= columnSet %>");
if (columnSet && $.isArray(columnSet)) {
columnSet = new self.ColumnSet(columnSet);
columnSet = columnSet.serialize(false, true);
} else if (columnSet && columnSet instanceof self.ColumnSet) {
columnSet = columnSet.serialize(false, true);
} else {
columnSet = self.ColumnSet.getAllColumnsSoap(false, true);
}
const result = executeSync(
soapBodyTemplate({
entityName: entityName,
id: new self.Guid(id).value,
columnSet: columnSet
}),
"Retrieve");
if (result && result instanceof Error) {
return result;
}
const retrieveResult = $(result).find("RetrieveResult")[0];
if (!retrieveResult) {
return null;
}
return self.Entity.deserialize(retrieveResult);
},
/**
* RetrieveMultiple like in Microsoft.Xrm.Sdk
* @param {QueryExpression|QueryByAttribute} query Query for perform retrieve operation
*/
retrieveMultiple: function(query) {
const result = executeSync(query.serialize(), "RetrieveMultiple");
if (result && result instanceof Error) {
return result;
}
const $resultXml = $(result);
var resultNodes;
if ($resultXml.find("a\\:Entities").length) {
resultNodes = $resultXml.find("a\\:Entities")[0];
} else {
// chrome could not load node properly
resultNodes = $resultXml.find("Entities")[0];
}
if (!resultNodes) {
return [];
}
const retrieveMultipleResults = [];
for (let i = 0, l = resultNodes.childNodes.length; i < l; i++) {
retrieveMultipleResults[i] = self.Entity.deserialize(resultNodes.childNodes[i]);
}
return retrieveMultipleResults;
},
/**
* Execute like in Microsoft.Xrm.Sdk
* @param {OrganizationRequest} request
*/
execute: function(request) {
return executeSync(request.serialize(), "Execute");
},
/**
* Execute fetch Xml query
* @param {String} fetchXml Fetch xml expression
*/
fetch: function(fetchXml) {
// ToDo: implement fetchXmlBuilder
const fetchQuery = [
`<query i:type='a:FetchExpression' xmlns:a='${contractsXrmNs}'>`,
"<a:Query>",
crmXmlEncode(fetchXml),
"</a:Query>",
"</query>"
].join("");
const result = executeSync(fetchQuery, "RetrieveMultiple");
if (result && result instanceof Error) {
return result;
}
const $resultXml = $(result);
const fetchResults = [];
let fetchResult;
let $entities = $resultXml.find("a\\:Entities");
if ($entities.length) {
fetchResult = $entities[0];
} else {
$entities = $resultXml.find("Entities");
// chrome could not load node
fetchResult = $entities[0];
}
for (let i = 0, l = fetchResult.childNodes.length; i < l; i++) {
fetchResults[fetchResults.length] = self.Entity.deserialize(fetchResult.childNodes[i]);
}
return fetchResults;
}
};
var execute = function(soapBody, soapAction, async) {
return new Promise(function(resolve, reject) {
const soapXml = soapTemplate({ soapBody: soapBody, soapAction: soapAction });
const req = new global.XMLHttpRequest();
req.open("POST", serviceUrl, async || false);
req.setRequestHeader("Accept", "application/xml, text/xml, */*");
req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
req.setRequestHeader("SOAPAction", xrmSoapActionPrefix + soapAction);
req.onload = function() {
const parsedResponse = processResponse(req.responseXML);
if (req.status === 200) {
req.onreadystatechange = null;
resolve(parsedResponse);
} else {
reject(Error(parsedResponse));
}
};
req.onerror = function() {
req.onreadystatechange = null;
reject(Error("network error occured"));
};
req.send(soapXml);
});
};
const orgService = function() {
this.url = function() {
return url;
};
this.orgName = function() {
return orgName;
};
};
orgService.prototype.sync = sync;
/**
* Create like create in Microsoft.Xrm.Sdk
* @param {Entity} entity
* @param {Boolean} async
*/
orgService.prototype.create = function(entity, async) {
return execute(entity.serialize(), "Create", async).then(function(resultXml) {
return resultXml ? $(resultXml).find("CreateResult").text() : null;
});
};
/**
* Create like create in Microsoft.Xrm.Sdk
* @param {Entity} entity
*/
orgService.prototype.createAsync = function(entity) {
return this.create(entity, true);
};
/**
* Update like update in Microsoft.Xrm.Sdk
* @param {Entity} entity
* @param {Boolean} async
*/
orgService.prototype.update = function(entity, async) {
return execute(entity.serialize(), "Update", async).then(function(resultXml) {
return resultXml ? $(resultXml).find("UpdateResponse").text() : null;
});
};
/**
* Update like update in Microsoft.Xrm.Sdk
* @param {Entity} entity
*/
orgService.prototype.updateAsync = function(entity) {
return this.update(entity, true);
};
/**
* Delete like delete in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Guid} id
* @param {Boolean} async
*/
orgService.prototype.delete = function(entityName, id, async) {
const request = `<entityName>${entityName}</entityName><id>${new self.Guid(id).value}</id>`;
return execute(request, "Delete", async);
};
/**
* Delete like delete in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Guid} id
*/
orgService.prototype.deleteAsync = function(entityName, id) {
return this.delete(entityName, id, true);
};
/**
* Retrieve like in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Guid} id
* @param {(Array<String>|ColumnSet)} columnSet
* @param {Boolean} async
*/
orgService.prototype.retrieve = function(entityName, id, columnSet, async) {
const soapBodyTemplate = compile("<entityName><%= entityName %></entityName><id><%= id %></id><%= columnSet %>");
if (columnSet && $.isArray(columnSet)) {
columnSet = new self.ColumnSet(columnSet);
columnSet = columnSet.serialize(false, true);
} else if (columnSet && columnSet instanceof self.ColumnSet) {
columnSet = columnSet.serialize(false, true);
} else {
columnSet = self.ColumnSet.getAllColumnsSoap(false, true);
}
return execute(soapBodyTemplate({
entityName: entityName,
id: new self.Guid(id).value,
columnSet: columnSet
}), "Retrieve", async).then(function(resultXml) {
const retrieveResult = $(resultXml).find("RetrieveResult")[0];
if (!retrieveResult) {
return null;
}
return self.Entity.deserialize(retrieveResult);
});
};
/**
* Retrieve like in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Guid} id
* @param {(Array<String>|ColumnSet)} columnSet
*/
orgService.prototype.retrieveAsync = function(entityName, id, columnSet) {
return this.retrieve(entityName, id, columnSet, true);
};
/**
* RetrieveMultiple like in Microsoft.Xrm.Sdk
* @param {(QueryExpression|QueryByAttribute))} query - Query for perform retrieve operation
* @param {Boolean} async
*/
orgService.prototype.retrieveMultiple = function(query, async) {
return execute(query.serialize(), "RetrieveMultiple", async).then(function(result) {
const $resultXml = $(result);
var resultNodes;
if ($resultXml.find("a\\:Entities").length) {
resultNodes = $resultXml.find("a\\:Entities")[0];
} else {
// chrome could not load node properly
resultNodes = $resultXml.find("Entities")[0];
}
if (!resultNodes) {
return [];
}
const retrieveMultipleResults = [];
for (let i = 0, l = resultNodes.childNodes.length; i < l; i++) {
retrieveMultipleResults[i] = self.Entity.deserialize(resultNodes.childNodes[i]);
}
return retrieveMultipleResults;
});
};
/**
* RetrieveMultiple like in Microsoft.Xrm.Sdk
* @param {(QueryExpression|QueryByAttribute)} query - Query for perform retrieve operation
*/
orgService.prototype.retrieveMultipleAsync = function(query) {
return this.retrieveMultiple(query, true);
};
/**
* Execute like in Microsoft.Xrm.Sdk
* @param {OrganizationRequest} request
* @param {Boolean} async
*/
orgService.prototype.execute = function(request, async) {
return execute(request.serialize(), "Execute", async);
};
/**
* Execute like in Microsoft.Xrm.Sdk
* @param {OrganizationRequest} request
*/
orgService.prototype.executeAsync = function(request) {
return this.execute(request, true);
};
/**
* Execute fetch Xml query
* @param {String} fetchXml
* @param {Boolean} async
*/
orgService.prototype.fetch = function(fetchXml, async) {
// ToDo: implement fetchXmlBuilder
const fetchQuery = [
`<query i:type='a:FetchExpression' xmlns:a='${contractsXrmNs}'>`,
"<a:Query>",
crmXmlEncode(fetchXml),
"</a:Query>",
"</query>"
].join("");
return execute(fetchQuery, "RetrieveMultiple", async).then(function(resultXml) {
let fetchResult;
const fetchResults = [];
let $entities = $(resultXml).find("a\\:Entities");
if ($entities.length) {
fetchResult = $entities[0];
} else {
$entities = $(resultXml).find("Entities");
// chrome could not load node
fetchResult = $entities[0];
}
for (let i = 0, l = fetchResult.childNodes.length; i < l; i++) {
fetchResults[fetchResults.length] = self.Entity.deserialize(fetchResult.childNodes[i]);
}
return fetchResults;
});
};
/**
* Execute fetch Xml query
* @param {String} fetchXml
*/
orgService.prototype.fetchAsync = function(fetchXml) {
return this.fetch(fetchXml, true);
};
return orgService;
})();
this.CrmProvider = (function() {
const entityMetadataType = "EntityMetadata";
const orgService = new self.OrganizationService();
const crmProvider = function() {};
/**
* Execute ExecuteWorkflowRequest like in Microsoft.Xrm.Sdk
* @param {Guid} entityId - Current entity Id
* @param {Guid} workflowId - Executing workflow Id
* @param {Boolean} async
* @returns {Guid} Async operation Id
*/
crmProvider.prototype.executeWorkflow = function(entityId, workflowId, async) {
const request = new self.ExecuteWorkflowRequest(entityId, workflowId);
return orgService.execute(request, async).then(function(result) {
const $xml = $(typeof(result.xml) === "undefined" ? result : result.xml);
const id = $xml.find("c\\:value").text() || $xml.find("value").text();
return id ? new self.Guid(id) : null;
}).catch(function(err) {
notify(err);
});
};
/**
* Execute ExecuteWorkflowRequest like in Microsoft.Xrm.Sdk
* @param {Guid} entityId - Current entity Id
* @param {Guid} workflowId - Executing workflow Id
* @returns {Guid} Async operation Id
*/
crmProvider.prototype.executeWorkflowAsync = function(entityId, workflowId) {
return this.executeWorkflow(entityId, workflowId, true);
};
/**
* Obtains user teams
* @param {Guid} userId - Current user Id
* @param {ColumnSet=ColumnSet("name")} teamColumnSet
* @param {Boolean} async
*/
crmProvider.prototype.getSystemUserTeams = function(userId, teamColumnSet, async) {
const query = new self.QueryExpression("team", [], teamColumnSet || new self.ColumnSet("name"));
const linkEntity = new self.LinkEntity("team", "teammembership", "teamid", "teamid", self.JoinOperator.Inner);
const filterExpression = new self.FilterExpression();
filterExpression.addCondition(new self.ConditionExpression("systemuserid", self.ConditionOperator.Equal, [new self.Guid(userId)]));
linkEntity.setLinkCriteria(filterExpression);
query.addLink(linkEntity);
return orgService.retrieveMultiple(query, async);
};
/**
* Obtains user teams
* @param {Guid} userId - Current user Id
* @param {ColumnSet=ColumnSet("name")} teamColumnSet
*/
crmProvider.prototype.getSystemUserTeamsAsync = function(userId, teamColumnSet) {
return this.getSystemUserTeams(userId, teamColumnSet, true);
};
/**
* Obtains user businessunit
* @param {Guid} userId - Current user Id
* @param {Boolean} async
*/
crmProvider.prototype.getSystemUserBusinessUnit = function(userId, async) {
return orgService.retrieve("systemuser", new self.Guid(userId).value, ["businessunitid"], async).then(function(user) {
return user.getAttributeValue("businessunitid");
});
};
/**
* Obtains user businessunit
* @param {Guid} userId - Current user Id
*/
crmProvider.prototype.getSystemUserBusinessUnitAsync = function(userId) {
return this.getSystemUserBusinessUnit(userId, true);
};
/**
* Execute RetrieveSharedPrincipalsAndAccessRequest like in Microsoft.Xrm.Sdk
* @param {String} entityName - Entity Logical Name
* @param {Guid} entityId - Entity instance Id for check access
* @param {Boolean} async
*/
crmProvider.prototype.retrieveSharedPrincipalsAndAccess = function(entityName, entityId, async) {
const request = new self.RetrieveSharedPrincipalsAndAccessRequest(entityName, new self.Guid(entityId));
return orgService.execute(request, async).then(function(result) {
const sharedAccessRights = [];
const principalAccess = $(typeof(result.xml) === "undefined" ? result : result.xml).find("PrincipalAccess");
for (let i = 0, l = principalAccess.length; i < l; i++) {
const parsedResult = principalAccess[i].childNodes;
sharedAccessRights[sharedAccessRights.length] = {
Rights: $(parsedResult[0]).text().split(" "),
Id: $(parsedResult[1].childNodes[0]).text(),
Principal: $(parsedResult[1].childNodes[1]).text()
};
}
return sharedAccessRights.length ? sharedAccessRights : null;
}).catch(function(err) {
notify(`Ошибка:\n${err && err.description ? err.description : err}`);
});
};
/**
* Execute RetrieveSharedPrincipalsAndAccessRequest like in Microsoft.Xrm.Sdk
* @param {String} entityName - Entity Logical Name
* @param {Guid} entityId - Entity instance Id for check access
*/
crmProvider.prototype.retrieveSharedPrincipalsAndAccessAsync = function(entityName, entityId) {
return this.retrieveSharedPrincipalsAndAccess(entityName, entityId, true);
};
/**
* Execute SetStateRequest like in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Guid} entityId
* @param {Number} state
* @param {Number} status
* @param {Boolean} async
*/
crmProvider.prototype.setState = function(entityName, entityId, state, status, async) {
const request = new self.SetStateRequest(entityName, entityId, state, status);
return orgService.execute(request, async).then(function(result) {
const $response = $(result).find("ExecuteResult").eq(0);
return crmXmlDecode($response.text());
});
};
/**
* Execute SetStateRequest like in Microsoft.Xrm.Sdk
* @param {String} entityName
* @param {Guid} entityId
* @param {Number} state
* @param {Number} status
*/
crmProvider.prototype.setStateAsync = function(entityName, entityId, state, status) {
return this.setState(entityName, entityId, state, status, true);
};
/**
* Obtains entity metadata
* @param {String} logicalName
* @param {Array<String>} entityFilters
* @param {Boolean} retrieveAsIfPublished
* @param {Boolean} async
*/
crmProvider.prototype.retrieveEntityMetadata = function(logicalName, entityFilters, retrieveAsIfPublished, async) {
entityFilters = $.isArray(entityFilters) ? entityFilters : [entityFilters];
entityFilters = entityFilters.join(" ");
const request = new self.RetrieveEntityRequest(logicalName, entityFilters, retrieveAsIfPublished);
return orgService.execute(request, async).then(function(result) {
const $resultXml = $(result);
const results = [];
const $value = $resultXml.find("b\\:value");
const response = $value.length ? $value : $resultXml.find("value");
for (let i = 0, l = response.length; i < l; i++) {
const a = objectifyNode(response[i]);
a._type = entityMetadataType;
results[results.length] = a;
}
return results;
});
};
/**
* Obtains entity metadata
* @param {String} logicalName
* @param {Array<String>} entityFilters
* @param {Boolean} retrieveAsIfPublished
*/
crmProvider.prototype.retrieveEntityMetadataAsync = function(logicalName, entityFilters, retrieveAsIfPublished) {
return this.retrieveEntityMetadata(logicalName, entityFilters, retrieveAsIfPublished, true);
};
/**
* Obtains entity attribute metadata
* @param {String} entityLogicalName
* @param {String} attributeLogicalName
* @param {Boolean} retrieveAsIfPublished
* @param {Boolean} async
*/
crmProvider.prototype.retrieveAttributeMetadata = function(entityLogicalName, attributeLogicalName, retrieveAsIfPublished, async) {
const request = new self.RetrieveAttributeRequest(entityLogicalName, attributeLogicalName, retrieveAsIfPublished);
return orgService.execute(request, async).then(function(result) {
const $resultXml = $(result);
const results = [];
const $value = $resultXml.find("b\\:value");
const response = $value.length ? $value : $resultXml.find("value");
for (let i = 0, l = response.length; i < l; i++) {
results[results.length] = objectifyNode(response[i]);
}
return results;
});
};
/**
* Obtains entity attribute metadata
* @param {String} entityLogicalName
* @param {String} attributeLogicalName
* @param {Boolean} retrieveAsIfPublished
*/
crmProvider.prototype.retrieveAttributeMetadataAsync = function(entityLogicalName, attributeLogicalName, retrieveAsIfPublished) {
return this.retrieveAttributeMetadata(entityLogicalName, attributeLogicalName, retrieveAsIfPublished, true);
};
/**
* Obtains all entities metadata
* @param {Array<String} entityFilters
* @param {Boolean} retrieveIfPublished
* @param {Boolean} async
*/
crmProvider.prototype.retrieveAllEntitiesMetadataAsync = function(entityFilters, retrieveIfPublished) {
entityFilters = $.isArray(entityFilters) ? entityFilters : [entityFilters];
entityFilters = entityFilters.join(" ");
const request = new self.RetrieveAllEntitiesRequest(entityFilters, retrieveIfPublished);
return orgService.execute(request, true).then(function(result) {
const $resultXml = $(result);
const results = [];
const $metadata = $resultXml.find(`c\\:${entityMetadataType}`);
const response = $metadata.length ? $metadata : $resultXml.find(entityMetadataType);
for (let i = 0, l = response.length; i < l; i++) {
const a = objectifyNode(response[i]);
a._type = entityMetadataType;
results[results.length] = a;
}
return results;
});
};
/**
* Execute action request like in Microsoft.Xrm.Sdk
* Action must return exactly one string parameter. If you want to pass more than one use JSON.
* @param {String} actionName
* @param {String} entityName
* @param {Guid} entityId
* @param {Array} parameters
* @param {Boolean} async
*/
crmProvider.prototype.callAction = function(actionName, entityName, entityId, parameters, async) {
const request = new self.ExecuteActionRequest(actionName, entityName, entityId, parameters);
return orgService.execute(request, async).then(function(result) {
const $response = $(result).find("ExecuteResult").eq(0);
return crmXmlDecode($response.text());
}).catch(function(err) {
notify(`Ошибка:\n${err && err.description ? err.description : err}`);
});
};
/**
* Execute action request like in Microsoft.Xrm.Sdk
* Action must return exactly one string parameter. If you want to pass more than one use JSON.
* @param {String} actionName
* @param {String} entityName
* @param {Guid} entityId
* @param {Array} parameters
*/
crmProvider.prototype.callActionAsync = function(actionName, entityName, entityId, parameters) {
return this.callAction(actionName, entityName, entityId, parameters, true);
};
/**
* Execute global action request like in Microsoft.Xrm.Sdk
* Action must return exactly one string parameter. If you want to pass more than one use JSON.
* @param {String} actionName
* @param {Array} parameters
* @param {Boolean} async
*/
crmProvider.prototype.callGlobalAction = function(actionName, parameters, async) {
const request = new self.ExecuteGlobalActionRequest(actionName, parameters);
return orgService.execute(request, async).then(function(result) {
const $response = $(result).find("ExecuteResult").eq(0);
return crmXmlDecode($response.text());
}).catch(function(err) {
notify(`Ошибка:\n${err && err.description ? err.description : err}`);
});
};
/**
* Execute global action request like in Microsoft.Xrm.Sdk
* Action must return exactly one string parameter. If you want to pass more than one use JSON.
* @param {String} actionName
* @param {Array} parameters
*/
crmProvider.prototype.callGlobalActionAsync = function(actionName, parameters) {
return this.callGlobalAction(actionName, parameters, true);
};
return crmProvider;
})();
}).call(this.Xrm.Soap.Sdk, this);