UNPKG

@aurahelper/xml-compressor

Version:

Libraries to compress any Salesforce Metadata XML Files to change the format. This library make easy the work with GIT and other Version Control Systems because grant always the same order of the elements, compress the file for ocuppy less storage and mak

698 lines 37.7 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (_) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.XMLCompressor = exports.SORT_ORDER = void 0; var core_1 = require("@aurahelper/core"); var languages_1 = require("@aurahelper/languages"); var xml_definitions_1 = require("@aurahelper/xml-definitions"); var events_1 = __importDefault(require("events")); var XMLUtils = languages_1.XML.XMLUtils; var XMLParser = languages_1.XML.XMLParser; var Validator = core_1.CoreUtils.Validator; var Utils = core_1.CoreUtils.Utils; var NEWLINE = '\r\n'; exports.SORT_ORDER = { SIMPLE_FIRST: 'simpleFirst', COMPLEX_FIRST: 'complexFirst', ALPHABET_ASC: 'alphabetAsc', ALPHABET_DESC: 'alphabetDesc' }; var ON_COMPRESS_SUCCESS = 'compressSucess'; var ON_COMPRESS_FAILED = 'compressFailed'; /** * Class to compress any Salesforce Metadata XML Files to change the format * to make easy the work with GIT or another Version Control Systems because grant always the same order of the elements, * compress the file for ocuppy less storage and make GIT faster and, * specially make merges conflict more easy to resolve because identify the changes better. * * You can choose the sort order of the elements to reorganize the XML data as you like. * * The setters methods are defined like a builder pattern to make it more usefull */ var XMLCompressor = /** @class */ (function () { /** * Constructor to create a new XML Compressor object * @param {string | string[]} [pathOrPaths] Path or paths to files or folder to compress * @param {string} [sortOrder] Sort order to order the XML elements. Values: simpleFirst, complexFirst, alphabetAsc or alphabetDesc. (alphabetAsc by default) */ function XMLCompressor(pathOrPaths, sortOrder) { this.paths = pathOrPaths ? XMLUtils.forceArray(pathOrPaths) : []; this.sortOrder = (sortOrder && Object.values(exports.SORT_ORDER).includes(sortOrder)) ? sortOrder : exports.SORT_ORDER.ALPHABET_ASC; this.content = undefined; this.xmlRoot = undefined; this._xmlDefinition = undefined; this._compressedContent = undefined; this._event = new events_1.default(); } /** * Method to handle when a file compression failed. The callback method will be execute with any file compression error when execute compress() method. * @param {Function} onFailedCallback Callback function to handle the event * * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.onCompressFailed = function (onFailedCallback) { this._event.on(ON_COMPRESS_FAILED, onFailedCallback); return this; }; /** * Method to handle when a file compressed succesfully. The callback method will be execute with any compressed file when execute compress() method. * @param {Function} onSuccessCallback Callback function to handle the event * * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.onCompressSuccess = function (onSuccessCallback) { this._event.on(ON_COMPRESS_SUCCESS, onSuccessCallback); return this; }; /** * Method to set the file or folder path or paths to execute compressor operations * @param {string | string[]} pathOrPaths Path or paths to files or folder to compress * * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.setPaths = function (pathOrPaths) { if (!this.paths) { this.paths = []; } this.paths = XMLUtils.forceArray(pathOrPaths); return this; }; /** * Method to add a file or folder path or paths to execute compressor operations * @param {string | string[]} pathOrPaths Path or paths to files or folder to compress * * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.addPaths = function (pathOrPaths) { if (!this.paths) { this.paths = []; } if (pathOrPaths) { pathOrPaths = XMLUtils.forceArray(pathOrPaths); this.paths = this.paths.concat(pathOrPaths); } return this; }; /** * Method to set a XML string content to execute compressor operations (except compress() and compressSync() and methods because only work with file or folder paths) * @param {string} content string XML content to compress. * * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.setContent = function (content) { this.content = content; return this; }; /** * Method to set the XML Parsed object to execute compressor operations (except compress() and compressSync() and methods because only work with file or folder paths) (Usgin XMLParser from @aurahelper/languages module) * @param {any} xmlRoot XML Parsed object with XMLParser from languages module * * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.setXMLRoot = function (xmlRoot) { this.xmlRoot = xmlRoot; return this; }; /** * Method to set the sort order value to sort the XML Elements when compress * @param {string} sortOrder Sort order to order the XML elements. Values: simpleFirst, complexFirst, alphabetAsc or alphabetDesc. (alphabetAsc by default). * * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.setSortOrder = function (sortOrder) { this.sortOrder = (sortOrder && Object.values(exports.SORT_ORDER).includes(sortOrder)) ? sortOrder : exports.SORT_ORDER.ALPHABET_ASC; return this; }; /** * Method to set Simple XML Elements first as sort order (simpleFirst) * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.sortSimpleFirst = function () { this.sortOrder = exports.SORT_ORDER.SIMPLE_FIRST; return this; }; /** * Method to set Complex XML Elements first as sort order (complexFirst) * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.sortComplexFirst = function () { this.sortOrder = exports.SORT_ORDER.COMPLEX_FIRST; return this; }; /** * Method to set Alphabet Asc as sort order (alphabetAsc) * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.sortAlphabetAsc = function () { this.sortOrder = exports.SORT_ORDER.ALPHABET_ASC; return this; }; /** * Method to set Alphabet Desc as sort order (alphabetDesc) * @returns {XMLCompressor} Return the XMLCompressor instance */ XMLCompressor.prototype.sortAlphabetDesc = function () { this.sortOrder = exports.SORT_ORDER.ALPHABET_DESC; return this; }; /** * Method to get the XML compressed content from a file path, string content or XMLRoot object on sync mode. * XMLRoot object has priority over string content to be processed, and string content priority over path. For example, if you pass content and XMLRoot object to compressor, this method will be run with the XMLRoot data. * @returns {string} Returns a string with the compressed content * * @throws {OperationNotSupportedException} If the file does not support compression * @throws {OperationNotAllowedException} If the file path is a folder path * @throws {DataNotFoundException} If has no paths, content or XML Root to process * @throws {WrongFilePathException} If the file Path is not a string or can't convert to absolute path * @throws {FileNotFoundException} If the file not exists or not have access to it * @throws {InvalidFilePathException} If the path is not a file */ XMLCompressor.prototype.getCompressedContentSync = function () { if (this._compressedContent) { return this._compressedContent; } if (!this.content && !this.xmlRoot) { if (this.paths.length > 1) { throw new core_1.OperationNotAllowedException('Can\'t get compressed content from more than one file'); } else if (!this.paths || this.paths.length === 0) { throw new core_1.DataNotFoundException('Not path, content or XML Root to get the compressed XML content'); } else if (core_1.FileChecker.isDirectory(this.paths[0])) { throw new core_1.OperationNotAllowedException('Can\'t get compressed content from a directory. Select a single file'); } this.paths[0] = Validator.validateFilePath(this.paths[0]); this.content = core_1.FileReader.readFileSync(this.paths[0]); } if (!this.xmlRoot) { this.xmlRoot = XMLParser.parseXML(this.content, true); } var type = Object.keys(this.xmlRoot)[0]; if (!this._xmlDefinition) { this._xmlDefinition = xml_definitions_1.XMLDefinitions.getRawDefinition(type); } var xmlData = XMLUtils.cleanXMLFile(this._xmlDefinition, this.xmlRoot[type]); if (xmlData === undefined) { throw new core_1.OperationNotSupportedException('The selected XML content of MetadataType ' + type + ' does not support compression'); } this._compressedContent = processXMLData(type, xmlData, this._xmlDefinition, this.sortOrder); return this._compressedContent; }; /** * Method to get the XML compressed content from a file path, string content or XMLRoot object on async mode. * XMLRoot object has priority over string content to be processed, and string content priority over path. For example, if you pass content and XMLRoot object to compressor, this method will be run with the XMLRoot data. * @returns {Promise<string>} Returns a string Promise with the compressed content * * @throws {OperationNotSupportedException} If the file does not support compression * @throws {OperationNotAllowedException} If the file path is a folder path * @throws {DataNotFoundException} If has no paths, content or XML Root to process * @throws {WrongFilePathException} If the file Path is not a string or can't convert to absolute path * @throws {FileNotFoundException} If the file not exists or not have access to it * @throws {InvalidFilePathException} If the path is not a file */ XMLCompressor.prototype.getCompressedContent = function () { var _this = this; return new Promise(function (resolve, reject) { try { if (_this._compressedContent) { resolve(_this._compressedContent); return; } if (!_this.content && !_this.xmlRoot) { if (_this.paths.length > 1) { throw new core_1.OperationNotAllowedException('Can\'t get compressed content from more than one file'); } else if (!_this.paths || _this.paths.length === 0) { throw new core_1.DataNotFoundException('Not path, content or XML Root to get the compressed XML content'); } else if (core_1.FileChecker.isDirectory(_this.paths[0])) { throw new core_1.OperationNotAllowedException('Can\'t get compressed content from a directory. Select a single file'); } _this.paths[0] = Validator.validateFilePath(_this.paths[0]); _this.content = core_1.FileReader.readFileSync(_this.paths[0]); } if (!_this.xmlRoot) { _this.xmlRoot = XMLParser.parseXML(_this.content, true); } var type = Object.keys(_this.xmlRoot)[0]; if (!_this._xmlDefinition) { _this._xmlDefinition = xml_definitions_1.XMLDefinitions.getRawDefinition(type); } var xmlData = XMLUtils.cleanXMLFile(_this._xmlDefinition, _this.xmlRoot[type]); if (xmlData === undefined) { throw new core_1.OperationNotSupportedException('The selected XML content of MetadataType ' + type + ' does not support compression'); } _this._compressedContent = processXMLData(type, xmlData, _this._xmlDefinition, _this.sortOrder); resolve(_this._compressedContent); } catch (error) { reject(error); } }); }; /** * Method to get the XML compressed content from a file path on sync mode. * * @throws {OperationNotSupportedException} If the file does not support compression * @throws {OperationNotAllowedException} If the file path is a folder path * @throws {DataNotFoundException} If has no paths to process * @throws {WrongFilePathException} If the file Path is not a string or can't convert to absolute path * @throws {FileNotFoundException} If the file not exists or not have access to it * @throws {InvalidFilePathException} If the path is not a file */ XMLCompressor.prototype.compressSync = function () { if (this.paths.length > 1) { throw new core_1.OperationNotAllowedException('Can\'t compress more than one file on sync mode. Execute compress() method compress several files'); } else if (!this.paths || this.paths.length === 0) { throw new core_1.DataNotFoundException('Has no paths to get the compressed XML content'); } else if (core_1.FileChecker.isDirectory(this.paths[0])) { throw new core_1.OperationNotAllowedException('Can\'t compress directory on sync mode. Execute compress() method to compress entire directory'); } this.paths[0] = Validator.validateFilePath(this.paths[0]); this.content = core_1.FileReader.readFileSync(this.paths[0]); this.xmlRoot = XMLParser.parseXML(this.content, true); var type = Object.keys(this.xmlRoot)[0]; this._xmlDefinition = xml_definitions_1.XMLDefinitions.getRawDefinition(type); var xmlData = XMLUtils.cleanXMLFile(this._xmlDefinition, this.xmlRoot[type]); if (xmlData === undefined) { throw new core_1.OperationNotSupportedException('The selected XML content of MetadataType ' + type + ' does not support compression'); } this._compressedContent = processXMLData(type, xmlData, this._xmlDefinition, this.sortOrder); core_1.FileWriter.createFileSync(this.paths[0], this._compressedContent); }; /** * Method to compress a XML File, a List of files or entire folder (and subfolders) in Async mode. This methods fire some events to handle compress progress. * Use onCompressFailed() and onCompressSuccess() methods to handling progress. * * @returns {Promise<void>} Returns an empty Promise * * @throws {OperationNotSupportedException} If try to compress more than one folder, or file and folders at the same time * @throws {DataNotFoundException} If has no paths to process * @throws {WrongFilePathException} If the file Path is not a string or can't convert to absolute path * @throws {FileNotFoundException} If the file not exists or not have access to it * @throws {InvalidFilePathException} If the path is not a file * @throws {WrongDirectoryPathException} If the folder Path is not a string or cant convert to absolute path * @throws {DirectoryNotFoundException} If the directory not exists or not have access to it * @throws {InvalidDirectoryPathException} If the path is not a directory */ XMLCompressor.prototype.compress = function () { var _this = this; return new Promise(function (resolve, reject) { return __awaiter(_this, void 0, void 0, function () { var pathsToCompress, nFiles, nFolders, _i, _a, path, files, totalFiles, filesProcessed, oldType, xmlDefinition, _b, files_1, file, xmlRoot, type, xmlData, xmlContent, error_1; return __generator(this, function (_c) { switch (_c.label) { case 0: _c.trys.push([0, 4, , 5]); pathsToCompress = []; nFiles = 0; nFolders = 0; for (_i = 0, _a = this.paths; _i < _a.length; _i++) { path = _a[_i]; if (core_1.FileChecker.isFile(path)) { nFiles++; pathsToCompress.push(Validator.validateFilePath(path)); } else { nFolders++; pathsToCompress.push(Validator.validateFolderPath(path)); } } if (nFiles === 0 && nFolders === 0) { throw new core_1.DataNotFoundException('Not files or folders selected to compress'); } else if (nFiles > 0 && nFolders > 0) { throw new core_1.OperationNotSupportedException('Can\'t compress files and folders at the same time. Please, add only folders or files to compress'); } else if (nFolders > 1) { throw new core_1.OperationNotSupportedException('Can\'t compress more than one folder at the same time.'); } files = void 0; if (!(nFolders === 1)) return [3 /*break*/, 2]; return [4 /*yield*/, core_1.FileReader.getAllFiles(pathsToCompress[0], ['.xml'])]; case 1: files = _c.sent(); return [3 /*break*/, 3]; case 2: files = pathsToCompress; _c.label = 3; case 3: Utils.sort(files); totalFiles = files.length; filesProcessed = 0; oldType = void 0; xmlDefinition = void 0; for (_b = 0, files_1 = files; _b < files_1.length; _b++) { file = files_1[_b]; try { xmlRoot = XMLParser.parseXML(core_1.FileReader.readFileSync(file), true); type = Object.keys(xmlRoot)[0]; if (!xmlDefinition || type !== oldType) { xmlDefinition = xml_definitions_1.XMLDefinitions.getRawDefinition(type); } oldType = type; xmlData = XMLUtils.cleanXMLFile(xmlDefinition, xmlRoot[type]); if (xmlData === undefined) { throw new core_1.OperationNotSupportedException('The selected XML content of MetadataType ' + type + ' does not support compression'); } xmlContent = processXMLData(type, xmlData, xmlDefinition, this.sortOrder); core_1.FileWriter.createFileSync(file, xmlContent); filesProcessed++; this._event.emit(ON_COMPRESS_SUCCESS, { file: file, filesProcessed: filesProcessed, totalFiles: totalFiles }); } catch (error) { filesProcessed++; this._event.emit(ON_COMPRESS_FAILED, { file: file, filesProcessed: filesProcessed, totalFiles: totalFiles }); } } resolve(); return [3 /*break*/, 5]; case 4: error_1 = _c.sent(); reject(error_1); return [3 /*break*/, 5]; case 5: return [2 /*return*/]; } }); }); }); }; /** * Method to get the Sort Order values object * @returns {XMLSortOrder} Return and object with the available sort order values */ XMLCompressor.getSortOrderValues = function () { return exports.SORT_ORDER; }; return XMLCompressor; }()); exports.XMLCompressor = XMLCompressor; function processXMLData(type, xmlData, xmlDefinition, sortOrder) { var content = XMLParser.getXMLFirstLine() + NEWLINE; var attributes = XMLUtils.getAttributes(xmlData); var indent = 0; var objectKeys = getOrderedKeys(xmlDefinition, sortOrder); content += XMLParser.getStartTag(type, attributes) + NEWLINE; try { if (objectKeys) { for (var _i = 0, objectKeys_1 = objectKeys; _i < objectKeys_1.length; _i++) { var key = objectKeys_1[_i]; var fieldValue = xmlData[key]; if (fieldValue !== undefined) { if (!Array.isArray(fieldValue) && typeof fieldValue === 'object' && Object.keys(fieldValue).length === 0) { continue; } if (Array.isArray(fieldValue) && fieldValue.length === 0) { continue; } var fieldDefinition = xmlDefinition[key]; content += processXMLField(xmlDefinition, fieldDefinition, fieldValue, sortOrder, indent + 1); } } } } catch (error) { throw error; } content += XMLParser.getEndTag(type); return content; } function processXMLField(typeDefinition, fieldDefinition, fieldValue, sortOrder, indent) { var content = ''; if (mustCompress(fieldDefinition)) { if (isComplexField(fieldDefinition)) { var objectKeys = getOrderedKeys(fieldDefinition, sortOrder); if (Array.isArray(fieldValue) || fieldDefinition.datatype === core_1.Datatypes.ARRAY) { fieldValue = XMLUtils.forceArray(fieldValue); if (fieldDefinition.sortOrder !== undefined) { XMLUtils.sort(fieldValue, fieldDefinition.sortOrder); } for (var _i = 0, fieldValue_1 = fieldValue; _i < fieldValue_1.length; _i++) { var value = fieldValue_1[_i]; content += XMLUtils.getTabs(indent) + XMLParser.getStartTag(fieldDefinition.key, XMLUtils.getAttributes(fieldValue)); if (objectKeys) { for (var _a = 0, objectKeys_2 = objectKeys; _a < objectKeys_2.length; _a++) { var key = objectKeys_2[_a]; var subFieldValue = value[key]; if (subFieldValue !== undefined && subFieldValue !== null) { if (!Array.isArray(subFieldValue) && typeof subFieldValue === 'object' && Object.keys(subFieldValue).length === 0) { continue; } if (Array.isArray(subFieldValue) && subFieldValue.length === 0) { continue; } var subFieldDefinition = fieldDefinition.fields[key]; if (subFieldDefinition.definitionRef) { subFieldDefinition = xml_definitions_1.XMLDefinitions.resolveDefinitionReference(typeDefinition, subFieldDefinition); } if (subFieldDefinition.datatype === core_1.Datatypes.OBJECT) { content += processXMLField(typeDefinition, subFieldDefinition, subFieldValue, sortOrder, 0); } else { content += XMLParser.getXMLElement(subFieldDefinition.key, XMLUtils.getAttributes(subFieldValue), subFieldDefinition.prepareValue(subFieldValue)); } } } } else { content += fieldDefinition.prepareValue(value); } content += XMLParser.getEndTag(fieldDefinition.key) + NEWLINE; } } else { var empty = fieldValue === undefined || fieldValue === null || fieldValue === ''; if (!empty && fieldValue !== undefined && fieldValue['@attrs'] !== undefined && Object.keys(fieldValue).length === 1) { empty = true; } content += XMLUtils.getTabs(indent) + XMLParser.getStartTag(fieldDefinition.key, XMLUtils.getAttributes(fieldValue), empty); if (empty) { content += NEWLINE; } if (!empty) { if (objectKeys) { for (var _b = 0, objectKeys_3 = objectKeys; _b < objectKeys_3.length; _b++) { var key = objectKeys_3[_b]; var subFieldValue = fieldValue[key]; if (subFieldValue !== undefined && subFieldValue !== null) { if (!Array.isArray(subFieldValue) && typeof subFieldValue === 'object' && Object.keys(subFieldValue).length === 0) { continue; } if (Array.isArray(subFieldValue) && subFieldValue.length === 0) { continue; } var subFieldDefinition = fieldDefinition.fields[key]; { if (subFieldDefinition.definitionRef) { subFieldDefinition = xml_definitions_1.XMLDefinitions.resolveDefinitionReference(typeDefinition, subFieldDefinition); } } content += XMLParser.getXMLElement(subFieldDefinition.key, XMLUtils.getAttributes(subFieldValue), subFieldDefinition.prepareValue(subFieldValue)); } } } content += XMLParser.getEndTag(fieldDefinition.key) + (indent === 0 ? '' : NEWLINE); } } } else { content = XMLUtils.getTabs(indent) + XMLParser.getXMLElement(fieldDefinition.key, XMLUtils.getAttributes(fieldValue), fieldDefinition.prepareValue(fieldValue)) + NEWLINE; } } else { var objectKeys = getOrderedKeys(fieldDefinition, sortOrder); if (Array.isArray(fieldValue) || fieldDefinition.datatype === core_1.Datatypes.ARRAY) { fieldValue = XMLUtils.forceArray(fieldValue); if (fieldDefinition.sortOrder !== undefined) { XMLUtils.sort(fieldValue, fieldDefinition.sortOrder); } for (var _c = 0, fieldValue_2 = fieldValue; _c < fieldValue_2.length; _c++) { var value = fieldValue_2[_c]; if (!objectKeys || objectKeys.length == 0) { content += XMLUtils.getTabs(indent) + XMLParser.getStartTag(fieldDefinition.key, XMLUtils.getAttributes(fieldValue)) + fieldDefinition.prepareValue(value) + XMLParser.getEndTag(fieldDefinition.key) + NEWLINE; } else { content += XMLUtils.getTabs(indent) + XMLParser.getStartTag(fieldDefinition.key, XMLUtils.getAttributes(fieldValue)) + NEWLINE; for (var _d = 0, objectKeys_4 = objectKeys; _d < objectKeys_4.length; _d++) { var key = objectKeys_4[_d]; var subFieldValue = value[key]; if (subFieldValue !== undefined && subFieldValue !== null) { if (!Array.isArray(subFieldValue) && typeof subFieldValue === 'object' && Object.keys(subFieldValue).length === 0) { continue; } if (Array.isArray(subFieldValue) && subFieldValue.length === 0) { continue; } var subFieldDefinition = fieldDefinition.fields[key]; if (subFieldDefinition.definitionRef) { subFieldDefinition = xml_definitions_1.XMLDefinitions.resolveDefinitionReference(typeDefinition, subFieldDefinition); } content += processXMLField(typeDefinition, subFieldDefinition, subFieldValue, sortOrder, indent + 1); } } content += XMLUtils.getTabs(indent) + XMLParser.getEndTag(fieldDefinition.key) + NEWLINE; } } } else { var empty = fieldValue === undefined || fieldValue === null || fieldValue === ''; if (!empty && fieldValue['@attrs'] !== undefined && Object.keys(fieldValue).length === 1) { empty = true; } content += XMLUtils.getTabs(indent) + XMLParser.getStartTag(fieldDefinition.key, XMLUtils.getAttributes(fieldValue), empty) + NEWLINE; if (!empty) { try { if (objectKeys) { for (var _e = 0, objectKeys_5 = objectKeys; _e < objectKeys_5.length; _e++) { var key = objectKeys_5[_e]; var subFieldValue = fieldValue[key]; if (subFieldValue !== undefined && subFieldValue !== null) { if (!Array.isArray(subFieldValue) && typeof subFieldValue === 'object' && Object.keys(subFieldValue).length === 0) { continue; } if (Array.isArray(subFieldValue) && subFieldValue.length === 0) { continue; } var subFieldDefinition = fieldDefinition.fields[key]; if (subFieldDefinition.definitionRef) { subFieldDefinition = xml_definitions_1.XMLDefinitions.resolveDefinitionReference(typeDefinition, subFieldDefinition); } content += processXMLField(typeDefinition, subFieldDefinition, subFieldValue, sortOrder, indent + 1); } } } } catch (error) { throw error; } content += XMLUtils.getTabs(indent) + XMLParser.getEndTag(fieldDefinition.key) + NEWLINE; } } } return content; } function mustCompress(field) { var compress = false; if (isComplexField(field)) { if (field.compress) { compress = true; } else { if (Utils.hasKeys(field.fields)) { compress = true; for (var _i = 0, _a = Object.keys(field.fields); _i < _a.length; _i++) { var key = _a[_i]; if (isComplexField(field.fields[key])) { compress = false; break; } } } } } else { compress = true; } return compress; } function getOrderedKeys(xmlEntity, sortOrder) { var entityKeys; if (isComplexField(xmlEntity)) { if (xmlEntity.fields) { xmlEntity = xmlEntity.fields; } else { return undefined; } } entityKeys = Object.keys(xmlEntity); if (sortOrder === exports.SORT_ORDER.ALPHABET_ASC) { entityKeys.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }); } else if (sortOrder === exports.SORT_ORDER.ALPHABET_DESC) { entityKeys.sort(function (a, b) { return b.toLowerCase().localeCompare(a.toLowerCase()); }); } else if (sortOrder === exports.SORT_ORDER.SIMPLE_FIRST || sortOrder === exports.SORT_ORDER.COMPLEX_FIRST) { var simpleKeys = []; var complexKeys = []; for (var _i = 0, entityKeys_1 = entityKeys; _i < entityKeys_1.length; _i++) { var key = entityKeys_1[_i]; if (isComplexField(xmlEntity[key])) { complexKeys.push(key); } else { simpleKeys.push(key); } } simpleKeys.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }); complexKeys.sort(function (a, b) { return a.toLowerCase().localeCompare(b.toLowerCase()); }); entityKeys = []; if (sortOrder === exports.SORT_ORDER.SIMPLE_FIRST) { entityKeys = entityKeys.concat(simpleKeys); entityKeys = entityKeys.concat(complexKeys); } else { entityKeys = entityKeys.concat(complexKeys); entityKeys = entityKeys.concat(simpleKeys); } } return entityKeys; } function isComplexField(xmlField) { return xmlField.datatype === core_1.Datatypes.ARRAY || xmlField.datatype === core_1.Datatypes.OBJECT; } //# sourceMappingURL=index.js.map