UNPKG

@insurgo/niam.xrm.client.test

Version:
825 lines (810 loc) 33.8 kB
(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.Niam = global.Niam || {}, global.Niam.Xrm = {}))); }(this, (function (exports) { 'use strict'; // https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/xrm-webapi/retrievemultiplerecords // https://docs.microsoft.com/en-us/powerapps/developer/model-driven-apps/clientapi/reference/xrm-webapi/retrieverecord function getWebApiOption(option) { if (!option) return {}; if (option[0] !== '?') { throw Error("'?' not found in the first parameter"); } option = option.replace('?', ''); var result = option .split('&') .filter(function (e) { return e; }) .reduce(function (webApiOption, attribute) { var firstEqualIndex = attribute.indexOf('='); var key = attribute.substr(0, firstEqualIndex); var value = attribute.substr(firstEqualIndex + 1, attribute.length - 1); switch (key) { case '$select': webApiOption.select = value; break; case '$filter': webApiOption.filter = value; break; case '$expand': webApiOption.expand = value; break; case '$orderby': webApiOption.orderby = value; break; case '$top': webApiOption.top = value; break; default: throw Error("WebApi with key '" + key + "' not supported"); } return webApiOption; }, {}); return result; } function toEntity(entityLogicalName, id, record) { var attributes = Object.keys(record); var result = { logicalName: entityLogicalName, id: id, }; for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { var attribute = attributes_1[_i]; result[attribute] = record[attribute]; } return result; } function toWebApiEntity(entity) { var excludeAttributes = ['id', 'logicalName']; var attributes = Object.keys(entity).filter(function (attribute) { return excludeAttributes.indexOf(attribute) === -1; }); var result = {}; for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { var attribute = attributes_1[_i]; result[attribute] = entity[attribute]; } return result; } function select(entity, webOption) { var valid = webOption && webOption.select && webOption.select !== ''; if (!valid) return entity; var entityAttributes = Object.keys(entity); var result = webOption.select .split(',') .map(function (e) { return e.trim(); }) .filter(function (e) { return e; }) .reduce(function (e, attribute) { var filterAttributes = entityAttributes.filter(function (e) { return e.indexOf(attribute) > -1; }); if (!filterAttributes) return e; for (var _i = 0, filterAttributes_1 = filterAttributes; _i < filterAttributes_1.length; _i++) { var entityAttribute = filterAttributes_1[_i]; e[entityAttribute] = entity[entityAttribute]; } return e; }, {}); if (entity.logicalName) { result.id = entity.id; result.logicalName = entity.logicalName; } return result; } function update(source, target) { var excludeAttributes = ['id', 'logicalName']; var attributes = Object.keys(target).filter(function (attribute) { return excludeAttributes.indexOf(attribute) === -1; }); for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { var attribute = attributes_1[_i]; source[attribute] = target[attribute]; } return source; } // https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/webapi/query-data-web-api exports.operator = void 0; (function (operator) { operator[operator["eq"] = 0] = "eq"; operator[operator["ne"] = 1] = "ne"; operator[operator["gt"] = 2] = "gt"; operator[operator["ge"] = 3] = "ge"; operator[operator["lt"] = 4] = "lt"; operator[operator["le"] = 5] = "le"; operator[operator["contains"] = 6] = "contains"; operator[operator["endswith"] = 7] = "endswith"; operator[operator["startswith"] = 8] = "startswith"; })(exports.operator || (exports.operator = {})); exports.logicalOperator = void 0; (function (logicalOperator) { logicalOperator[logicalOperator["and"] = 0] = "and"; logicalOperator[logicalOperator["or"] = 1] = "or"; logicalOperator[logicalOperator["not"] = 2] = "not"; })(exports.logicalOperator || (exports.logicalOperator = {})); function parseValue(value) { if (value === null || value === undefined) return value; if (Number(value)) { return Number(value); } var boolValue = value; if (boolValue) { return boolValue; } var stringValue = value; var date = new Date(stringValue); if (date instanceof Date && !isNaN(date.getTime())) { return date; } return stringValue; } function getExpandValue(attribute, entity) { var keys = attribute.split('/'); if (keys.length != 2) return null; var entityAttribute = keys[0]; var valueAttribute = keys[1]; var entityObj = entity[entityAttribute]; return entityObj ? entityObj[valueAttribute] : null; } function isValid(entity, command, parentCommand, parentResult) { if (parentCommand === void 0) { parentCommand = null; } if (parentResult === void 0) { parentResult = null; } if (!command) return false; var value = command.attributeName.indexOf('/') > -1 ? getExpandValue(command.attributeName, entity) : parseValue(entity[command.attributeName]); var compareValue = parseValue(command.value); var valid = false; if (command.operator === exports.operator.contains) { valid = value.indexOf(compareValue) > -1; } else if (command.operator === exports.operator.startswith) { valid = value.startWith(compareValue); } else if (command.operator === exports.operator.endswith) { valid = value.endsWith(compareValue); } else if (command.operator === exports.operator.eq) { valid = value === compareValue; } else if (command.operator === exports.operator.ge) { valid = value >= compareValue; } else if (command.operator === exports.operator.gt) { valid = value > compareValue; } else if (command.operator === exports.operator.le) { valid = value <= compareValue; } else if (command.operator === exports.operator.lt) { valid = value < compareValue; } else if (command.operator === exports.operator.ne) { valid = value != compareValue; } if (command.not) { valid = !valid; } if (command.filterTypes.length > 0) { for (var _i = 0, _a = command.filterTypes; _i < _a.length; _i++) { var childCommand = _a[_i]; valid = isValid(entity, childCommand, command, valid); } } valid = parentCommand != null ? (parentCommand.logicalOperator || command.logicalOperator) === exports.logicalOperator.and ? parentResult && valid : parentResult || valid : valid; return valid; } function filter(entities, webOption) { var resultEntities = []; var valid = entities && entities.length > 0 && webOption && webOption.filter !== ''; if (!valid) return resultEntities; var commands = getHierarchyCommands(webOption.filter); for (var _i = 0, entities_1 = entities; _i < entities_1.length; _i++) { var entity = entities_1[_i]; var result = true; var lastLogicalOperator = null; for (var _a = 0, commands_1 = commands; _a < commands_1.length; _a++) { var command = commands_1[_a]; if (!lastLogicalOperator && !command.logicalOperator) { lastLogicalOperator = command.logicalOperator; } var temp = isValid(entity, command); result = lastLogicalOperator != null ? lastLogicalOperator === exports.logicalOperator.and ? result && temp : result || temp : temp; lastLogicalOperator = command.logicalOperator; if (!result) break; } if (result) { resultEntities.push(entity); } } return resultEntities; } function setRefrentialCommands(result, currentCommand, commands, parentHierarchy) { if (parentHierarchy === void 0) { parentHierarchy = null; } var currentHierarchy = { attributeName: currentCommand.attributeName, operator: currentCommand.operator, value: currentCommand.value, filterTypes: [], logicalOperator: currentCommand.logicalOperator, not: currentCommand.not, }; if (parentHierarchy) { parentHierarchy.filterTypes = parentHierarchy.filterTypes.concat(currentHierarchy); } else if (commands.length > 0 && currentCommand.bracketOpenCt != currentCommand.bracketCloseCt) { do { var command = commands.shift(); if (!command) { return; } setRefrentialCommands(result, command, commands, currentHierarchy); currentCommand.bracketOpenCt += command.bracketOpenCt; currentCommand.bracketCloseCt += command.bracketCloseCt; } while (currentCommand.bracketOpenCt != currentCommand.bracketCloseCt); result.push(currentHierarchy); } else { result.push(currentHierarchy); } } function getHierarchyCommands(query) { var commands = getCommands(query); if (commands.length === 0) return null; var result = []; do { var currentCommand = commands.shift(); setRefrentialCommands(result, currentCommand, commands); } while (commands.length > 0); return result; } function getValueWithoutBracket(value, isHaveQuoteChar) { if (isHaveQuoteChar) { var bracketChar = value[0]; var bracketCloseIndex = -1; for (var i = value.length; i >= 0; i--) { var letter = value[i]; if (letter === bracketChar) { bracketCloseIndex = i; break; } } return value.substring(0, bracketCloseIndex); } var closeBracketCounter = 0; var lastLetter = ''; for (var i = value.length; i >= 0; i--) { var letter = value[i - 1]; if (letter === ')') { closeBracketCounter++; } lastLetter = letter; if (lastLetter !== ')') break; } return closeBracketCounter === 0 ? value : value.substring(0, value.length - closeBracketCounter); } function parsingValue(value) { var isHaveQuoteChar = value.startsWith("'") || value.startsWith('"'); var valueWithoutBracket = getValueWithoutBracket(value, isHaveQuoteChar); var from = isHaveQuoteChar ? 1 : 0; var to = valueWithoutBracket.endsWith("'") || valueWithoutBracket.endsWith('"') ? valueWithoutBracket.length - 1 : valueWithoutBracket.length; var result = value.substring(from, to); mappingLogicalOperators.forEach(function (e) { return (result = result.replace(e.replaceWord, e.word)); }); return { text: result, closeBracketCount: value.length - result.length, }; } var mappingLogicalOperators = [ { word: ' and ', replaceWord: ' _&_&_ ', }, { word: ' or ', replaceWord: ' _|_|_ ', }, ]; function transformText(value) { var quoteChars = ['"', "'"]; var tempText = value; var valid = quoteChars.some(function (e) { return tempText.indexOf(e) > -1; }); if (!valid) return tempText; var quotePositions = []; var _loop_1 = function (i_1) { var letter = tempText[i_1]; if (!quoteChars.some(function (e) { return letter === e; })) return "continue"; quotePositions.push(i_1); }; for (var i_1 = 0; i_1 < tempText.length; i_1++) { _loop_1(i_1); } var _loop_2 = function () { var beginIndex = quotePositions[i]; var endIndex = quotePositions[i + 1]; var checkText = tempText.substring(beginIndex, endIndex); mappingLogicalOperators.forEach(function (map) { var replaceText = checkText.replace(map.word, map.replaceWord); tempText = tempText.replace(checkText, replaceText); }); }; for (var i = 0; i < quotePositions.length - 1; i++) { _loop_2(); } return tempText; } function getCommands(query) { query = transformText(query); var result = []; var commonOperators = [' eq ', ' ne ', ' gt ', ' ge ', ' lt ', ' le ']; var specialOperators = ['contains(', 'endswith(', 'startswith(']; var logicalTypes = []; var logicalOperators = ['and', 'or']; var words = query.split(' '); var lastLogicalOperator = null; var lastIndexWord = 0; for (var i = 0; i < words.length; i++) { if (i == words.length - 1) { logicalTypes.push({ text: words.slice(lastIndexWord, i + 1).join(' '), logicalOperator: lastLogicalOperator, }); break; } var word = words[i]; if (logicalOperators.indexOf(word) === -1) continue; logicalTypes.push({ text: words.slice(lastIndexWord, i).join(' '), logicalOperator: lastLogicalOperator, }); lastLogicalOperator = word === 'and' ? exports.logicalOperator.and : exports.logicalOperator.or; lastIndexWord = i + 1; } for (var _i = 0, logicalTypes_1 = logicalTypes; _i < logicalTypes_1.length; _i++) { var datum = logicalTypes_1[_i]; for (var _a = 0, specialOperators_1 = specialOperators; _a < specialOperators_1.length; _a++) { var specialStr = specialOperators_1[_a]; if (datum.text.indexOf(specialStr) === -1) continue; var operatorType = specialStr.trim().indexOf('contains(') > -1 ? exports.operator.contains : specialStr.trim().indexOf('endswith(') > -1 ? exports.operator.endswith : exports.operator.startswith; var isNot = datum.text.startsWith('not '); var logicalTextCommand = isNot ? datum.text.substring(4, datum.text.length) : datum.text; logicalTextCommand = logicalTextCommand .substring(0, logicalTextCommand.length - 1) .replace(specialStr, ''); var data = logicalTextCommand.split(',').map(function (e) { return e.trim(); }); var attributeData = getAttributeData(data.shift()); datum.text = ''; var specialValue = parsingValue(data.join(',')); var filter_1 = { attributeName: attributeData.attributeName, operator: operatorType, value: specialValue.text, logicalOperator: datum.logicalOperator, not: isNot, bracketOpenCt: attributeData.bracketOpenCt, bracketCloseCt: specialValue.closeBracketCount, }; result.push(filter_1); } if (datum.text === '') continue; for (var _b = 0, commonOperators_1 = commonOperators; _b < commonOperators_1.length; _b++) { var operatorStr = commonOperators_1[_b]; if (datum.text.indexOf(operatorStr) === -1) continue; var data = datum.text.split(operatorStr); var operatorType = operatorStr.trim() === 'eq' ? exports.operator.eq : operatorStr.trim() === 'ne' ? exports.operator.ne : operatorStr.trim() === 'gt' ? exports.operator.gt : operatorStr.trim() === 'ge' ? exports.operator.ge : operatorStr.trim() === 'lt' ? exports.operator.lt : exports.operator.le; var attributeData = getAttributeData(data[0]); var commonData = parsingValue(data[1]); var filter_2 = { attributeName: attributeData.attributeName, operator: operatorType, value: commonData.text, logicalOperator: datum.logicalOperator, bracketOpenCt: attributeData.bracketOpenCt, bracketCloseCt: commonData.closeBracketCount, }; result.push(setIsNot(filter_2)); } } return result; } function getAttributeData(attributeName) { if (!attributeName.startsWith('(')) return { bracketOpenCt: 0, attributeName: attributeName }; var found = 0; var lastLetter = ''; for (var _i = 0, attributeName_1 = attributeName; _i < attributeName_1.length; _i++) { var letter = attributeName_1[_i]; lastLetter = letter; if (letter === '(') { found++; } if (lastLetter !== '(') { break; } } return { bracketOpenCt: found, attributeName: attributeName.substring(found, attributeName.length), }; } function setIsNot(filterType) { var isNot = filterType.attributeName.indexOf('not ') > -1; return { attributeName: isNot ? filterType.attributeName.replace('not ', '') : filterType.attributeName, operator: filterType.operator, value: filterType.value, logicalOperator: filterType.logicalOperator, not: isNot, bracketCloseCt: filterType.bracketCloseCt, bracketOpenCt: filterType.bracketOpenCt, }; } function top(entities, webOption) { if (!webOption.top) return entities; var result = []; var maxIndex = Number(webOption.top) - 1; for (var i = 0; i < entities.length; i++) { result.push(entities[i]); if (i === maxIndex) break; } return result; } var orderBy; (function (orderBy) { orderBy[orderBy["asc"] = 0] = "asc"; orderBy[orderBy["desc"] = 1] = "desc"; })(orderBy || (orderBy = {})); function order(entities, webApiOption) { if (!webApiOption.orderby) return entities; var orders = webApiOption.orderby.split(',').map(function (text) { var commands = text.split(' '); return { attributeName: commands[0], orderBy: commands.length > 1 ? commands[1] === 'asc' ? orderBy.asc : orderBy.desc : orderBy.asc, }; }); var _loop_1 = function (order_1) { var isAsc = order_1.orderBy === orderBy.asc; entities = entities.sort(function (a, b) { var aValue = a[order_1.attributeName]; var bValue = b[order_1.attributeName]; if (aValue === bValue) return 0; return isAsc ? (aValue < bValue ? -1 : 1) : aValue > bValue ? -1 : 1; }); }; for (var _i = 0, orders_1 = orders; _i < orders_1.length; _i++) { var order_1 = orders_1[_i]; _loop_1(order_1); } return entities; } function getMetadataExpand(webOption) { var isExpandValid = webOption.expand && webOption.expand.indexOf('($select') > -1; if (!isExpandValid) return [{ isExpand: false, selectAttributes: '', entity: '' }]; var result = []; var data = webOption.expand.split(')'); for (var _i = 0, data_1 = data; _i < data_1.length; _i++) { var row = data_1[_i]; var datum = row.split('($select='); var entityAttribute = datum[0].replace(',', ''); var attributes = datum[1]; result.push({ entity: entityAttribute, isExpand: true, selectAttributes: attributes, }); } return result; } function setForObject(temp, attribute, value, metadatas) { if (value === {}) return; var metadata = metadatas.find(function (e) { return e.entity === attribute; }); if (!metadata) return; if (!metadata.isExpand) return; var entityValue = select(value, { select: metadata.selectAttributes, }); temp[attribute] = entityValue; } function setForArray(temp, attribute, value, metadatas) { if (!Array.isArray(value)) return; var resultArray = []; var metadata = metadatas.find(function (e) { return e.entity === attribute; }); if (!metadata) return; if (!metadata.isExpand) return; var arrayValue = value; for (var _i = 0, arrayValue_1 = arrayValue; _i < arrayValue_1.length; _i++) { var record = arrayValue_1[_i]; var entityValue = select(record, { select: metadata.selectAttributes, }); resultArray.push(entityValue); } temp[attribute] = resultArray; } function filterEntity(metadatas, entity) { var temp = { id: entity.id, logicalName: entity.logicalName, }; var attributes = Object.keys(entity); for (var _i = 0, attributes_1 = attributes; _i < attributes_1.length; _i++) { var attribute = attributes_1[_i]; var value = entity[attribute]; var valueType = typeof value; if (valueType !== 'object') { temp[attribute] = value; continue; } setForObject(temp, attribute, value, metadatas); setForArray(temp, attribute, value, metadatas); } return temp; } function expand(entities, webOption) { var resultEntities = []; var metadatas = getMetadataExpand(webOption); for (var _i = 0, entities_1 = entities; _i < entities_1.length; _i++) { var entity = entities_1[_i]; var temp = filterEntity(metadatas, entity); resultEntities.push(temp); } return resultEntities; } function guid() { function s4() { return Math.floor((1 + Math.random()) * 0x10000) .toString(16) .substring(1); } return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); } var InMemoryWebApi = /** @class */ (function () { function InMemoryWebApi(testContext) { this.testContext = testContext; this.entities = []; } InMemoryWebApi.prototype.init = function (entities) { this.entities = entities; }; InMemoryWebApi.prototype.getEntitiesByLogicalName = function (entityLogicalName) { return this.entities.filter(function (e) { return e.logicalName === entityLogicalName; }); }; InMemoryWebApi.prototype.getIndex = function (entityLogicalName, id) { var index = this.entities.findIndex(function (e) { return e.id === id && e.logicalName === entityLogicalName; }); return index; }; InMemoryWebApi.prototype.get = function (entityLogicalName, id) { var _a; var index = this.getIndex(entityLogicalName, id); return (_a = this.entities[index]) !== null && _a !== void 0 ? _a : null; }; InMemoryWebApi.prototype.replace = function (entityLogicalName, id, data) { var index = this.getIndex(entityLogicalName, id); this.entities[index] = data; }; InMemoryWebApi.prototype.isAvailableOffline = function (entityLogicalName) { throw new Error('Method not implemented.'); }; InMemoryWebApi.prototype.getEntities = function () { return this.entities; }; InMemoryWebApi.prototype.createRecord = function (entityLogicalName, record) { var _this = this; var promise = new Promise(function (resolve, reject) { try { var id = guid(); var entity = toEntity(entityLogicalName, id, record); _this.entities.push(entity); _this.testContext.createdEntities.push(entity); var result = { entityType: entityLogicalName, id: id, }; resolve(result); } catch (ex) { reject(ex); } }); return promise; }; InMemoryWebApi.prototype.deleteRecord = function (entityLogicalName, id) { var _this = this; var promise = new Promise(function (resolve, reject) { try { var index = _this.getIndex(entityLogicalName, id); var entity = _this.get(entityLogicalName, id); _this.testContext.deletedEntities.push(entity); _this.entities.splice(index, 1); var result = { entityType: entityLogicalName, id: id, }; resolve(JSON.stringify(result)); } catch (ex) { reject(ex); } }); return promise; }; InMemoryWebApi.prototype.retrieveRecord = function (entityLogicalName, id, options) { var _this = this; var promise = new Promise(function (resolve, reject) { try { var entity = _this.get(entityLogicalName, id); var webOption = getWebApiOption(options); var selectEntity = select(entity, webOption); var webEntity = toWebApiEntity(selectEntity); resolve(webEntity); } catch (ex) { reject(ex); } }); return promise; }; InMemoryWebApi.prototype.retrieveMultipleRecords = function (entityLogicalName, options, maxPageSize) { var _this = this; var promise = new Promise(function (resolve, reject) { try { var result = { entities: [], nextLink: null, }; var entitiesByLogicalName = _this.getEntitiesByLogicalName(entityLogicalName); var webOption = getWebApiOption(options); result.entities = filter(entitiesByLogicalName, webOption); result.entities = order(entitiesByLogicalName, webOption); result.entities = top(result.entities, webOption); result.entities = expand(result.entities, webOption); resolve(result); } catch (ex) { reject(ex); } }); return promise; }; InMemoryWebApi.prototype.updateRecord = function (entityLogicalName, id, data) { var _this = this; var promise = new Promise(function (resolve, reject) { try { var record = _this.get(entityLogicalName, id); var target = toEntity(entityLogicalName, id, data); var updated = update(record, target); _this.testContext.updatedEntities.push(updated); _this.replace(entityLogicalName, id, updated); var result = { entityType: entityLogicalName, id: id, }; resolve(result); } catch (ex) { reject(ex); } }); return promise; }; return InMemoryWebApi; }()); var TestApiContext = /** @class */ (function () { function TestApiContext() { this._createdEntities = []; this._updatedEntities = []; this._deletedEntities = []; } Object.defineProperty(TestApiContext.prototype, "createdEntities", { get: function () { return this._createdEntities; }, enumerable: false, configurable: true }); Object.defineProperty(TestApiContext.prototype, "updatedEntities", { get: function () { return this._updatedEntities; }, enumerable: false, configurable: true }); Object.defineProperty(TestApiContext.prototype, "deletedEntities", { get: function () { return this._deletedEntities; }, enumerable: false, configurable: true }); Object.defineProperty(TestApiContext.prototype, "webApi", { get: function () { if (!this._webApi) { this._webApi = new InMemoryWebApi(this); } return this._webApi; }, enumerable: false, configurable: true }); TestApiContext.prototype.init = function (entities) { this.webApi.init(entities); }; return TestApiContext; }()); exports.InMemoryWebApi = InMemoryWebApi; exports.TestApiContext = TestApiContext; exports.expand = expand; exports.filter = filter; exports.getCommands = getCommands; exports.getHierarchyCommands = getHierarchyCommands; exports.getWebApiOption = getWebApiOption; exports.order = order; exports.parseValue = parseValue; exports.parsingValue = parsingValue; exports.select = select; exports.toEntity = toEntity; exports.toWebApiEntity = toWebApiEntity; exports.top = top; exports.transformText = transformText; exports.update = update; Object.defineProperty(exports, '__esModule', { value: true }); })));