UNPKG

@nxrocks/common-jvm

Version:

Common library to share code among the JVM-related plugins.

373 lines (357 loc) 16.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SPOTLESS_MAVEN_PLUGIN_VERSION = exports.SPOTLESS_MAVEN_PLUGIN_ARTIFACT_ID = exports.SPOTLESS_MAVEN_PLUGIN_GROUP_ID = void 0; exports.hasMavenPlugin = hasMavenPlugin; exports.hasMavenPluginInTree = hasMavenPluginInTree; exports.hasMavenProperty = hasMavenProperty; exports.addMavenPlugin = addMavenPlugin; exports.removeMavenPlugin = removeMavenPlugin; exports.addMavenProperty = addMavenProperty; exports.getMavenSpotlessConfig = getMavenSpotlessConfig; exports.addSpotlessMavenPlugin = addSpotlessMavenPlugin; exports.hasMultiModuleMavenProjectInTree = hasMultiModuleMavenProjectInTree; exports.hasMultiModuleMavenProject = hasMultiModuleMavenProject; exports.hasMavenModuleInTree = hasMavenModuleInTree; exports.hasMavenModule = hasMavenModule; exports.addMavenModule = addMavenModule; exports.initMavenParentModule = initMavenParentModule; exports.getMavenModules = getMavenModules; exports.getMavenWrapperFiles = getMavenWrapperFiles; exports.hasMavenWrapperInTree = hasMavenWrapperInTree; exports.hasMavenWrapper = hasMavenWrapper; exports.getCoordinatesForMavenProjet = getCoordinatesForMavenProjet; const index_1 = require("./index"); const fileutils_1 = require("@nx/workspace/src/utilities/fileutils"); const path_1 = require("path"); const common_1 = require("@nxrocks/common"); exports.SPOTLESS_MAVEN_PLUGIN_GROUP_ID = 'com.diffplug.spotless'; exports.SPOTLESS_MAVEN_PLUGIN_ARTIFACT_ID = 'spotless-maven-plugin'; exports.SPOTLESS_MAVEN_PLUGIN_VERSION = '2.23.0'; function readPomXml(tree, rootFolder) { const pomFile = `./${rootFolder}/pom.xml`; const pomXmlStr = tree.read(pomFile, 'utf-8'); return pomXmlStr !== null ? (0, index_1.readXml)(pomXmlStr) : null; } function hasMavenPlugin(cwd, groupId, artifactId, version) { const pomXmlStr = (0, common_1.getProjectFileContent)({ root: cwd }, `pom.xml`); const pomXml = (0, index_1.readXml)(pomXmlStr); return hasMavenPluginBase(pomXml, groupId, artifactId, version); } function hasMavenPluginInTree(tree, rootFolder, groupId, artifactId, version) { const pomXml = readPomXml(tree, rootFolder); return hasMavenPluginBase(pomXml, groupId, artifactId, version); } function hasMavenPluginBase(pomXml, groupId, artifactId, version) { if (pomXml === null) return false; let pluginXPath = `/project/build/plugins/plugin/groupId/text()[.="${groupId}"]/../../artifactId/text()[.="${artifactId}"]`; if (version) { pluginXPath += `/../../version/text()[.="${version}"]`; } return (0, index_1.hasXmlMatching)(pomXml, pluginXPath); } function hasMavenProperty(tree, rootFolder, property, value) { const pomXml = readPomXml(tree, rootFolder); if (pomXml === null) return false; const propertyXPath = value ? `/project/properties/${property}/text()[.="${value}"]` : `/project/properties/${property}`; return (0, index_1.hasXmlMatching)(pomXml, propertyXPath); } function addMavenPlugin(tree, rootFolder, groupId, artifactId, version, configuration, executions) { const pomXml = readPomXml(tree, rootFolder); if (pomXml === null) return false; if (hasMavenPluginInTree(tree, rootFolder, groupId, artifactId, version)) { return false; // plugin already exists } if (configuration && executions && typeof configuration !== typeof executions) throw new Error('"configuration" and "executions" must be of same type (either object or string)'); const projectNode = (0, index_1.findXmlMatching)(pomXml, '/project'); if (!projectNode) throw new Error('The POM.xml is invalid (no "<project>" node found)'); const buildNode = (0, index_1.findXmlMatching)(pomXml, '/project/build'); if (!buildNode) { // make sure the <build> node exists (0, index_1.addXmlNode)(projectNode, { build: { plugins: {}, }, }); } let pluginsNode = (0, index_1.findXmlMatching)(pomXml, '/project/build/plugins'); if (!pluginsNode) { // make sure the <plugins> node exists if (!buildNode) return false; (0, index_1.addXmlNode)(buildNode, { plugins: {}, }); pluginsNode = (0, index_1.findXmlMatching)(pomXml, '/project/build/plugins'); } const pluginNode = (configuration || executions) && (typeof configuration === 'object' || typeof executions === 'object') ? { plugin: { groupId: groupId, artifactId: artifactId, ...(version && { version: version }), ...(configuration && { configuration: configuration }), ...(executions && { executions: executions }), }, } : `<plugin> <groupId>${groupId}</groupId> <artifactId>${artifactId}</artifactId> ${version ? `<version>${version}</version>` : ''} ${configuration ? `<configuration>${configuration}</configuration>` : ''} ${executions ? `<executions>${executions}</executions>` : ''} </plugin>`; if (pluginsNode) { (0, index_1.addXmlNode)(pluginsNode, pluginNode); tree.write(`${rootFolder}/pom.xml`, pomXml.toString({ prettyPrint: true, indent: '\t' })); return true; } return false; } function removeMavenPlugin(tree, rootFolder, groupId, artifactId) { const pomXml = readPomXml(tree, rootFolder); if (pomXml === null) return false; const pluginNode = (0, index_1.findXmlMatching)(pomXml, `/project/build/plugins/plugin/groupId/text()[.="${groupId}"]/../../artifactId/text()[.="${artifactId}"]`) ?.up() ?.up(); if (pluginNode) { const pluginsNode = (0, index_1.removeXmlNode)(pluginNode); //if parent 'plugins' node is now empty, remove it if ((0, index_1.isXmlNodeEmpty)(pluginsNode)) { const buildNode = (0, index_1.removeXmlNode)(pluginsNode); //if parent 'build' node is now empty, remove it if ((0, index_1.isXmlNodeEmpty)(buildNode)) { (0, index_1.removeXmlNode)(buildNode); } } tree.write(`${rootFolder}/pom.xml`, pomXml.toString({ prettyPrint: true, indent: '\t' })); return true; } return false; } function addMavenProperty(tree, rootFolder, property, value) { const pomXml = readPomXml(tree, rootFolder); if (pomXml === null) return false; if (hasMavenProperty(tree, rootFolder, property, value)) { return false; // property already exists } const projectNode = (0, index_1.findXmlMatching)(pomXml, '/project'); if (!projectNode) throw new Error('The POM.xml is invalid (no "<project>" node found)'); let propertiesNode = (0, index_1.findXmlMatching)(pomXml, '/project/properties'); if (!propertiesNode) { // make sure the <properties> node exists (0, index_1.addXmlNode)(projectNode, { properties: {}, }); propertiesNode = (0, index_1.findXmlMatching)(pomXml, '/project/properties'); } const propertyNode = `<${property}>${value}</${property}>`; if (propertiesNode) { (0, index_1.addXmlNode)(propertiesNode, propertyNode); tree.write(`${rootFolder}/pom.xml`, pomXml.toString({ prettyPrint: true, indent: '\t' })); return true; } return false; } function getMavenSpotlessBaseConfig(languageConfig, baseGitBranch) { const ratchetFrom = baseGitBranch ? (0, common_1.stripIndent) ` <!-- optional: limit format enforcement to just the files changed by this feature branch --> <ratchetFrom>${baseGitBranch}</ratchetFrom> ` : ''; return (0, common_1.stripIndent) ` ${ratchetFrom} <formats> <!-- you can define as many formats as you want, each is independent --> <format> <!-- define the files to apply to --> <includes> <include>*.md</include> <include>.gitignore</include> </includes> <!-- define the steps to apply to those files --> <trimTrailingWhitespace/> <endWithNewline/> <indent> <tabs>true</tabs> <spacesPerTab>4</spacesPerTab> </indent> </format> </formats> ${languageConfig}`; } function getMavenSpotlessConfig(language, jdkVersion, baseGitBranch) { switch (language) { case 'java': return getMavenSpotlessBaseConfig((0, common_1.stripIndent) ` <java> <!-- to customize, go to https://github.com/diffplug/spotless/tree/main/plugin-maven#java --> <!-- Use the default importOrder configuration --> <importOrder/> <!-- Clean up --> <removeUnusedImports/> <!-- Apply google-java-format formatter --> <googleJavaFormat/> </java`, baseGitBranch); case 'kotlin': return getMavenSpotlessBaseConfig((0, common_1.stripIndent) ` <kotlin> <!-- to customize, go to https://github.com/diffplug/spotless/tree/main/plugin-maven#kotlin --> <!-- Use the default importOrder configuration --> <importOrder/> <!-- Clean up --> <removeUnusedImports/> <!-- Apply ${jdkVersion && jdkVersion >= 11 ? 'ktfmt formatter(similar to google-java-format, but for Kotlin)' : 'ktlint formatter'} --> ${jdkVersion && jdkVersion >= 11 ? '<ktfmt/>' : '<ktlint/>'} </kotlin>`, baseGitBranch); case 'groovy': return getMavenSpotlessBaseConfig((0, common_1.stripIndent) ` <groovy> <!-- to customize, go to https://github.com/diffplug/spotless/tree/main/plugin-maven#groovy --> <!-- Use the default importOrder configuration --> <importOrder/> <!-- Clean up --> <removeUnusedImports/> <!-- Apply groovy-eclipse formatter --> <greclipse/> </groovy>`, baseGitBranch); } } function addSpotlessMavenPlugin(tree, rootFolder, language, jdkVersion, gitBaseBranch) { const spotlessConfig = getMavenSpotlessConfig(language, jdkVersion, gitBaseBranch); return addMavenPlugin(tree, rootFolder, exports.SPOTLESS_MAVEN_PLUGIN_GROUP_ID, exports.SPOTLESS_MAVEN_PLUGIN_ARTIFACT_ID, exports.SPOTLESS_MAVEN_PLUGIN_VERSION, spotlessConfig); } function hasMultiModuleMavenProjectInTree(tree, rootFolder) { if (!(0, index_1.isMavenProjectInTree)(tree, rootFolder)) return false; const pomXml = readPomXml(tree, rootFolder); if (pomXml === null) return false; const modulesXpath = `/project/modules`; return (0, index_1.hasXmlMatching)(pomXml, modulesXpath); } function hasMultiModuleMavenProject(cwd) { if (!(0, index_1.hasMavenProject)(cwd)) return false; const pomXmlStr = (0, common_1.getProjectFileContent)({ root: cwd }, `pom.xml`); const pomXml = (0, index_1.readXml)(pomXmlStr); const modulesXpath = `/project/modules`; return (0, index_1.hasXmlMatching)(pomXml, modulesXpath); } function hasMavenModuleInTree(tree, rootFolder, moduleName) { if (!hasMultiModuleMavenProjectInTree(tree, rootFolder)) return false; const pomXml = readPomXml(tree, rootFolder); if (pomXml === null) return false; const modulesXpath = `/project/modules/module/text()[.="${moduleName}"]`; return (0, index_1.hasXmlMatching)(pomXml, modulesXpath); } function hasMavenModule(cwd, moduleName) { if (!hasMultiModuleMavenProject(cwd)) return false; const pomXmlStr = (0, common_1.getProjectFileContent)({ root: cwd }, `pom.xml`); const pomXml = (0, index_1.readXml)(pomXmlStr); const modulesXpath = `/project/modules/module/text()[.="${moduleName}"]`; return (0, index_1.hasXmlMatching)(pomXml, modulesXpath); } function addMavenModule(tree, rootFolder, moduleName) { if (hasMavenModuleInTree(tree, rootFolder, moduleName)) return false; const pomXml = readPomXml(tree, rootFolder); if (pomXml === null) return false; const modulesNode = (0, index_1.findXmlMatching)(pomXml, `/project/modules`); if (modulesNode) { (0, index_1.addXmlNode)(modulesNode, { module: moduleName, }); tree.write(`${rootFolder}/pom.xml`, pomXml.toString({ prettyPrint: true, indent: '\t' })); return true; } return false; } function initMavenParentModule(tree, rootFolder, groupId, parentModuleName, childModuleName, helpComment = '', version = 'O.0.1-SNAPSHOT') { const parentPomXml = `<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> ${helpComment} <groupId>${groupId}</groupId> <artifactId>${parentModuleName}</artifactId> <version>${version}</version> <packaging>pom</packaging> <modules> <module>${childModuleName}</module> </modules> </project> `; tree.write(`./${rootFolder}/pom.xml`, parentPomXml); } function getMavenModules(cwd) { if (!hasMultiModuleMavenProject(cwd)) return []; const pomXmlStr = (0, common_1.getProjectFileContent)({ root: cwd }, `pom.xml`); const pomXml = (0, index_1.readXml)(pomXmlStr); const modulesXpath = `/project/modules/module/text()`; return (0, index_1.findXmlContents)(pomXml, modulesXpath); } function getMavenWrapperFiles() { return [ 'mvnw', 'mvnw.bat', 'mvnw.cmd', '.mvn/wrapper/maven-wrapper.properties', '.mvn/wrapper/MavenWrapperDownloader.class', '.mvn/wrapper/MavenWrapperDownloader.java', '.mvn/wrapper/maven-wrapper.jar', ]; } function hasMavenWrapperInTree(tree, rootFolder) { return hasMavenWrapperWithPredicate((file) => tree.exists(`./${rootFolder}/${file}`)); } function hasMavenWrapper(rootFolder) { return hasMavenWrapperWithPredicate((file) => (0, fileutils_1.fileExists)((0, path_1.resolve)(rootFolder, file))); } function getCoordinatesForMavenProjet(cwd) { const pomXmlStr = (0, common_1.getProjectFileContent)({ root: cwd }, 'pom.xml'); const pomXmlNode = (0, index_1.readXml)(pomXmlStr); let groupId = (0, index_1.findXmlContent)(pomXmlNode, `/project/groupId/text()`); const artifactId = (0, index_1.findXmlContent)(pomXmlNode, `/project/artifactId/text()`); if (!groupId && artifactId) { // groupId might be defined at parent module level, continue searching for it groupId = getGroupIdInHierarchy(cwd); } return { groupId, artifactId }; } function getGroupIdInHierarchy(cwd) { const { root, name } = (0, common_1.getNameAndRoot)(cwd); if (root === '.') // we reach the root of the workspace without finding the groupId, so we stop the search return undefined; if (!hasMavenModule(root, name)) return undefined; const pomXmlStr = (0, common_1.getProjectFileContent)({ root }, 'pom.xml'); const pomXmlNode = (0, index_1.readXml)(pomXmlStr); const groupId = (0, index_1.findXmlContent)(pomXmlNode, `/project/groupId/text()`); return groupId ?? getGroupIdInHierarchy(root); } function hasMavenWrapperWithPredicate(predicate) { return (['mvnw', '.mvn/wrapper/maven-wrapper.properties'].every((file) => predicate(file)) && ['mvnw.bat', 'mvnw.cmd'].some((file) => predicate(file))); } //# sourceMappingURL=maven-utils.js.map