UNPKG

@aurahelper/package-generator

Version:

Aura Helper Package Generator Module to create Salesforce XML Package, to deploy, retrieve or delete elements on your Org. Support to create package from JSON File, Git Diffs or Mergin other packages.

536 lines 31.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PackageGenerator = void 0; var languages_1 = require("@aurahelper/languages"); var core_1 = require("@aurahelper/core"); var utils_1 = require("@aurahelper/core/dist/utils"); var metadata_factory_1 = require("@aurahelper/metadata-factory"); var ignore_1 = require("@aurahelper/ignore"); var XMLUtils = languages_1.XML.XMLUtils; var XMLParser = languages_1.XML.XMLParser; var Utils = core_1.CoreUtils.Utils; var Validator = core_1.CoreUtils.Validator; var START_XML_FILE = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"; var PACKAGE_TAG_START = "<Package xmlns=\"http://soap.sforce.com/2006/04/metadata\">"; var PACKAGE_TAG_END = "</Package>"; var VERSION_TAG_START = "<version>"; var VERSION_TAG_END = "</version>"; var TYPES_TAG_START = "<types>"; var TYPES_TAG_END = "</types>"; var NAME_TAG_START = "<name>"; var NAME_TAG_END = "</name>"; var MEMBERS_TAG_START = "<members>"; var MEMBERS_TAG_END = "</members>"; var NEWLINE = '\n'; var DESTRUCT_BEFORE_FILENAME = 'destructiveChanges.xml'; var DESTRUCT_AFTER_FILENAME = 'destructiveChangesPost.xml'; var PACKAGE_FILENAME = 'package.xml'; var DESTRUCT_BEFORE_NO_EXT = 'destructiveChanges'; var DESTRUCT_AFTER_NO_EXT = 'destructiveChangesPost'; var PACKAGE_NO_EXT = 'package'; var NOT_ALLOWED_WILDCARDS = []; /** * Class to create and merge package files to deploy, retrieve or delete metadata from your Salesforce's projects. * * Can merge several package xml files (including destructiveChanges.xml and destructiveChangesPost.xml files) to combine into one file of each type, * combine all packages in one file and all detructives in another file or merge all files into one package or destructive file. * * The file names must contains at least the "package" word to identify the package XML files * and destructiveChanges or destrutiveChangesPost to the destructive files. * For example: package1.xml, destructiveChanges_uat.xml, destructiveChangesPost-v34... * * You can choose a custom API Version to create the packages, * if not specified API version, the package generator get the higher API version * from each file types, that is, for package XML files, * get the higher API of the Package XML files passed, and the same with other file types. * * The setters methods are defined like a builder pattern to make it more usefull */ var PackageGenerator = /** @class */ (function () { /** * Constructor to instance a new PackageGenerator object * @param {string | number} [apiVersion] Api version to create the package. If not provided use the latest api version of the provided files */ function PackageGenerator(apiVersion) { this.apiVersion = apiVersion; this.mergePackageFiles = true; this.mergeDestructives = false; this.isDestructive = false; this.beforeDeploy = false; this.explicit = true; this.ignoreFile = undefined; this.typesToIgnore = undefined; this.destructiveIgnoreFile = undefined; } /** * Method to Set the api version to create the packages * @param {string | number} apiVersion Api version to create the package. If not provided use the latest api version of the provided files * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setApiVersion = function (apiVersion) { this.apiVersion = apiVersion; return this; }; /** * Method to set if merge package files * @param {boolean} [mergePackageFiles] true if want to merge the provided package files. If undefiend ot not has param, also set to true * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setMergePackagesFiles = function (mergePackageFiles) { this.mergePackageFiles = (mergePackageFiles !== undefined && Utils.isBoolean(mergePackageFiles)) ? mergePackageFiles : true; return this; }; /** * Method to set if merge destructive files * @param {boolean} [mergeDestructives] true if want to merge the provided destructive files into one single file. If undefiend ot not has param, also set to true * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setMergeDestructives = function (mergeDestructives) { this.mergeDestructives = (mergeDestructives !== undefined && Utils.isBoolean(mergeDestructives)) ? mergeDestructives : true; return this; }; /** * Method to set if merge all package and XML destructive files into one destructive file * @param {boolean} [isDestructive] true if you want to merge all files into one destructive file (valid option to merge packages full). If undefiend ot not has param, also set to true * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setIsDestructive = function (isDestructive) { this.isDestructive = (isDestructive !== undefined && Utils.isBoolean(isDestructive)) ? isDestructive : true; return this; }; /** * Method to set if the destructive file to create is before deploy, in otherwise create destructive files after deploy * @param {boolean} [beforeDeploy] true if want to merge destructive files into before deploy destructive file when select mergeDestructives. If undefiend ot not has param, also set to true * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setBeforeDeploy = function (beforeDeploy) { this.beforeDeploy = (beforeDeploy !== undefined && Utils.isBoolean(beforeDeploy)) ? beforeDeploy : true; return this; }; /** * Method to set if put all elements explicit on the package XML or use wildcards when apply * @param {boolean} [explicit] true if you want to put all metadata types explicit into the file, false to use wildcards when are all checked * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setExplicit = function (explicit) { this.explicit = (explicit !== undefined && Utils.isBoolean(explicit)) ? explicit : true; return this; }; /** * Method to set the path to the ignore file * @param {string} ignoreFile path to the ignore file to ignore some metadata types from the packages * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setIgnoreFile = function (ignoreFile) { this.ignoreFile = ignoreFile; return this; }; /** * Method to set the path to the ignore file to destructive package * @param {string} destructiveIgnoreFile path to the ignore file to ignore some metadata types from the packages * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setDestructiveIgnoreFile = function (destructiveIgnoreFile) { this.destructiveIgnoreFile = destructiveIgnoreFile; return this; }; /** * Method to set the Metadata Types to ignore from package (Also must be exists on ignore file) * @param {string | string[]} typesToIgnore List with the Metadata Type API Names to ignore. This parameter is used to ignore only the specified metadata (also must be in ignore file) and avoid ignore all metadata types specified on the file. * * @returns {PackageGenerator} Return the package generator instance */ PackageGenerator.prototype.setTypesToIgnore = function (typesToIgnore) { this.typesToIgnore = Utils.forceArray(typesToIgnore); return this; }; /** * Method to merge several package xml files (including destructiveChanges.xml and destructiveChangesPost.xml files) to combine into one file of each type, combine all packages in one file and all detructives in another file. * @param {string | string[]} packageOrDestructiveFiles File or list of files to merge (including package and destructive files in the same list) * @param {string} outputFolder Folder to save the created files * * @returns {PackageGeneratorResult} Object with the merge result including the paths of the merged files * * @throws {WrongDatatypeException} If api version is not a string or number (can be undefined) * @throws {DataNotFoundException} If not package or destructive files provided * @throws {WrongFilePathException} If the package or destructive files path is not a string or cant convert to absolute path * @throws {FileNotFoundException} If the package or destructive files path not exists or not have access to it * @throws {InvalidFilePathException} If the package or destructive files path is not a file * @throws {WrongDirectoryPathException} If the output Folder 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 */ PackageGenerator.prototype.mergePackages = function (packageOrDestructiveFiles, outputFolder) { if (this.apiVersion) { this.apiVersion = utils_1.ProjectUtils.getApiAsNumber(this.apiVersion); } if (this.mergePackageFiles === undefined) { this.mergePackageFiles = true; } var packages = []; var beforeDestructivePackages = []; var afterDestructivePackages = []; packageOrDestructiveFiles = XMLUtils.forceArray(packageOrDestructiveFiles); for (var _i = 0, packageOrDestructiveFiles_1 = packageOrDestructiveFiles; _i < packageOrDestructiveFiles_1.length; _i++) { var file = packageOrDestructiveFiles_1[_i]; file = Validator.validateFilePath(file); var fileName = core_1.PathUtils.getBasename(file); if (fileName.indexOf(PACKAGE_NO_EXT) !== -1 && this.mergePackageFiles) { packages.push(file); } else if (fileName.indexOf(DESTRUCT_AFTER_NO_EXT) !== -1) { afterDestructivePackages.push(file); } else if ((fileName.indexOf(DESTRUCT_BEFORE_NO_EXT) !== -1 && fileName.indexOf(DESTRUCT_AFTER_NO_EXT) === -1)) { beforeDestructivePackages.push(file); } if (this.mergeDestructives) { if (this.beforeDeploy) { beforeDestructivePackages = beforeDestructivePackages.concat(afterDestructivePackages); afterDestructivePackages = []; } else { afterDestructivePackages = afterDestructivePackages.concat(beforeDestructivePackages); beforeDestructivePackages = []; } } } if (packages.length === 0 && beforeDestructivePackages.length === 0 && afterDestructivePackages.length === 0) { throw new core_1.DataNotFoundException('Not package files (' + PACKAGE_NO_EXT + ') or destructive files (' + DESTRUCT_BEFORE_NO_EXT + ', ' + DESTRUCT_AFTER_NO_EXT + ') selected to merge'); } var mergedPackage = mergePackageFiles(packages, this.apiVersion); var mergedBeforeDestructive = mergePackageFiles(beforeDestructivePackages, this.apiVersion); var mergedAfterDestructive = mergePackageFiles(afterDestructivePackages, this.apiVersion); var result = new core_1.PackageGeneratorResult(); if (mergedPackage) { this.apiVersion = mergedPackage.version; result[PACKAGE_NO_EXT] = this.createPackage(metadata_factory_1.MetadataFactory.createMetadataTypesFromPackageXML(mergedPackage), outputFolder); } if (mergedBeforeDestructive) { this.apiVersion = mergedBeforeDestructive.version; result[DESTRUCT_BEFORE_NO_EXT] = this.createBeforeDeployDestructive(metadata_factory_1.MetadataFactory.createMetadataTypesFromPackageXML(mergedBeforeDestructive), outputFolder); } if (mergedAfterDestructive) { this.apiVersion = mergedAfterDestructive.version; result[DESTRUCT_AFTER_NO_EXT] = this.createAfterDeployDestructive(metadata_factory_1.MetadataFactory.createMetadataTypesFromPackageXML(mergedAfterDestructive), outputFolder); } return result; }; /** * Method to merge all provided files into only one file. You can choose if merge all into a package.xml, destructiveChanges.xml or destructiveChangesPost.xml * @param {string | string[]} packageOrDestructiveFiles file or list of files to merge (including package and destructive files in the same list) * @param {string} outputFolder Folder to save the created files. If not provided use the default options calling options() method * * @returns {PackageGeneratorResult} Object with the merge result including the paths of the merged files * * @throws {WrongDatatypeException} If api version is not a string or number (can be undefined) * @throws {DataNotFoundException} If not package or destructive files provided * @throws {WrongFilePathException} If the package or destructive files path is not a string or cant convert to absolute path * @throws {FileNotFoundException} If the package or destructive files path not exists or not have access to it * @throws {InvalidFilePathException} If the package or destructive files path is not a file * @throws {WrongDirectoryPathException} If the output Folder 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 */ PackageGenerator.prototype.mergePackagesFull = function (packageOrDestructiveFiles, outputFolder) { if (this.apiVersion) { this.apiVersion = utils_1.ProjectUtils.getApiAsNumber(this.apiVersion); } var packages = []; packageOrDestructiveFiles = XMLUtils.forceArray(packageOrDestructiveFiles); for (var _i = 0, packageOrDestructiveFiles_2 = packageOrDestructiveFiles; _i < packageOrDestructiveFiles_2.length; _i++) { var file = packageOrDestructiveFiles_2[_i]; file = Validator.validateFilePath(file); var fileName = core_1.PathUtils.getBasename(file); if (fileName.indexOf(PACKAGE_NO_EXT) !== -1) { packages.push(file); } else if (fileName.indexOf(DESTRUCT_AFTER_NO_EXT) !== -1) { packages.push(file); } else if (fileName.indexOf(DESTRUCT_BEFORE_NO_EXT) !== -1) { packages.push(file); } } if (packages.length === 0) { throw new core_1.DataNotFoundException('Not package files (' + PACKAGE_NO_EXT + ') or destructive files (' + DESTRUCT_BEFORE_NO_EXT + ', ' + DESTRUCT_AFTER_NO_EXT + ') selected to merge'); } var mergedPackage = mergePackageFiles(packages, this.apiVersion); var result = new core_1.PackageGeneratorResult(); if (mergedPackage) { this.apiVersion = mergedPackage.version; if (!this.isDestructive) { result[PACKAGE_NO_EXT] = this.createPackage(metadata_factory_1.MetadataFactory.createMetadataTypesFromPackageXML(mergedPackage), outputFolder); } else { if (this.beforeDeploy) { result[DESTRUCT_BEFORE_NO_EXT] = this.createBeforeDeployDestructive(metadata_factory_1.MetadataFactory.createMetadataTypesFromPackageXML(mergedPackage), outputFolder); } else { result[DESTRUCT_AFTER_NO_EXT] = this.createAfterDeployDestructive(metadata_factory_1.MetadataFactory.createMetadataTypesFromPackageXML(mergedPackage), outputFolder); } } } return result; }; /** * Method to get the Package XML format content as string to the selected Metadata JSON file or Metadata JSON Object * @param {string | { [key: string]: MetadataType }} metadataOrPath Metadata JSON file or Metadata JSON object to get the package or destructive XML content. If not provided use the default options calling options() method * @param {boolean} [useIgnoreDestructive] True to use the ignore destructive file to ignore the package content * * @returns {string} Returns an string with the XML content * * @throws {WrongDatatypeException} If api version is not a string or number. Can't be empty or undefined * @throws {WrongFilePathException} If the package or destructive file path is not a string or cant convert to absolute path * @throws {FileNotFoundException} If the package or destructive file path not exists or not have access to it * @throws {InvalidFilePathException} If the package or destructive file path is not a file * @throws {WrongFormatException} If file is not a JSON file or not have the correct Metadata JSON format * @throws {WrongDirectoryPathException} If the output Folder 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 */ PackageGenerator.prototype.getPackageContent = function (metadataOrPath, useIgnoreDestructive) { var _this = this; var metadata = PackageGenerator.validateJSON(metadataOrPath); if (this.ignoreFile || this.destructiveIgnoreFile) { var ignore = new ignore_1.Ignore().setTypesToIgnore(this.typesToIgnore); if (useIgnoreDestructive && this.destructiveIgnoreFile) { ignore.setIgnoreFile(this.destructiveIgnoreFile); } else if (this.ignoreFile) { ignore.setIgnoreFile(this.ignoreFile); } metadata = ignore.ignoreMetadata(metadata); } this.apiVersion = (this.apiVersion !== undefined) ? utils_1.ProjectUtils.getApiAsString(this.apiVersion) : this.apiVersion; this.explicit = (this.explicit !== undefined) ? this.explicit : true; var packageContent = ''; ; packageContent += START_XML_FILE + NEWLINE; packageContent += PACKAGE_TAG_START + NEWLINE; Object.keys(metadata).forEach(function (key) { var typesBlock = makeTypesBlock(metadata[key], _this.explicit); if (typesBlock) { packageContent += typesBlock; } }); packageContent += '\t' + VERSION_TAG_START + this.apiVersion + VERSION_TAG_END + NEWLINE; packageContent += PACKAGE_TAG_END; return packageContent; }; /** * Method to create a package XML file with the selected Metadata JSON file or Metadata JSON Object * @param {string | { [key: string]: MetadataType }} metadataOrPath Metadata JSON file or Metadata JSON object to create the package file * @param {string} outputFolder Folder to save the created file. If not provided use the default options calling options() method * * @returns {string} Returns the path to the created file * * @throws {WrongDatatypeException} If api version is not a string or number. Can't be empty or undefined * @throws {WrongFilePathException} If the package or destructive file path is not a string or cant convert to absolute path * @throws {FileNotFoundException} If the package or destructive file path not exists or not have access to it * @throws {InvalidFilePathException} If the package or destructive file path is not a file * @throws {WrongDirectoryPathException} If the output Folder 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 * @throws {WrongFormatException} If file is not a JSON file or not have the correct Metadata JSON format */ PackageGenerator.prototype.createPackage = function (metadataOrPath, outputFolder) { return createPackageFile(outputFolder, PACKAGE_FILENAME, this.getPackageContent(metadataOrPath)); }; /** * Method to create a before deploy destructive file with the selected Metadata JSON file or Metadata JSON Object * @param {string | { [key: string]: MetadataType }} metadataOrPath Metadata JSON file or Metadata JSON object to create the destructive file * @param {string} outputFolder Folder to save the created file. If not provided use the default options calling options() method * * @returns {string} Returns the path to the created file * * @throws {WrongDatatypeException} If api version is not a string or number. Can't be empty or undefined * @throws {WrongFilePathException} If the package or destructive file path is not a string or cant convert to absolute path * @throws {FileNotFoundException} If the package or destructive file path not exists or not have access to it * @throws {InvalidFilePathException} If the package or destructive file path is not a file * @throws {WrongFormatException} If file is not a JSON file or not have the correct Metadata JSON format * @throws {WrongDirectoryPathException} If the output Folder 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 */ PackageGenerator.prototype.createBeforeDeployDestructive = function (metadataOrPath, outputFolder) { return createPackageFile(outputFolder, DESTRUCT_BEFORE_FILENAME, this.getPackageContent(metadataOrPath, true)); }; /** * Method to create an after deploy destructive file with the selected Metadata JSON file or Metadata JSON Object * @param {string | { [key: string]: MetadataType }} metadataOrPath Metadata JSON file or Metadata JSON object to create the destructive file * @param {string} outputFolder Folder to save the created file. If not provided use the default options calling options() method * * @returns {string} Returns the path to the created file * * @throws {WrongDatatypeException} If api version is not a string or number. Can't be empty or undefined * @throws {WrongFilePathException} If the package or destructive file path is not a string or cant convert to absolute path * @throws {FileNotFoundException} If the package or destructive file path not exists or not have access to it * @throws {InvalidFilePathException} If the package or destructive file path is not a file * @throws {WrongFormatException} If file is not a JSON file or not have the correct Metadata JSON format * @throws {WrongDirectoryPathException} If the output Folder 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 */ PackageGenerator.prototype.createAfterDeployDestructive = function (metadataOrPath, outputFolder) { return createPackageFile(outputFolder, DESTRUCT_AFTER_FILENAME, this.getPackageContent(metadataOrPath, true)); }; /** * Method to validate a Metadata JSON file or Metadata JSON Object format. If is not valid, throw several exceptions. * @param {string | any} metadataOrPath Metadata JSON file or Metadata JSON object to validate * * @throws {WrongFilePathException} If the filePath is not a string or cant 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 {WrongFormatException} If file is not a JSON file or not have the correct Metadata JSON format * * @returns {{ [key: string]: MetadataType }} Returns the Metadata Object Content validated */ PackageGenerator.validateJSON = function (metadataOrPath) { return metadata_factory_1.MetadataFactory.deserializeMetadataTypes(Validator.validateMetadataJSON(metadataOrPath)); }; return PackageGenerator; }()); exports.PackageGenerator = PackageGenerator; function createPackageFile(outputPath, fileName, content) { outputPath = Validator.validateFolderPath(outputPath, 'Output'); var path = outputPath + '/' + fileName; core_1.FileWriter.createFileSync(path, content); return path; } function makeTypesBlock(metadataType, explicit) { var typesBlockContent = ''; var addBlock = false; if (!metadataType.hasChilds()) { return ''; } typesBlockContent += '\t' + TYPES_TAG_START + NEWLINE; if (!explicit && metadataType.checked && metadataType.allChildsChecked() && !NOT_ALLOWED_WILDCARDS.includes(metadataType.name)) { typesBlockContent += '\t\t' + MEMBERS_TAG_START + '*' + MEMBERS_TAG_END + NEWLINE; addBlock = true; } else { var folderAdded_1 = false; Object.keys(metadataType.childs).forEach(function (key) { var mtObject = metadataType.getChild(key); if (mtObject && mtObject.hasChilds()) { if (!folderAdded_1 && mtObject.checked && (metadataType.name === core_1.MetadataTypes.DOCUMENT || metadataType.name === core_1.MetadataTypes.EMAIL_TEMPLATE || metadataType.name === core_1.MetadataTypes.REPORT || metadataType.name === core_1.MetadataTypes.DASHBOARD)) { typesBlockContent += '\t\t' + MEMBERS_TAG_START + mtObject.name + MEMBERS_TAG_END + NEWLINE; addBlock = true; folderAdded_1 = true; } Object.keys(mtObject.childs).forEach(function (key) { var mtItem = mtObject.getChild(key); if (mtItem) { var separator = void 0; if (metadataType.name === core_1.MetadataTypes.EMAIL_TEMPLATE || metadataType.name === core_1.MetadataTypes.DOCUMENT || metadataType.name === core_1.MetadataTypes.REPORT || metadataType.name === core_1.MetadataTypes.DASHBOARD) { separator = '/'; } else if (metadataType.name === core_1.MetadataTypes.LAYOUT || metadataType.name === core_1.MetadataTypes.CUSTOM_OBJECT_TRANSLATIONS || metadataType.name === core_1.MetadataTypes.FLOW) { separator = '-'; } else { separator = '.'; } if (mtItem.checked) { if (metadataType.name === core_1.MetadataTypes.QUICK_ACTION) { if (mtObject.name === mtItem.name || mtObject.name === 'GlobalActions') { typesBlockContent += '\t\t' + MEMBERS_TAG_START + mtItem.name + MEMBERS_TAG_END + NEWLINE; addBlock = true; } else { typesBlockContent += '\t\t' + MEMBERS_TAG_START + mtObject.name + separator + mtItem.name + MEMBERS_TAG_END + NEWLINE; addBlock = true; } } else { typesBlockContent += '\t\t' + MEMBERS_TAG_START + mtObject.name + separator + mtItem.name + MEMBERS_TAG_END + NEWLINE; addBlock = true; } } } }); } else if (mtObject && mtObject.checked) { typesBlockContent += '\t\t' + MEMBERS_TAG_START + mtObject.name + MEMBERS_TAG_END + NEWLINE; addBlock = true; } }); } typesBlockContent += '\t\t' + NAME_TAG_START + metadataType.name + NAME_TAG_END + NEWLINE; typesBlockContent += '\t' + TYPES_TAG_END + NEWLINE; if (addBlock) { return typesBlockContent; } else { return ''; } } function preparePackageFromXML(pkg, apiVersion) { var result = {}; if (pkg.Package) { result.prepared = true; result.version = apiVersion || pkg.Package.version; var types = XMLUtils.forceArray(pkg.Package.types); for (var _i = 0, types_1 = types; _i < types_1.length; _i++) { var type = types_1[_i]; result[type.name] = []; var members = XMLUtils.forceArray(type.members); for (var _a = 0, members_1 = members; _a < members_1.length; _a++) { var member = members_1[_a]; result[type.name].push(member); } } } return result; } function mergePackageFiles(packages, apiVersion) { var result; var api = 0; for (var _i = 0, packages_1 = packages; _i < packages_1.length; _i++) { var pkg = packages_1[_i]; var xmlRoot = XMLParser.parseXML(core_1.FileReader.readFileSync(pkg)); var preparedPackage = preparePackageFromXML(xmlRoot, apiVersion); if (!result) { result = preparedPackage; } else { result = mergePackage(result, preparedPackage); } if (result.version > api) { api = result.version; } } if (result) { result.version = apiVersion || api; } if (result && Object.keys(result).length === 2) { result = undefined; } return result; } function mergePackage(target, source) { Object.keys(target).forEach(function (key) { if (key !== 'version' && key !== 'prepared') { if (source[key]) { for (var _i = 0, _a = source[key]; _i < _a.length; _i++) { var sourceMember = _a[_i]; if (!target[key].includes(sourceMember)) { target[key].push(sourceMember); } } } target[key] = target[key].sort(); } }); return target; } //# sourceMappingURL=index.js.map