From 1ff2c79e02d7268e61631b9914e4cb28df2a13b5 Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Sun, 21 Jan 2024 09:14:33 +0000 Subject: [PATCH 01/12] feat(common-jvm): improve retrieval of `groupId`and `artifactId` when defined at parent level --- .../common-jvm/src/lib/utils/gradle-utils.ts | 152 +++++++++++------- .../common-jvm/src/lib/utils/maven-utils.ts | 74 ++++++--- packages/common-jvm/src/lib/utils/utils.ts | 20 +-- packages/common/src/lib/workspace/utils.ts | 11 +- 4 files changed, 165 insertions(+), 92 deletions(-) diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.ts b/packages/common-jvm/src/lib/utils/gradle-utils.ts index 7ff09b42..07df0ad3 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.ts @@ -1,8 +1,8 @@ -import { Tree } from '@nx/devkit'; -import { checkProjectFileContains, getGradleBuildFilesExtension, getGradleBuildFilesExtensionInTree, hasGradleSettingsFile, isGradleProjectSettingsInTree as hasGradleProjectSettingsInTree } from './utils'; +import { Tree, workspaceRoot } from '@nx/devkit'; +import { checkProjectFileContains, getGradleBuildFilesExtension, getGradleBuildFilesExtensionInTree, hasGradleSettingsFile, isGradleProjectSettingsInTree as hasGradleProjectSettingsInTree, hasGradleBuildFile } from './utils'; import { fileExists } from '@nx/workspace/src/utilities/fileutils'; import { resolve } from 'path'; -import { getProjectFileContent } from '@nxrocks/common'; +import { getCurrentAndParentFolder, getProjectFileContent } from '@nxrocks/common'; export const GRADLE_PLUGINS_REGEX = /(?:plugins\s*\{\s*)([^}]+)(?:\s*\})/g; export const SPOTLESS_CONFIG_REGEX = @@ -70,7 +70,7 @@ export function disableGradlePlugin( const ext = withKotlinDSL ? '.gradle.kts' : '.gradle'; const buildGradle = tree.read(`${rootFolder}/build${ext}`, 'utf-8'); - if(buildGradle === null) + if (buildGradle === null) return false; const plugin = getGradlePlugin(buildGradle, pluginId); if (plugin && plugin.applied) { @@ -81,8 +81,8 @@ export function disableGradlePlugin( GRADLE_PLUGIN_REGEX, (pluginMatch: string, _: string, id: string) => { if (id === pluginId) { - const lastQuoteIdx = pluginMatch.lastIndexOf( withKotlinDSL ? '"': "'"); - const disabledPlugin = `${pluginMatch.substring(0, lastQuoteIdx+1)} apply false${pluginMatch.substring(lastQuoteIdx+1)}`; + const lastQuoteIdx = pluginMatch.lastIndexOf(withKotlinDSL ? '"' : "'"); + const disabledPlugin = `${pluginMatch.substring(0, lastQuoteIdx + 1)} apply false${pluginMatch.substring(lastQuoteIdx + 1)}`; return disabledPlugin; } return pluginMatch; @@ -108,7 +108,7 @@ export function addGradlePlugin( ) { const ext = withKotlinDSL ? '.gradle.kts' : '.gradle'; const buildGradle = tree.read(`${rootFolder}/build${ext}`, 'utf-8'); - if(buildGradle === null) + if (buildGradle === null) return false; let withVersion = ''; @@ -154,19 +154,17 @@ function getGradleSpotlessBaseConfig( : ''; return ` -${ - withKotlinDSL - ? 'configure' - : 'spotless' -} { +${withKotlinDSL + ? 'configure' + : 'spotless' + } { ${ratchetFrom} format${withKotlinDSL ? '("misc")' : " 'misc',"} { // define the files to apply 'misc' to - target${ - withKotlinDSL - ? '("*.gradle.kts", "*.md", ".gitignore")' - : " '*.gradle', '*.md', '.gitignore'" - } + target${withKotlinDSL + ? '("*.gradle.kts", "*.md", ".gitignore")' + : " '*.gradle', '*.md', '.gitignore'" + } // define the steps to apply to those files trimTrailingWhitespace() @@ -191,8 +189,7 @@ export function getGradleSpotlessConfig( ` java {// to customize, go to https://github.com/diffplug/spotless/tree/main/plugin-gradle#java - target${ - withKotlinDSL ? '("src/*/java/**/*.java")' : " 'src/*/java/**/*.java'" + target${withKotlinDSL ? '("src/*/java/**/*.java")' : " 'src/*/java/**/*.java'" } // Use the default importOrder configuration @@ -213,16 +210,14 @@ export function getGradleSpotlessConfig( ` kotlin { // to customize, go to https://github.com/diffplug/spotless/tree/main/plugin-gradle#kotlin - ${ - jdkVersion && jdkVersion >= 11 - ? '// Apply ktfmt formatter(similar to google-java-format, but for Kotlin)' - : '// Apply ktlint formatter' + ${jdkVersion && jdkVersion >= 11 + ? '// Apply ktfmt formatter(similar to google-java-format, but for Kotlin)' + : '// Apply ktlint formatter' } ${jdkVersion && jdkVersion >= 11 ? 'ktfmt()' : 'ktlint()'} } kotlinGradle { - target${ - withKotlinDSL ? '("*.gradle.kts")' : " '*.gradle.kts'" + target${withKotlinDSL ? '("*.gradle.kts")' : " '*.gradle.kts'" } // default target for kotlinGradle ${jdkVersion && jdkVersion >= 11 ? 'ktfmt()' : 'ktlint()'} }`, @@ -245,8 +240,7 @@ export function getGradleSpotlessConfig( greclipse() } groovyGradle { - target${ - withKotlinDSL ? '("*.gradle")' : " '*.gradle'" + target${withKotlinDSL ? '("*.gradle")' : " '*.gradle'" } // default target of groovyGradle greclipse() }`, @@ -267,7 +261,7 @@ export function applySpotlessGradlePlugin( const ext = withKotlinDSL ? '.gradle.kts' : '.gradle'; const buildGradle = tree.read(`${rootFolder}/build${ext}`, 'utf-8'); - if(buildGradle === null) + if (buildGradle === null) return false; if (!SPOTLESS_CONFIG_REGEX.test(buildGradle)) { @@ -315,95 +309,95 @@ export function addSpotlessGradlePlugin( return added; } -export function hasMultiModuleGradleProjectInTree(tree: Tree, rootFolder: string){ +export function hasMultiModuleGradleProjectInTree(tree: Tree, rootFolder: string) { if (!hasGradleProjectSettingsInTree(tree, rootFolder)) return false; const extension = getGradleBuildFilesExtensionInTree(tree, rootFolder); const settings = tree.read(`./${rootFolder}/settings${extension}`, 'utf-8'); - if(settings === null) + if (settings === null) return false; return checkForMultiModuleProject(settings); } -export function hasMultiModuleGradleProject(cwd: string){ +export function hasMultiModuleGradleProject(cwd: string) { if (!hasGradleSettingsFile(cwd)) return false; - const extension = getGradleBuildFilesExtension({root: cwd}); - const settings = getProjectFileContent({root: cwd}, `settings${extension}`); + const extension = getGradleBuildFilesExtension({ root: cwd }); + const settings = getProjectFileContent({ root: cwd }, `settings${extension}`); return checkForMultiModuleProject(settings); } -function checkForMultiModuleProject(settings: string){ +function checkForMultiModuleProject(settings: string) { const opts = { fragments: [/rootProject\.name\s*=\s*'/, /include\s+'/], - logicalOp: 'and' as 'and' | 'or' + logicalOp: 'and' as const }; const optsKts = { fragments: [/rootProject\.name\s*=\s*"/, /include\("/], - logicalOp: 'and' as 'and' | 'or' + logicalOp: 'and' as const }; return checkProjectFileContains(settings, opts) || checkProjectFileContains(settings, optsKts); } -export function hasGradleModuleInTree(tree: Tree, rootFolder:string, moduleName: string){ +export function hasGradleModuleInTree(tree: Tree, rootFolder: string, moduleName: string) { if (!hasMultiModuleGradleProjectInTree(tree, rootFolder)) return false; const ext = getGradleBuildFilesExtensionInTree(tree, rootFolder); const settings = tree.read(`./${rootFolder}/settings${ext}`, 'utf-8'); - if(settings === null) + if (settings === null) return false; return checkForModule(settings, moduleName) } -export function hasGradleModule(cwd:string, moduleName: string){ +export function hasGradleModule(cwd: string, moduleName: string) { if (!hasMultiModuleGradleProject(cwd)) return false; - const extension = getGradleBuildFilesExtension({root: cwd}); - const settings = getProjectFileContent({root: cwd}, `settings${extension}`); + const extension = getGradleBuildFilesExtension({ root: cwd }); + const settings = getProjectFileContent({ root: cwd }, `settings${extension}`); return checkForModule(settings, moduleName) } -function checkForModule(settings:string, moduleName:string){ +function checkForModule(settings: string, moduleName: string) { const opts = { fragments: [new RegExp(`rootProject\\.name\\s*=\\s*'`), new RegExp(`include\\s+':?(?:[^:]*:)*${moduleName}'`)], - logicalOp: 'and' as 'and' | 'or' + logicalOp: 'and' as const }; const optsKts = { fragments: [new RegExp(`rootProject\\.name\\s*=\\s*"`), new RegExp(`include\\(":?(?:[^:]*:)*${moduleName}"\\)`)], - logicalOp: 'and' as 'and' | 'or' + logicalOp: 'and' as const }; return checkProjectFileContains(settings, opts) || checkProjectFileContains(settings, optsKts); } -export function getGradleModules(cwd:string): string[]{ +export function getGradleModules(cwd: string): string[] { if (!hasMultiModuleGradleProject(cwd)) return []; - const extension = getGradleBuildFilesExtension({root: cwd}); - const settings = getProjectFileContent({root: cwd}, `settings${extension}`); + const extension = getGradleBuildFilesExtension({ root: cwd }); + const settings = getProjectFileContent({ root: cwd }, `settings${extension}`); const modulesRegex = extension === '.gradle.kts' ? /include\(":?(\w+)"\)/g : /include\s+':?(\w+)'/g; const modules = []; let m; - while ( (m=modulesRegex.exec(settings))){ + while ((m = modulesRegex.exec(settings))) { modules.push(m?.[1]) } return modules; @@ -416,30 +410,30 @@ export function addGradleModule( withKotlinDSL: boolean ) { - if(hasGradleModuleInTree(tree, rootFolder, moduleName)) + if (hasGradleModuleInTree(tree, rootFolder, moduleName)) return false; const ext = withKotlinDSL ? '.gradle.kts' : '.gradle'; const settingsGradle = tree.read(`${rootFolder}/settings${ext}`, 'utf-8'); - if(settingsGradle === null) + if (settingsGradle === null) return false; - + let lastIncludeIdx = settingsGradle.lastIndexOf('include'); lastIncludeIdx = lastIncludeIdx > 0 ? lastIncludeIdx : settingsGradle.length; - const newModule = withKotlinDSL ? `\ninclude("${moduleName}")\n`: `\ninclude '${moduleName}'\n`; + const newModule = withKotlinDSL ? `\ninclude("${moduleName}")\n` : `\ninclude '${moduleName}'\n`; - const newSettingGradle = settingsGradle.slice(0, lastIncludeIdx) + newModule + settingsGradle.slice(lastIncludeIdx); + const newSettingGradle = settingsGradle.slice(0, lastIncludeIdx) + newModule + settingsGradle.slice(lastIncludeIdx); tree.write(`${rootFolder}/settings${ext}`, newSettingGradle) return true } -export function initGradleParentModule(tree: Tree, rootFolder: string, parentModuleName: string, childModuleName: string, withKotlinDSL:boolean, helpComment=''){ +export function initGradleParentModule(tree: Tree, rootFolder: string, parentModuleName: string, childModuleName: string, withKotlinDSL: boolean, helpComment = '') { const settingsGradle = ` ${helpComment} -rootProject.name = ${withKotlinDSL? `"${parentModuleName}"` : `'${parentModuleName}'`} +rootProject.name = ${withKotlinDSL ? `"${parentModuleName}"` : `'${parentModuleName}'`} -${withKotlinDSL? `include("${childModuleName}")` : `include '${childModuleName}'`} +${withKotlinDSL ? `include("${childModuleName}")` : `include '${childModuleName}'`} `; tree.write(`./${rootFolder}/settings.gradle${withKotlinDSL ? '.kts' : ''}`, settingsGradle); @@ -463,6 +457,50 @@ export function hasGradleWrapper(rootFolder: string) { return hasGradleWrapperWithPredicate((file: string) => fileExists(resolve(rootFolder, file))); } +export function getCoordinatesForGradleProjet(cwd: string): { groupId?: string | null, artifactId?: string | null } { + + let groupId; + let artifactId; + + const ext = getGradleBuildFilesExtension({ root: cwd }); + const { currentFolder: name } = getCurrentAndParentFolder(cwd); + + if (hasGradleSettingsFile(cwd)) { + const settingsGradle = getProjectFileContent({ root: cwd }, `settings${ext}`); + artifactId = settingsGradle.match(/rootProject\.name\s*=\s*['"]([^"']+)['"]/)?.[1]; + } + artifactId = artifactId ?? name; // use the folder name as default if stil undefined + + + if (hasGradleBuildFile(cwd)) { + const buildGradle = getProjectFileContent({ root: cwd }, `build${ext}`); + groupId = buildGradle.match(/group\s*=\s*['"]([^"']+)['"]/)?.[1]; + } + + if (!groupId && ext && artifactId) { + // groupId might be defined at parent module level, continue searching for it + groupId = getGroupIdInHierarchy(cwd, ext); + } + + return { groupId, artifactId }; +} + +function getGroupIdInHierarchy(cwd: string, buildFileExtension: string): string | undefined { + + if (cwd === workspaceRoot) + return undefined; + + const { parentFolder: root, currentFolder: name } = getCurrentAndParentFolder(cwd); + + let groupId; + if (hasGradleBuildFile(root) && hasGradleModule(root, name)) { + const buildGradle = getProjectFileContent({ root: cwd }, `build${buildFileExtension}`); + groupId = buildGradle.match(/group\s*=\s*['"]([^"']+)['"]/)?.[1]; + } + + return groupId ?? getGroupIdInHierarchy(root, buildFileExtension); +} + function hasGradleWrapperWithPredicate(predicate: (file: string) => boolean) { return [ 'gradlew', @@ -472,5 +510,5 @@ function hasGradleWrapperWithPredicate(predicate: (file: string) => boolean) { [ 'gradlew.bat', 'gradlew.cmd', - ].some(file => predicate(file)) ;; + ].some(file => predicate(file));; } diff --git a/packages/common-jvm/src/lib/utils/maven-utils.ts b/packages/common-jvm/src/lib/utils/maven-utils.ts index f1c08d0a..e708d487 100644 --- a/packages/common-jvm/src/lib/utils/maven-utils.ts +++ b/packages/common-jvm/src/lib/utils/maven-utils.ts @@ -1,6 +1,7 @@ -import { Tree } from '@nx/devkit'; +import { Tree, workspaceRoot } from '@nx/devkit'; import { addXmlNode, + findXmlContent, findXmlContents, findXmlMatching, hasMavenProject, @@ -12,18 +13,18 @@ import { } from './index'; import { fileExists } from '@nx/workspace/src/utilities/fileutils'; import { resolve } from 'path'; -import { stripIndent, getProjectFileContent } from '@nxrocks/common'; +import { stripIndent, getProjectFileContent, getCurrentAndParentFolder } from '@nxrocks/common'; import { XMLBuilder } from 'xmlbuilder2/lib/interfaces'; export const SPOTLESS_MAVEN_PLUGIN_GROUP_ID = 'com.diffplug.spotless'; export const SPOTLESS_MAVEN_PLUGIN_ARTIFACT_ID = 'spotless-maven-plugin'; export const SPOTLESS_MAVEN_PLUGIN_VERSION = '2.23.0'; -function readPomXml(tree: Tree, rootFolder:string): XMLBuilder | null{ +function readPomXml(tree: Tree, rootFolder: string): XMLBuilder | null { const pomFile = `./${rootFolder}/pom.xml`; const pomXmlStr = tree.read(pomFile, 'utf-8'); - return pomXmlStr !== null ? readXml(pomXmlStr): null; + return pomXmlStr !== null ? readXml(pomXmlStr) : null; } export function hasMavenPlugin( @@ -36,7 +37,7 @@ export function hasMavenPlugin( const pomXml = readPomXml(tree, rootFolder); - if(pomXml === null) + if (pomXml === null) return false; let pluginXPath = `/project/build/plugins/plugin/groupId/text()[.="${groupId}"]/../../artifactId/text()[.="${artifactId}"]`; @@ -55,7 +56,7 @@ export function hasMavenProperty( ): boolean { const pomXml = readPomXml(tree, rootFolder); - if(pomXml === null) + if (pomXml === null) return false; const propertyXPath = value @@ -76,7 +77,7 @@ export function addMavenPlugin( ): boolean { const pomXml = readPomXml(tree, rootFolder); - if(pomXml === null) + if (pomXml === null) return false; if (hasMavenPlugin(tree, rootFolder, groupId, artifactId, version)) { @@ -105,9 +106,9 @@ export function addMavenPlugin( let pluginsNode = findXmlMatching(pomXml, '/project/build/plugins'); if (!pluginsNode) { // make sure the node exists - if(!buildNode) + if (!buildNode) return false; - + addXmlNode(buildNode, { plugins: {}, }); @@ -137,7 +138,7 @@ export function addMavenPlugin( ${executions ? `${executions}` : ''} `; - if(pluginsNode){ + if (pluginsNode) { addXmlNode(pluginsNode, pluginNode); tree.write( `${rootFolder}/pom.xml`, @@ -156,7 +157,7 @@ export function removeMavenPlugin( ): boolean { const pomXml = readPomXml(tree, rootFolder); - if(pomXml === null) + if (pomXml === null) return false; const pluginNode = findXmlMatching( @@ -196,7 +197,7 @@ export function addMavenProperty( ): boolean { const pomXml = readPomXml(tree, rootFolder); - if(pomXml === null) + if (pomXml === null) return false; if (hasMavenProperty(tree, rootFolder, property, value)) { @@ -218,7 +219,7 @@ export function addMavenProperty( const propertyNode = `<${property}>${value}`; - if(propertiesNode){ + if (propertiesNode) { addXmlNode(propertiesNode, propertyNode); tree.write( `${rootFolder}/pom.xml`, @@ -358,7 +359,7 @@ export function hasMultiModuleMavenProjectInTree(tree: Tree, rootFolder: string) const pomXml = readPomXml(tree, rootFolder); - if(pomXml === null) + if (pomXml === null) return false; const modulesXpath = `/project/modules`; @@ -386,7 +387,7 @@ export function hasMavenModuleInTree(tree: Tree, rootFolder: string, moduleName: const pomXml = readPomXml(tree, rootFolder); - if(pomXml === null) + if (pomXml === null) return false; const modulesXpath = `/project/modules/module/text()[.="${moduleName}"]`; @@ -418,12 +419,12 @@ export function addMavenModule( const pomXml = readPomXml(tree, rootFolder); - if(pomXml === null) + if (pomXml === null) return false; const modulesNode = findXmlMatching(pomXml, `/project/modules`);; - if(modulesNode){ + if (modulesNode) { addXmlNode(modulesNode, { module: moduleName }); @@ -439,8 +440,8 @@ export function addMavenModule( export function initMavenParentModule(tree: Tree, rootFolder: string, groupId: string, parentModuleName: string, childModuleName: string, helpComment = '', version = 'O.0.1-SNAPSHOT') { - const parentPomXml = -` + const parentPomXml = + ` 4.0.0 @@ -495,6 +496,41 @@ export function hasMavenWrapper(rootFolder: string) { return hasMavenWrapperWithPredicate((file: string) => fileExists(resolve(rootFolder, file))); } +export function getCoordinatesForMavenProjet(cwd: string): { groupId?: string | null, artifactId?: string | null } { + + const pomXmlStr = getProjectFileContent({ root: cwd }, 'pom.xml'); + const pomXmlNode = readXml(pomXmlStr); + + let groupId = findXmlContent(pomXmlNode, `/project/groupId/text()`); + const artifactId = 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: string): string | undefined { + + if (cwd === workspaceRoot) + return undefined; + + const { parentFolder: root, currentFolder: name } = getCurrentAndParentFolder(cwd); + + if (!hasMavenModule(root, name)) + return undefined; + + const pomXmlStr = getProjectFileContent({ root }, 'pom.xml'); + const pomXmlNode = readXml(pomXmlStr); + + const groupId = findXmlContent(pomXmlNode, `/project/groupId/text()`); + + return groupId ?? getGroupIdInHierarchy(root); +} + function hasMavenWrapperWithPredicate(predicate: (file: string) => boolean) { return [ 'mvnw', diff --git a/packages/common-jvm/src/lib/utils/utils.ts b/packages/common-jvm/src/lib/utils/utils.ts index 4b17b9a9..75d6f066 100644 --- a/packages/common-jvm/src/lib/utils/utils.ts +++ b/packages/common-jvm/src/lib/utils/utils.ts @@ -10,13 +10,12 @@ import { PackageInfo, } from '@nxrocks/common'; import { - findXmlContent, readXml, findXmlNodes, findNodeContent, } from '../utils'; -import { getMavenModules } from './maven-utils'; -import { getGradleModules } from './gradle-utils'; +import { getCoordinatesForMavenProjet, getMavenModules } from './maven-utils'; +import { getCoordinatesForGradleProjet, getGradleModules } from './gradle-utils'; export const LARGE_BUFFER = 1024 * 1000000; @@ -121,8 +120,8 @@ export function getJvmPackageInfo(project: {root:string}): PackageInfo { const pomXmlStr = getProjectFileContent(project, 'pom.xml'); const pomXmlNode = readXml(pomXmlStr); - const groupId = findXmlContent(pomXmlNode, `/project/groupId/text()`); - const artifactId = findXmlContent(pomXmlNode, `/project/artifactId/text()`); + const {groupId, artifactId} = getCoordinatesForMavenProjet(project.root); + const dependencies: PackageInfo[] = []; const dependencyNodes = findXmlNodes( @@ -153,13 +152,7 @@ export function getJvmPackageInfo(project: {root:string}): PackageInfo { if (isGradleProject(project)) { // gradle project const ext = getGradleBuildFilesExtension(project); - - const settingsGradle = getProjectFileContent(project, `settings${ext}`); - - let groupId; - const artifactId = settingsGradle.match( - /rootProject\.name\s*=\s*['"]([^"']+)['"]/ - )?.[1]; + const {groupId, artifactId} = getCoordinatesForGradleProjet(project.root); const gradleDependencyIdRegEx = getGradleDependencyIdRegEx(); const dependencyIds: string[] = []; @@ -167,8 +160,6 @@ export function getJvmPackageInfo(project: {root:string}): PackageInfo { if(hasGradleBuildFile(project.root)){ const buildGradle = getProjectFileContent(project, `build${ext}`); - groupId = buildGradle.match(/group\s*=\s*['"]([^"']+)['"]/)?.[1] ?? 'not-available'; - let match: RegExpExecArray|null; do { match = gradleDependencyIdRegEx.exec(buildGradle); @@ -233,6 +224,7 @@ export function checkProjectFileContains( return findOccurencesInContent(content); } + function match(content: string, value: string | RegExp) { if( typeof value === 'string'){ return content.includes(value); diff --git a/packages/common/src/lib/workspace/utils.ts b/packages/common/src/lib/workspace/utils.ts index ecc722f7..3b1840af 100644 --- a/packages/common/src/lib/workspace/utils.ts +++ b/packages/common/src/lib/workspace/utils.ts @@ -1,4 +1,4 @@ -import { dirname, join, resolve } from 'path'; +import { basename, dirname, join, resolve } from 'path'; import { workspaceRoot } from '@nx/devkit'; import { readFileSync } from 'fs'; @@ -22,7 +22,6 @@ export function getProjectFileContent( return readFileSync(filePath, 'utf8'); } - export function getNameAndRoot(file: string) { const root = dirname(file); @@ -31,4 +30,12 @@ export function getNameAndRoot(file: string) { const name = parts[parts.length - 1].toLowerCase(); return { root, name }; +} + + +export function getCurrentAndParentFolder(cwd: string) { + const currentFolder = basename(resolve(cwd)); + const parentFolder = dirname(cwd); + + return { currentFolder, parentFolder }; } \ No newline at end of file From aaeeb9c1c7e5f2fed7b887594ba5847c71938263 Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Mon, 22 Jan 2024 05:17:31 +0000 Subject: [PATCH 02/12] fix(common): fix creation of dependencies between nodes for ProjectGraph v2 --- packages/common/src/lib/workspace/project-graph.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/common/src/lib/workspace/project-graph.ts b/packages/common/src/lib/workspace/project-graph.ts index e639ca8d..8be14df2 100644 --- a/packages/common/src/lib/workspace/project-graph.ts +++ b/packages/common/src/lib/workspace/project-graph.ts @@ -145,11 +145,11 @@ export function getProjectGraph( return builder.getUpdatedProjectGraph(); } -//Project Graph V2 +// Project Graph V2 -export const createNodesFor = (projectFilePattern: string[], pluginName: string) => +export const createNodesFor = (projectFiles: string[], pluginName: string) => [ - `**/{${projectFilePattern.join(',')}}` as string, + `**/{${projectFiles.join(',')}}` as string, ( file: string, opt: unknown, @@ -172,7 +172,7 @@ export const createNodesFor = (projectFilePattern: string[], pluginName: string) export const createDependenciesIf = (pluginName: string, - projectFilePattern: string[], + projectFiles: string[], projectFilter: (project: { root: string }) => boolean, getPackageInfo: (project: { root: string }) => PackageInfo, ctx: CreateDependenciesContext) => { @@ -190,10 +190,11 @@ export const createDependenciesIf = (pluginName: string, let dependencies: RawProjectGraphDependency[] = []; + const projectFilePattern = `**/{${projectFiles.join(',')}}`; for (const source in ctx.filesToProcess.projectFileMap) { const changed = ctx.filesToProcess.projectFileMap[source]; for (const file of changed) { - if (projectFilePattern.some(p => minimatch(file.file, p))) { + if (minimatch(file.file, projectFilePattern)) { const { root, name } = getNameAndRoot(file.file); dependencies = dependencies.concat( From 0fe9a65739a209e0ed310734600255a98d4538d5 Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Mon, 22 Jan 2024 05:49:01 +0000 Subject: [PATCH 03/12] fix(common-jvm): include `settings.gradle[.kts]` files when creating nodes for ProjectGraph v2 --- packages/common-jvm/src/lib/utils/gradle-utils.ts | 4 ++-- packages/common-jvm/src/lib/utils/utils.ts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.ts b/packages/common-jvm/src/lib/utils/gradle-utils.ts index 07df0ad3..71871547 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.ts @@ -340,12 +340,12 @@ function checkForMultiModuleProject(settings: string) { }; const optsKts = { - fragments: [/rootProject\.name\s*=\s*"/, /include\("/], + fragments: [/rootProject\.name\s*=\s*"/, /include\s*\("/], logicalOp: 'and' as const }; return checkProjectFileContains(settings, opts) || checkProjectFileContains(settings, optsKts); -} + } export function hasGradleModuleInTree(tree: Tree, rootFolder: string, moduleName: string) { diff --git a/packages/common-jvm/src/lib/utils/utils.ts b/packages/common-jvm/src/lib/utils/utils.ts index 75d6f066..f0a2c7a1 100644 --- a/packages/common-jvm/src/lib/utils/utils.ts +++ b/packages/common-jvm/src/lib/utils/utils.ts @@ -19,7 +19,7 @@ import { getCoordinatesForGradleProjet, getGradleModules } from './gradle-utils' export const LARGE_BUFFER = 1024 * 1000000; -export const JVM_PROJECT_FILES = ['pom.xml', 'build.gradle', 'build.gradle.kts'] +export const JVM_PROJECT_FILES = ['pom.xml', 'build.gradle', 'build.gradle.kts', 'settings.gradle', 'settings.gradle.kts'] export function runBuilderCommand( commandAlias: BuilderCommandAliasType, From b5c49ab2c1673e7a41dc8574908b2253fdd4a240 Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Fri, 26 Jan 2024 19:29:18 +0000 Subject: [PATCH 04/12] chore(common-jvm): fix retrieval of `groupId` in project hierarchy --- .../src/lib/utils/gradle-utils.spec.ts | 19 ++++++++++++++++++- .../common-jvm/src/lib/utils/gradle-utils.ts | 14 +++++++------- .../common-jvm/src/lib/utils/maven-utils.ts | 6 +++--- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.spec.ts b/packages/common-jvm/src/lib/utils/gradle-utils.spec.ts index 61decc4f..da61b381 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.spec.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.spec.ts @@ -13,7 +13,7 @@ import { } from './gradle-utils'; import { createTreeWithEmptyWorkspace } from '@nx/devkit/testing'; import { stripIndent } from '@nxrocks/common'; -import { SPOTLESS_GRADLE_PLUGIN_ID } from '.'; +import { SPOTLESS_GRADLE_PLUGIN_ID, checkForMultiModuleGradleProject } from '.'; const BUILD_GRADLE_FILE = `plugins { id 'org.springframework.boot' version '2.6.2' @@ -469,5 +469,22 @@ describe('gradle-utils', () => { expect(addGradleModule(tree, rootFolder, 'library1', true)).toBe(false); }); }); + + describe('checkForMultiModuleGradleProject', ()=>{ + + it('should return true if the given settings.gradle represents a multi-module gradle project', ()=>{ + const settings = ` + // For more information about Spring boot multi-modules projects, go to: https://spring.io/guides/gs/multi-module/ + rootProject.name = 'gboot-parent' + + + include 'gbootlib' + include 'gbootapp' + `; + + expect(checkForMultiModuleGradleProject(settings)).toBe(true) + }); + }); + }); diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.ts b/packages/common-jvm/src/lib/utils/gradle-utils.ts index 71871547..8996db96 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.ts @@ -319,7 +319,7 @@ export function hasMultiModuleGradleProjectInTree(tree: Tree, rootFolder: string if (settings === null) return false; - return checkForMultiModuleProject(settings); + return checkForMultiModuleGradleProject(settings); } export function hasMultiModuleGradleProject(cwd: string) { @@ -330,10 +330,10 @@ export function hasMultiModuleGradleProject(cwd: string) { const extension = getGradleBuildFilesExtension({ root: cwd }); const settings = getProjectFileContent({ root: cwd }, `settings${extension}`); - return checkForMultiModuleProject(settings); + return checkForMultiModuleGradleProject(settings); } -function checkForMultiModuleProject(settings: string) { +export function checkForMultiModuleGradleProject(settings: string) { const opts = { fragments: [/rootProject\.name\s*=\s*'/, /include\s+'/], logicalOp: 'and' as const @@ -394,7 +394,7 @@ export function getGradleModules(cwd: string): string[] { const extension = getGradleBuildFilesExtension({ root: cwd }); const settings = getProjectFileContent({ root: cwd }, `settings${extension}`); - const modulesRegex = extension === '.gradle.kts' ? /include\(":?(\w+)"\)/g : /include\s+':?(\w+)'/g; + const modulesRegex = extension === '.gradle.kts' ? /include\s*\(":?(\w+)"\)/g : /include\s+':?(\w+)'/g; const modules = []; let m; while ((m = modulesRegex.exec(settings))) { @@ -487,11 +487,11 @@ export function getCoordinatesForGradleProjet(cwd: string): { groupId?: string | function getGroupIdInHierarchy(cwd: string, buildFileExtension: string): string | undefined { - if (cwd === workspaceRoot) - return undefined; - const { parentFolder: root, currentFolder: name } = getCurrentAndParentFolder(cwd); + if (root === '.') // we reach the root of the workspace without finding the groupId, so we stop the search + return undefined; + let groupId; if (hasGradleBuildFile(root) && hasGradleModule(root, name)) { const buildGradle = getProjectFileContent({ root: cwd }, `build${buildFileExtension}`); diff --git a/packages/common-jvm/src/lib/utils/maven-utils.ts b/packages/common-jvm/src/lib/utils/maven-utils.ts index e708d487..585a485c 100644 --- a/packages/common-jvm/src/lib/utils/maven-utils.ts +++ b/packages/common-jvm/src/lib/utils/maven-utils.ts @@ -515,11 +515,11 @@ export function getCoordinatesForMavenProjet(cwd: string): { groupId?: string | function getGroupIdInHierarchy(cwd: string): string | undefined { - if (cwd === workspaceRoot) - return undefined; - const { parentFolder: root, currentFolder: name } = getCurrentAndParentFolder(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; From 734874070264ed701b8fe2b63caf82e9c7a94f7b Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Fri, 26 Jan 2024 19:30:50 +0000 Subject: [PATCH 05/12] fix(nx-spring-boot): fix how Spring Boot projects using `gradle` are detected --- packages/nx-spring-boot/src/utils/boot-utils.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/nx-spring-boot/src/utils/boot-utils.ts b/packages/nx-spring-boot/src/utils/boot-utils.ts index 80144d7e..8076c974 100644 --- a/packages/nx-spring-boot/src/utils/boot-utils.ts +++ b/packages/nx-spring-boot/src/utils/boot-utils.ts @@ -77,8 +77,8 @@ export function isBootProject(project: {root:string}): boolean { if (isGradleProject(project)) { return checkProjectBuildFileContains(project, { fragments: [ - "implementation 'org.springframework.boot:spring-boot-starter-parent'", - 'implementation("org.springframework.boot:spring-boot-starter")', + "id 'io.spring.dependency-management'", + 'id("io.spring.dependency-management"' ], }); } From 22c91526f921138aba776c61669dbb707f82426b Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Sat, 27 Jan 2024 08:34:28 +0000 Subject: [PATCH 06/12] =?UTF-8?q?feat:=20generate=20the=20`build.gradle[.k?= =?UTF-8?q?ts]`=20file=20when=20initializing=20the=20parent=20=C3=A0Gradle?= =?UTF-8?q?`=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/common-jvm/src/lib/utils/gradle-utils.ts | 11 ++++++++--- .../project/lib/prompt-multi-module-support.ts | 2 +- .../project/lib/prompt-multi-module-support.ts | 2 +- .../project/lib/prompt-multi-module-support.ts | 2 +- .../project/lib/prompt-multi-module-support.ts | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.ts b/packages/common-jvm/src/lib/utils/gradle-utils.ts index 8996db96..e23a8e34 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.ts @@ -345,7 +345,7 @@ export function checkForMultiModuleGradleProject(settings: string) { }; return checkProjectFileContains(settings, opts) || checkProjectFileContains(settings, optsKts); - } +} export function hasGradleModuleInTree(tree: Tree, rootFolder: string, moduleName: string) { @@ -427,7 +427,7 @@ export function addGradleModule( return true } -export function initGradleParentModule(tree: Tree, rootFolder: string, parentModuleName: string, childModuleName: string, withKotlinDSL: boolean, helpComment = '') { +export function initGradleParentModule(tree: Tree, rootFolder: string, groupId: string, parentModuleName: string, childModuleName: string, withKotlinDSL: boolean, helpComment = '') { const settingsGradle = ` ${helpComment} @@ -436,7 +436,12 @@ rootProject.name = ${withKotlinDSL ? `"${parentModuleName}"` : `'${parentModuleN ${withKotlinDSL ? `include("${childModuleName}")` : `include '${childModuleName}'`} `; - tree.write(`./${rootFolder}/settings.gradle${withKotlinDSL ? '.kts' : ''}`, settingsGradle); + const buildGradle = `group = ${withKotlinDSL ? `"${groupId}"` : `'${groupId}'`}`; + + const ext = withKotlinDSL ? '.kts' : ''; + + tree.write(`./${rootFolder}/settings.gradle${ext}`, settingsGradle); + tree.write(`./${rootFolder}/build.gradle${ext}`, buildGradle); } export function getGradleWrapperFiles() { diff --git a/packages/nx-ktor/src/generators/project/lib/prompt-multi-module-support.ts b/packages/nx-ktor/src/generators/project/lib/prompt-multi-module-support.ts index 3e6490c1..2f9c5280 100644 --- a/packages/nx-ktor/src/generators/project/lib/prompt-multi-module-support.ts +++ b/packages/nx-ktor/src/generators/project/lib/prompt-multi-module-support.ts @@ -83,7 +83,7 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize initMavenParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, ``); } else { - initGradleParentModule(tree, options.moduleRoot, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KTS', `// ${helpComment}`); + initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KTS', `// ${helpComment}`); } } else if(options.addToExistingParentModule){ diff --git a/packages/nx-micronaut/src/generators/project/lib/prompt-multi-module-support.ts b/packages/nx-micronaut/src/generators/project/lib/prompt-multi-module-support.ts index 1d47d3c9..3af1432b 100644 --- a/packages/nx-micronaut/src/generators/project/lib/prompt-multi-module-support.ts +++ b/packages/nx-micronaut/src/generators/project/lib/prompt-multi-module-support.ts @@ -83,7 +83,7 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize initMavenParentModule(tree, options.moduleRoot, options.basePackage, options.parentModuleName, options.projectName, ``); } else { - initGradleParentModule(tree, options.moduleRoot, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KOTLIN', `// ${helpComment}`); + initGradleParentModule(tree, options.moduleRoot, options.basePackage, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KOTLIN', `// ${helpComment}`); } } else if(options.addToExistingParentModule){ diff --git a/packages/nx-quarkus/src/generators/project/lib/prompt-multi-module-support.ts b/packages/nx-quarkus/src/generators/project/lib/prompt-multi-module-support.ts index 09165cea..27a3243c 100644 --- a/packages/nx-quarkus/src/generators/project/lib/prompt-multi-module-support.ts +++ b/packages/nx-quarkus/src/generators/project/lib/prompt-multi-module-support.ts @@ -83,7 +83,7 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize initMavenParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, ``); } else { - initGradleParentModule(tree, options.moduleRoot, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KOTLIN_DSL', `// ${helpComment}`); + initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KOTLIN_DSL', `// ${helpComment}`); } } else if(options.addToExistingParentModule){ diff --git a/packages/nx-spring-boot/src/generators/project/lib/prompt-multi-module-support.ts b/packages/nx-spring-boot/src/generators/project/lib/prompt-multi-module-support.ts index 5f7f916c..63116e3d 100644 --- a/packages/nx-spring-boot/src/generators/project/lib/prompt-multi-module-support.ts +++ b/packages/nx-spring-boot/src/generators/project/lib/prompt-multi-module-support.ts @@ -82,7 +82,7 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize initMavenParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, ``); } else { - initGradleParentModule(tree, options.moduleRoot, options.parentModuleName, options.projectName, options. buildSystem === 'gradle-project-kotlin', `// ${helpComment}`); + initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, options. buildSystem === 'gradle-project-kotlin', `// ${helpComment}`); } } else if(options.addToExistingParentModule){ From 964c7f616bc157bc43a878c6352684727df2329e Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Mon, 29 Jan 2024 18:30:00 +0000 Subject: [PATCH 07/12] fix(common-jvm): fix `Project Graph` dependencies collection for projects using `Gradle` --- .../common-jvm/src/lib/utils/gradle-utils.ts | 22 +++++++++- .../common-jvm/src/lib/utils/maven-utils.ts | 2 +- packages/common-jvm/src/lib/utils/utils.ts | 41 ++++++++++--------- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.ts b/packages/common-jvm/src/lib/utils/gradle-utils.ts index e23a8e34..2b2b6d32 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.ts @@ -1,4 +1,4 @@ -import { Tree, workspaceRoot } from '@nx/devkit'; +import { Tree } from '@nx/devkit'; import { checkProjectFileContains, getGradleBuildFilesExtension, getGradleBuildFilesExtensionInTree, hasGradleSettingsFile, isGradleProjectSettingsInTree as hasGradleProjectSettingsInTree, hasGradleBuildFile } from './utils'; import { fileExists } from '@nx/workspace/src/utilities/fileutils'; import { resolve } from 'path'; @@ -490,6 +490,24 @@ export function getCoordinatesForGradleProjet(cwd: string): { groupId?: string | return { groupId, artifactId }; } +export function getPathFromParenModule(cwd: string): string[] { + + let pathFromParent: string[] = []; + let root: string, name: string; + let currentFolder = cwd; + do { + const obj = getCurrentAndParentFolder(currentFolder); + + root = obj.parentFolder; + name = obj.currentFolder; + currentFolder = root; + + pathFromParent = [name, ...pathFromParent]; + } while (!(hasGradleBuildFile(root) && hasGradleModule(root, name)) && root !== '.'); + + return pathFromParent; +} + function getGroupIdInHierarchy(cwd: string, buildFileExtension: string): string | undefined { const { parentFolder: root, currentFolder: name } = getCurrentAndParentFolder(cwd); @@ -499,7 +517,7 @@ function getGroupIdInHierarchy(cwd: string, buildFileExtension: string): string let groupId; if (hasGradleBuildFile(root) && hasGradleModule(root, name)) { - const buildGradle = getProjectFileContent({ root: cwd }, `build${buildFileExtension}`); + const buildGradle = getProjectFileContent({ root }, `build${buildFileExtension}`); groupId = buildGradle.match(/group\s*=\s*['"]([^"']+)['"]/)?.[1]; } diff --git a/packages/common-jvm/src/lib/utils/maven-utils.ts b/packages/common-jvm/src/lib/utils/maven-utils.ts index 585a485c..e6168f45 100644 --- a/packages/common-jvm/src/lib/utils/maven-utils.ts +++ b/packages/common-jvm/src/lib/utils/maven-utils.ts @@ -1,4 +1,4 @@ -import { Tree, workspaceRoot } from '@nx/devkit'; +import { Tree } from '@nx/devkit'; import { addXmlNode, findXmlContent, diff --git a/packages/common-jvm/src/lib/utils/utils.ts b/packages/common-jvm/src/lib/utils/utils.ts index f0a2c7a1..03e2c9ac 100644 --- a/packages/common-jvm/src/lib/utils/utils.ts +++ b/packages/common-jvm/src/lib/utils/utils.ts @@ -15,7 +15,7 @@ import { findNodeContent, } from '../utils'; import { getCoordinatesForMavenProjet, getMavenModules } from './maven-utils'; -import { getCoordinatesForGradleProjet, getGradleModules } from './gradle-utils'; +import { getCoordinatesForGradleProjet, getGradleModules, getPathFromParenModule } from './gradle-utils'; export const LARGE_BUFFER = 1024 * 1000000; @@ -35,8 +35,8 @@ export function runBuilderCommand( // Take the parameters or set defaults const buildSystem = getBuilder(options.cwd); const executable = buildSystem.getExecutable( - options.ignoreWrapper??false, - options.useLegacyWrapper??false + options.ignoreWrapper ?? false, + options.useLegacyWrapper ?? false ); const { cwd, command } = buildSystem.getCommand(commandAlias, options); // Create the command to execute @@ -52,7 +52,7 @@ export function runBuilderCommand( } } -export function isMavenProject(project: {root:string}) { +export function isMavenProject(project: { root: string }) { return fileExists(getProjectFilePath(project, 'pom.xml')); } @@ -64,7 +64,7 @@ export function hasMavenProject(cwd: string) { return fileExists(`${cwd}/pom.xml`); } -export function isGradleProject(project: {root:string}) { +export function isGradleProject(project: { root: string }) { return fileExists(getProjectFilePath(project, 'build.gradle')) || fileExists(getProjectFilePath(project, 'settings.gradle')) || fileExists(getProjectFilePath(project, 'build.gradle.kts')) || fileExists(getProjectFilePath(project, 'settings.gradle.kts')); } @@ -91,7 +91,7 @@ export function hasGradleBuildFile(cwd: string) { return fileExists(`${cwd}/build.gradle`) || fileExists(`${cwd}/build.gradle.kts`); } -export function getGradleBuildFilesExtension(project: {root:string}): '.gradle.kts' | '.gradle' | undefined { +export function getGradleBuildFilesExtension(project: { root: string }): '.gradle.kts' | '.gradle' | undefined { if (fileExists(getProjectFilePath(project, 'build.gradle.kts')) || fileExists(getProjectFilePath(project, 'settings.gradle.kts'))) { return '.gradle.kts'; } @@ -106,21 +106,21 @@ export function getGradleBuildFilesExtensionInTree(tree: Tree, rootFolder: strin return '.gradle.kts'; } - return (tree.exists(`./${rootFolder}/build.gradle`) || tree.exists(`./${rootFolder}/settings.gradle`)) + return (tree.exists(`./${rootFolder}/build.gradle`) || tree.exists(`./${rootFolder}/settings.gradle`)) ? '.gradle' : undefined; } export const getGradleDependencyIdRegEx = () => - /\s*(api|implementation|testImplementation)\s*\(?['"](?[^"']+)['"]\)?/g; + /\s*(api|implementation|testImplementation)\s*(\(?project)?\s*\(?['"](?[^"']+)['"]\)?\)?/g; -export function getJvmPackageInfo(project: {root:string}): PackageInfo { +export function getJvmPackageInfo(project: { root: string }): PackageInfo { if (isMavenProject(project)) { // maven project const pomXmlStr = getProjectFileContent(project, 'pom.xml'); const pomXmlNode = readXml(pomXmlStr); - const {groupId, artifactId} = getCoordinatesForMavenProjet(project.root); + const { groupId, artifactId } = getCoordinatesForMavenProjet(project.root); const dependencies: PackageInfo[] = []; @@ -152,19 +152,20 @@ export function getJvmPackageInfo(project: {root:string}): PackageInfo { if (isGradleProject(project)) { // gradle project const ext = getGradleBuildFilesExtension(project); - const {groupId, artifactId} = getCoordinatesForGradleProjet(project.root); + const { groupId } = getCoordinatesForGradleProjet(project.root); const gradleDependencyIdRegEx = getGradleDependencyIdRegEx(); const dependencyIds: string[] = []; - if(hasGradleBuildFile(project.root)){ + if (hasGradleBuildFile(project.root)) { const buildGradle = getProjectFileContent(project, `build${ext}`); - - let match: RegExpExecArray|null; + + let match: RegExpExecArray | null; do { match = gradleDependencyIdRegEx.exec(buildGradle); - if (match?.groups?.['id']) { - dependencyIds.push(match.groups['id']); + const id = match?.groups?.['id'] + if (id) {// project dependencies start with ':', we prepend the groupId to it + dependencyIds.push(id.startsWith(':') ? `${groupId}${id}` : id); } } while (match); } @@ -176,7 +177,7 @@ export function getJvmPackageInfo(project: {root:string}): PackageInfo { const modules = getGradleModules(project.root); return { - packageId: `${groupId}:${artifactId}`, + packageId: `${groupId}:${getPathFromParenModule(project.root).join(':')}`, packageFile: hasGradleSettingsFile(project.root) ? `settings${ext}` : `build${ext}`, dependencies, modules @@ -191,7 +192,7 @@ export function getJvmPackageInfo(project: {root:string}): PackageInfo { } export function checkProjectBuildFileContains( - project: {root:string}, + project: { root: string }, opts: { fragments: string[]; logicalOp?: 'and' | 'or' } ): boolean { @@ -226,10 +227,10 @@ export function checkProjectFileContains( function match(content: string, value: string | RegExp) { - if( typeof value === 'string'){ + if (typeof value === 'string') { return content.includes(value); } - else{ + else { return value.test(content) } } From 31367aed8c8f119c2a3ea948176de5fbfae2e96d Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Mon, 29 Jan 2024 18:40:06 +0000 Subject: [PATCH 08/12] chore: add nx graph port to `forwardPorts` in `devcontainer.json` --- .devcontainer/devcontainer.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cef8362c..cbd1e0d1 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -28,6 +28,11 @@ "mounts": [ "source=nxrocks-node_modules,target=${containerWorkspaceFolder}/node_modules,type=volume" ], + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + "forwardPorts": [ + 4211 + ], "runArgs": [], "postCreateCommand": "./.devcontainer/postCreateCommand.sh", "customizations": { From 110d675a7e04d3c35387b9d90ba57cb52b40ea4e Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Wed, 31 Jan 2024 22:56:36 +0000 Subject: [PATCH 09/12] feat(common-jvm): extends the search for content inside a project file to its prent module --- .../common-jvm/src/lib/utils/gradle-utils.ts | 18 ----- packages/common-jvm/src/lib/utils/utils.ts | 67 +++++++++++++++++-- 2 files changed, 60 insertions(+), 25 deletions(-) diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.ts b/packages/common-jvm/src/lib/utils/gradle-utils.ts index 2b2b6d32..2b2aacc8 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.ts @@ -490,24 +490,6 @@ export function getCoordinatesForGradleProjet(cwd: string): { groupId?: string | return { groupId, artifactId }; } -export function getPathFromParenModule(cwd: string): string[] { - - let pathFromParent: string[] = []; - let root: string, name: string; - let currentFolder = cwd; - do { - const obj = getCurrentAndParentFolder(currentFolder); - - root = obj.parentFolder; - name = obj.currentFolder; - currentFolder = root; - - pathFromParent = [name, ...pathFromParent]; - } while (!(hasGradleBuildFile(root) && hasGradleModule(root, name)) && root !== '.'); - - return pathFromParent; -} - function getGroupIdInHierarchy(cwd: string, buildFileExtension: string): string | undefined { const { parentFolder: root, currentFolder: name } = getCurrentAndParentFolder(cwd); diff --git a/packages/common-jvm/src/lib/utils/utils.ts b/packages/common-jvm/src/lib/utils/utils.ts index 03e2c9ac..d8286882 100644 --- a/packages/common-jvm/src/lib/utils/utils.ts +++ b/packages/common-jvm/src/lib/utils/utils.ts @@ -4,6 +4,7 @@ import { fileExists } from '@nx/workspace/src/utilities/fileutils'; import { BuilderCommandAliasType, BuilderCore } from '../builders'; import { + getCurrentAndParentFolder, getProjectFileContent, getProjectFilePath, getProjectRoot, @@ -14,8 +15,8 @@ import { findXmlNodes, findNodeContent, } from '../utils'; -import { getCoordinatesForMavenProjet, getMavenModules } from './maven-utils'; -import { getCoordinatesForGradleProjet, getGradleModules, getPathFromParenModule } from './gradle-utils'; +import { getCoordinatesForMavenProjet, getMavenModules, hasMavenModule } from './maven-utils'; +import { getCoordinatesForGradleProjet, getGradleModules, hasGradleModule } from './gradle-utils'; export const LARGE_BUFFER = 1024 * 1000000; @@ -177,7 +178,7 @@ export function getJvmPackageInfo(project: { root: string }): PackageInfo { const modules = getGradleModules(project.root); return { - packageId: `${groupId}:${getPathFromParenModule(project.root).join(':')}`, + packageId: `${groupId}:${getPathFromParentModule(project.root).join(':')}`, packageFile: hasGradleSettingsFile(project.root) ? `settings${ext}` : `build${ext}`, dependencies, modules @@ -193,21 +194,33 @@ export function getJvmPackageInfo(project: { root: string }): PackageInfo { export function checkProjectBuildFileContains( project: { root: string }, - opts: { fragments: string[]; logicalOp?: 'and' | 'or' } + opts: { fragments: string[]; logicalOp?: 'and' | 'or' }, + searchInParentModule = true ): boolean { + let found = false; if (isMavenProject(project)) { const content = getProjectFileContent(project, 'pom.xml'); - return checkProjectFileContains(content, opts); + found = checkProjectFileContains(content, opts); + if (!found && searchInParentModule) {//not found in the project, check at parent module level + const parentRoot = getPathToParentModule(project.root); + const parentModuleContent = getProjectFileContent({ root: parentRoot }, 'pom.xml'); + return checkProjectFileContains(parentModuleContent, opts); + } } if (isGradleProject(project)) { const ext = getGradleBuildFilesExtension(project); const content = getProjectFileContent(project, `build${ext}`); - return checkProjectFileContains(content, opts); + found = checkProjectFileContains(content, opts); + if (!found && searchInParentModule) {//not found in the project, check at parent module level + const parentRoot = getPathToParentModule(project.root); + const parentModuleContent = getProjectFileContent({ root: parentRoot }, `build${ext}`); + return checkProjectFileContains(parentModuleContent, opts); + } } - return false; + return found; } export function checkProjectFileContains( @@ -225,6 +238,46 @@ export function checkProjectFileContains( return findOccurencesInContent(content); } +export function getPathFromParentModule(cwd: string): string[] { + + let pathFromParent: string[] = []; + let root: string, name: string; + let currentFolder = cwd; + do { + const obj = getCurrentAndParentFolder(currentFolder); + + root = obj.parentFolder; + name = obj.currentFolder; + currentFolder = root; + + pathFromParent = [name, ...pathFromParent]; + } while ( + !(hasGradleBuildFile(root) && hasGradleModule(root, name)) && + !(hasMavenProject(root) && hasMavenModule(root, name)) && + root !== '.'); + + return pathFromParent; +} + +export function getPathToParentModule(cwd: string): string { + + let root: string, name: string; + let currentFolder = cwd; + do { + const obj = getCurrentAndParentFolder(currentFolder); + + root = obj.parentFolder; + name = obj.currentFolder; + + currentFolder = root; + } while ( + !(hasGradleBuildFile(root) && hasGradleModule(root, name)) && + !(hasMavenProject(root) && hasMavenModule(root, name)) && + root !== '.'); + + return root; +} + function match(content: string, value: string | RegExp) { if (typeof value === 'string') { From db946718a5f4e59f8cb4e6f9a30f74f1ac8fab39 Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Tue, 6 Feb 2024 20:54:35 +0000 Subject: [PATCH 10/12] feat(common-jvm): update utils for better support for `Maven` and `Gradle` muti-module projects --- .../src/lib/utils/gradle-utils.spec.ts | 8 +-- .../common-jvm/src/lib/utils/gradle-utils.ts | 12 ++-- packages/common-jvm/src/lib/utils/utils.ts | 60 ++++++++++++++++--- 3 files changed, 63 insertions(+), 17 deletions(-) diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.spec.ts b/packages/common-jvm/src/lib/utils/gradle-utils.spec.ts index da61b381..bdb9b1f0 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.spec.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.spec.ts @@ -442,7 +442,7 @@ describe('gradle-utils', () => { tree.write(`./${rootFolder}/settings.gradle`, MULTI_MODULE_SETTINGS_FILE); expect(hasGradleModuleInTree(tree, rootFolder, 'libraryX')).toBe(false); - expect(addGradleModule(tree, rootFolder, 'libraryX', false)).toBe(true); + expect(addGradleModule(tree, rootFolder, 'libraryX', '', false)).toBe(true); expect(hasGradleModuleInTree(tree, rootFolder, 'libraryX')).toBe(true); }); @@ -450,7 +450,7 @@ describe('gradle-utils', () => { tree.write(`./${rootFolder}/build.gradle`, BUILD_GRADLE_FILE); tree.write(`./${rootFolder}/settings.gradle`, MULTI_MODULE_SETTINGS_FILE); - expect(addGradleModule(tree, rootFolder, 'library1', false)).toBe(false); + expect(addGradleModule(tree, rootFolder, 'library1', '', false)).toBe(false); }); it('should add kotlin gradle module when not already present', ()=>{ @@ -458,7 +458,7 @@ describe('gradle-utils', () => { tree.write(`./${rootFolder}/settings.gradle.kts`, MULTI_MODULE_SETTINGS_KTS_FILE); expect(hasGradleModuleInTree(tree, rootFolder, 'libraryX')).toBe(false); - expect(addGradleModule(tree, rootFolder, 'libraryX', true)).toBe(true); + expect(addGradleModule(tree, rootFolder, 'libraryX', '', true)).toBe(true); expect(hasGradleModuleInTree(tree, rootFolder, 'libraryX')).toBe(true); }); @@ -466,7 +466,7 @@ describe('gradle-utils', () => { tree.write(`./${rootFolder}/build.gradle.kts`, BUILD_GRADLE_KOTLIN_FILE); tree.write(`./${rootFolder}/settings.gradle.kts`, MULTI_MODULE_SETTINGS_KTS_FILE); - expect(addGradleModule(tree, rootFolder, 'library1', true)).toBe(false); + expect(addGradleModule(tree, rootFolder, 'library1', '', true)).toBe(false); }); }); diff --git a/packages/common-jvm/src/lib/utils/gradle-utils.ts b/packages/common-jvm/src/lib/utils/gradle-utils.ts index 2b2aacc8..d0c815a3 100644 --- a/packages/common-jvm/src/lib/utils/gradle-utils.ts +++ b/packages/common-jvm/src/lib/utils/gradle-utils.ts @@ -394,7 +394,7 @@ export function getGradleModules(cwd: string): string[] { const extension = getGradleBuildFilesExtension({ root: cwd }); const settings = getProjectFileContent({ root: cwd }, `settings${extension}`); - const modulesRegex = extension === '.gradle.kts' ? /include\s*\(":?(\w+)"\)/g : /include\s+':?(\w+)'/g; + const modulesRegex = extension === '.gradle.kts' ? /include\s*\("([\w:]+)"\)/g : /include\s+'([\w:]+)'/g; const modules = []; let m; while ((m = modulesRegex.exec(settings))) { @@ -407,6 +407,7 @@ export function addGradleModule( tree: Tree, rootFolder: string, moduleName: string, + offsetFromRoot: string, withKotlinDSL: boolean ) { @@ -420,20 +421,23 @@ export function addGradleModule( let lastIncludeIdx = settingsGradle.lastIndexOf('include'); lastIncludeIdx = lastIncludeIdx > 0 ? lastIncludeIdx : settingsGradle.length; - const newModule = withKotlinDSL ? `\ninclude("${moduleName}")\n` : `\ninclude '${moduleName}'\n`; + + const name = offsetFromRoot === '.' ? moduleName: `${offsetFromRoot}/${moduleName}`.replaceAll('/', ':') ; + const newModule = withKotlinDSL ? `\ninclude("${name}")\n` : `\ninclude '${name}'\n`; const newSettingGradle = settingsGradle.slice(0, lastIncludeIdx) + newModule + settingsGradle.slice(lastIncludeIdx); tree.write(`${rootFolder}/settings${ext}`, newSettingGradle) return true } -export function initGradleParentModule(tree: Tree, rootFolder: string, groupId: string, parentModuleName: string, childModuleName: string, withKotlinDSL: boolean, helpComment = '') { +export function initGradleParentModule(tree: Tree, rootFolder: string, groupId: string, parentModuleName: string, childModuleName: string, offsetFromRoot: string, withKotlinDSL: boolean, helpComment = '') { + const name = offsetFromRoot === '.' ? childModuleName: `${offsetFromRoot}/${childModuleName}`.replaceAll('/', ':') ; const settingsGradle = ` ${helpComment} rootProject.name = ${withKotlinDSL ? `"${parentModuleName}"` : `'${parentModuleName}'`} -${withKotlinDSL ? `include("${childModuleName}")` : `include '${childModuleName}'`} +${withKotlinDSL ? `include("${name}")` : `include '${name}'`} `; const buildGradle = `group = ${withKotlinDSL ? `"${groupId}"` : `'${groupId}'`}`; diff --git a/packages/common-jvm/src/lib/utils/utils.ts b/packages/common-jvm/src/lib/utils/utils.ts index d8286882..5a618c17 100644 --- a/packages/common-jvm/src/lib/utils/utils.ts +++ b/packages/common-jvm/src/lib/utils/utils.ts @@ -1,4 +1,4 @@ -import { logger, Tree } from '@nx/devkit'; +import { createProjectGraphAsync, logger, ProjectGraph, readCachedProjectGraph, Tree } from '@nx/devkit'; import { execSync } from 'child_process'; import { fileExists } from '@nx/workspace/src/utilities/fileutils'; @@ -17,6 +17,7 @@ import { } from '../utils'; import { getCoordinatesForMavenProjet, getMavenModules, hasMavenModule } from './maven-utils'; import { getCoordinatesForGradleProjet, getGradleModules, hasGradleModule } from './gradle-utils'; +import { dirname, relative } from 'path'; export const LARGE_BUFFER = 1024 * 1000000; @@ -130,7 +131,7 @@ export function getJvmPackageInfo(project: { root: string }): PackageInfo { `/project/dependencies/dependency` ); - if (Array.isArray(dependencyNodes)) + if (Array.isArray(dependencyNodes)){ dependencyNodes?.forEach((node) => { const depGroupId = findNodeContent(node, `/dependency/groupId/text()`); const depArtifactId = findNodeContent( @@ -142,18 +143,21 @@ export function getJvmPackageInfo(project: { root: string }): PackageInfo { packageFile: 'pom.xml', }); }); + } + + const modules = getMavenModules(project.root); return { packageId: `${groupId}:${artifactId}`, packageFile: 'pom.xml', dependencies, - modules: getMavenModules(project.root) + modules: modules.map(mod => `${groupId}:${mod}`) }; } if (isGradleProject(project)) { // gradle project const ext = getGradleBuildFilesExtension(project); - const { groupId } = getCoordinatesForGradleProjet(project.root); + const { groupId, artifactId } = getCoordinatesForGradleProjet(project.root); const gradleDependencyIdRegEx = getGradleDependencyIdRegEx(); const dependencyIds: string[] = []; @@ -177,11 +181,14 @@ export function getJvmPackageInfo(project: { root: string }): PackageInfo { const modules = getGradleModules(project.root); + const offsetFromRoot = getPathFromParentModule(project.root); + const pkgId = offsetFromRoot ? offsetFromRoot.replaceAll('/', ':') : artifactId; + return { - packageId: `${groupId}:${getPathFromParentModule(project.root).join(':')}`, + packageId: `${groupId}:${pkgId}`, packageFile: hasGradleSettingsFile(project.root) ? `settings${ext}` : `build${ext}`, dependencies, - modules + modules: modules.map(mod => `${groupId}:${mod}`) }; } @@ -238,7 +245,7 @@ export function checkProjectFileContains( return findOccurencesInContent(content); } -export function getPathFromParentModule(cwd: string): string[] { +export function getPathFromParentModule(cwd: string): string { let pathFromParent: string[] = []; let root: string, name: string; @@ -250,13 +257,16 @@ export function getPathFromParentModule(cwd: string): string[] { name = obj.currentFolder; currentFolder = root; - pathFromParent = [name, ...pathFromParent]; + if (root !== '.') { + pathFromParent = [name, ...pathFromParent]; + } + } while ( !(hasGradleBuildFile(root) && hasGradleModule(root, name)) && !(hasMavenProject(root) && hasMavenModule(root, name)) && root !== '.'); - return pathFromParent; + return pathFromParent.slice(1).join('/'); } export function getPathToParentModule(cwd: string): string { @@ -278,6 +288,38 @@ export function getPathToParentModule(cwd: string): string { return root; } +export async function getAdjustedProjectAndModuleRoot(options: { + projectRoot: string; + addToExistingParentModule?: boolean; + parentModuleName?: string; +}, isMavenProject: boolean +) { + + const projectGraph: ProjectGraph = process.env['NX_INTERACTIVE'] === 'true' ? readCachedProjectGraph() : await createProjectGraphAsync(); + + if (options.addToExistingParentModule && options.parentModuleName && !projectGraph.nodes[options.parentModuleName]) { + throw new Error(`No parent module project named '${options.parentModuleName}' was found in this workspace! Make sure the project exists.`); + } + const indexOfPathSlash = isMavenProject ? options.projectRoot.lastIndexOf('/') : options.projectRoot.indexOf('/'); + let projectRoot = options.projectRoot; + let moduleRoot; + if (options.addToExistingParentModule && options.parentModuleName) { + moduleRoot = projectGraph.nodes[options.parentModuleName].data.root; + } + else { + const rootFolder = options.projectRoot.substring(0, indexOfPathSlash); + moduleRoot = `${rootFolder}/${options.parentModuleName}`; + } + projectRoot = `${moduleRoot}/${options.projectRoot.substring(indexOfPathSlash + 1)}`; + + const offsetFromRoot = dirname(relative(moduleRoot, projectRoot)); + + return { + projectRoot, + moduleRoot, + offsetFromRoot + }; +} function match(content: string, value: string | RegExp) { if (typeof value === 'string') { From ae587ad3de615f7f20a054e64202902d0b0d9b07 Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Tue, 6 Feb 2024 20:56:06 +0000 Subject: [PATCH 11/12] feat(common): update Project Graph generation for JVM projects with child modules --- .../common/src/lib/workspace/project-graph.ts | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/packages/common/src/lib/workspace/project-graph.ts b/packages/common/src/lib/workspace/project-graph.ts index 8be14df2..87091ecf 100644 --- a/packages/common/src/lib/workspace/project-graph.ts +++ b/packages/common/src/lib/workspace/project-graph.ts @@ -99,15 +99,19 @@ export function getDependenciesForProject( } }); - rootPkgInfo.modules?.forEach((childModuleName) => { - dependencies.push( - { - source: rootProjectName, - target: childModuleName, - type: DependencyType.static, - sourceFile: joinPathFragments(rootProjectFolder, rootPkgInfo.packageFile) - } - ); + rootPkgInfo.modules?.forEach((moduleId) => { + const depProjectName = workspace.packages[moduleId]; + + if (depProjectName) { + dependencies.push( + { + source: rootProjectName, + target: depProjectName, + type: DependencyType.static, + sourceFile: joinPathFragments(rootProjectFolder, rootPkgInfo.packageFile) + } + ); + } }); return dependencies; From dea011f8aa26a265578bad57a443b257a24902a2 Mon Sep 17 00:00:00 2001 From: Tine Kondo Date: Tue, 6 Feb 2024 20:59:30 +0000 Subject: [PATCH 12/12] feat: improve multi-module support for `Maven` and `Gradle` projects - Better support for `Gradle` projects in nested folders --- .../lib/prompt-multi-module-support.ts | 48 +++++++------------ .../lib/prompt-multi-module-support.ts | 38 +++++---------- .../lib/prompt-multi-module-support.ts | 48 +++++++------------ .../lib/prompt-multi-module-support.ts | 42 ++++++---------- 4 files changed, 60 insertions(+), 116 deletions(-) diff --git a/packages/nx-ktor/src/generators/project/lib/prompt-multi-module-support.ts b/packages/nx-ktor/src/generators/project/lib/prompt-multi-module-support.ts index 2f9c5280..ea0d7ece 100644 --- a/packages/nx-ktor/src/generators/project/lib/prompt-multi-module-support.ts +++ b/packages/nx-ktor/src/generators/project/lib/prompt-multi-module-support.ts @@ -1,8 +1,8 @@ -import { logger, createProjectGraphAsync, ProjectGraph, Tree, readCachedProjectGraph } from "@nx/devkit"; +import { logger, createProjectGraphAsync, ProjectGraph, Tree } from "@nx/devkit"; import { prompt } from 'enquirer'; import { NormalizedSchema } from "../schema"; -import { addGradleModule, addMavenModule, initGradleParentModule, initMavenParentModule, hasMultiModuleGradleProjectInTree, hasMultiModuleMavenProjectInTree } from "@nxrocks/common-jvm"; +import { addGradleModule, addMavenModule, initGradleParentModule, initMavenParentModule, hasMultiModuleGradleProjectInTree, hasMultiModuleMavenProjectInTree, getAdjustedProjectAndModuleRoot } from "@nxrocks/common-jvm"; export async function promptForMultiModuleSupport(tree: Tree, options: NormalizedSchema) { @@ -50,7 +50,7 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize options.addToExistingParentModule = await prompt({ name: 'addToExistingParentModule', message: - `We found ${multiModuleProjects.length} existing ${buildSystemName} multi-module projects in your workaspace${multiModuleProjects.length === 1 ? `('${multiModuleProjects[0].name}')` : ''}.\nWould you like to add this new project ${multiModuleProjects.length === 1 ? 'to it?' : 'into one of them?'}`, + `We found ${multiModuleProjects.length} existing ${buildSystemName} multi-module projects in your workaspace${multiModuleProjects.length === 1 ? `('${multiModuleProjects[0].name}')` : ''}.\nWould you like to add this new project ${multiModuleProjects.length === 1 ? 'to it?' : 'into one of them?'}`, type: 'confirm', initial: false }).then((a) => a['addToExistingParentModule']); @@ -63,7 +63,7 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize options.parentModuleName = await prompt({ name: 'parentModuleName', message: - 'Which parent module would you like to add the new project into?', + 'Which parent module would you like to add the new project into?', type: 'select', choices: multiModuleProjects.map(p => p.name), }).then((a) => a['parentModuleName']); @@ -72,46 +72,32 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize } } - if((options.transformIntoMultiModule || options.addToExistingParentModule) && options.parentModuleName){ - const helpComment = `For more information about ${buildSystemName} multi-modules projects, go to: ${options.buildSystem === 'MAVEN' ? 'https://maven.apache.org/guides/mini/guide-multiple-modules-4.html' : 'https://docs.gradle.org/current/userguide/intro_multi_project_builds.html'}`; + if ((options.transformIntoMultiModule || options.addToExistingParentModule) && options.parentModuleName) { + const isMavenProject = options.buildSystem === 'MAVEN'; + const helpComment = `For more information about ${buildSystemName} multi-modules projects, go to: ${isMavenProject ? 'https://maven.apache.org/guides/mini/guide-multiple-modules-4.html' : 'https://docs.gradle.org/current/userguide/intro_multi_project_builds.html'}`; - await adjustOptionsForMultiModules(options); + const opts = await getAdjustedProjectAndModuleRoot(options, isMavenProject); - if(options.transformIntoMultiModule){ + options.projectRoot = opts.projectRoot; + options.moduleRoot = opts.moduleRoot; + + if (options.transformIntoMultiModule) { // add the root module - if(options.buildSystem === 'MAVEN'){ + if (isMavenProject) { initMavenParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, ``); } else { - initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KTS', `// ${helpComment}`); + initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, opts.offsetFromRoot, options.buildSystem === 'GRADLE_KTS', `// ${helpComment}`); } } - else if(options.addToExistingParentModule){ + else if (options.addToExistingParentModule) { // add to the chosen root module - if(options.buildSystem === 'MAVEN'){ + if (isMavenProject) { addMavenModule(tree, options.moduleRoot, options.projectName); } else { - addGradleModule(tree, options.moduleRoot, options.projectName, options. buildSystem === 'GRADLE_KTS'); + addGradleModule(tree, options.moduleRoot, options.projectName, opts.offsetFromRoot, options.buildSystem === 'GRADLE_KTS'); } } } } - -async function adjustOptionsForMultiModules(options: NormalizedSchema) { - - const projectGraph: ProjectGraph = process.env.NX_INTERACTIVE === 'true' ? readCachedProjectGraph() : await createProjectGraphAsync(); - - if(options.addToExistingParentModule && !projectGraph.nodes[options.parentModuleName]){ - throw new Error(`No parent module project named '${options.parentModuleName}' was found in this workspace! Make sure the project exists.`); - } - const lastIndexOfPathSlash = options.projectRoot.lastIndexOf('/'); - if(options.addToExistingParentModule){ - options.moduleRoot = projectGraph.nodes[options.parentModuleName].data.root; - } - else { - const rootFolder = options.projectRoot.substring(0, lastIndexOfPathSlash); - options.moduleRoot = `${rootFolder}/${options.parentModuleName}`; - } - options.projectRoot = `${options.moduleRoot}/${options.projectRoot.substring(lastIndexOfPathSlash + 1)}`; -} \ No newline at end of file diff --git a/packages/nx-micronaut/src/generators/project/lib/prompt-multi-module-support.ts b/packages/nx-micronaut/src/generators/project/lib/prompt-multi-module-support.ts index 3af1432b..37a039c8 100644 --- a/packages/nx-micronaut/src/generators/project/lib/prompt-multi-module-support.ts +++ b/packages/nx-micronaut/src/generators/project/lib/prompt-multi-module-support.ts @@ -1,8 +1,8 @@ -import { logger, createProjectGraphAsync, ProjectGraph, Tree, readCachedProjectGraph } from "@nx/devkit"; +import { logger, createProjectGraphAsync, ProjectGraph, Tree } from "@nx/devkit"; import { prompt } from 'enquirer'; import { NormalizedSchema } from "../schema"; -import { addGradleModule, addMavenModule, initGradleParentModule, initMavenParentModule, hasMultiModuleGradleProjectInTree, hasMultiModuleMavenProjectInTree } from "@nxrocks/common-jvm"; +import { addGradleModule, addMavenModule, initGradleParentModule, initMavenParentModule, hasMultiModuleGradleProjectInTree, hasMultiModuleMavenProjectInTree, getAdjustedProjectAndModuleRoot } from "@nxrocks/common-jvm"; export async function promptForMultiModuleSupport(tree: Tree, options: NormalizedSchema) { @@ -73,45 +73,31 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize } if((options.transformIntoMultiModule || options.addToExistingParentModule) && options.parentModuleName){ - const helpComment = `For more information about ${buildSystemName} multi-modules projects, go to: ${options.buildSystem === 'MAVEN' ? 'https://maven.apache.org/guides/mini/guide-multiple-modules-4.html' : 'https://docs.gradle.org/current/userguide/intro_multi_project_builds.html'}`; + const isMavenProject = options.buildSystem === 'MAVEN'; + const helpComment = `For more information about ${buildSystemName} multi-modules projects, go to: ${isMavenProject ? 'https://maven.apache.org/guides/mini/guide-multiple-modules-4.html' : 'https://docs.gradle.org/current/userguide/intro_multi_project_builds.html'}`; - await adjustOptionsForMultiModules(options); + const opts = await getAdjustedProjectAndModuleRoot(options, isMavenProject); + + options.projectRoot = opts.projectRoot; + options.moduleRoot = opts.moduleRoot; if(options.transformIntoMultiModule){ // add the root module - if(options.buildSystem === 'MAVEN'){ + if(isMavenProject){ initMavenParentModule(tree, options.moduleRoot, options.basePackage, options.parentModuleName, options.projectName, ``); } else { - initGradleParentModule(tree, options.moduleRoot, options.basePackage, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KOTLIN', `// ${helpComment}`); + initGradleParentModule(tree, options.moduleRoot, options.basePackage, options.parentModuleName, options.projectName, opts.offsetFromRoot, options. buildSystem === 'GRADLE_KOTLIN', `// ${helpComment}`); } } else if(options.addToExistingParentModule){ // add to the chosen root module - if(options.buildSystem === 'MAVEN'){ + if(isMavenProject){ addMavenModule(tree, options.moduleRoot, options.projectName); } else { - addGradleModule(tree, options.moduleRoot, options.projectName, options. buildSystem === 'GRADLE_KOTLIN'); + addGradleModule(tree, options.moduleRoot, options.projectName, opts.offsetFromRoot, options. buildSystem === 'GRADLE_KOTLIN'); } } } } - -async function adjustOptionsForMultiModules(options: NormalizedSchema) { - - const projectGraph: ProjectGraph = process.env.NX_INTERACTIVE === 'true' ? readCachedProjectGraph() : await createProjectGraphAsync(); - - if(options.addToExistingParentModule && !projectGraph.nodes[options.parentModuleName]){ - throw new Error(`No parent module project named '${options.parentModuleName}' was found in this workspace! Make sure the project exists.`); - } - const lastIndexOfPathSlash = options.projectRoot.lastIndexOf('/'); - if(options.addToExistingParentModule){ - options.moduleRoot = projectGraph.nodes[options.parentModuleName].data.root; - } - else { - const rootFolder = options.projectRoot.substring(0, lastIndexOfPathSlash); - options.moduleRoot = `${rootFolder}/${options.parentModuleName}`; - } - options.projectRoot = `${options.moduleRoot}/${options.projectRoot.substring(lastIndexOfPathSlash + 1)}`; -} \ No newline at end of file diff --git a/packages/nx-quarkus/src/generators/project/lib/prompt-multi-module-support.ts b/packages/nx-quarkus/src/generators/project/lib/prompt-multi-module-support.ts index 27a3243c..41a84c22 100644 --- a/packages/nx-quarkus/src/generators/project/lib/prompt-multi-module-support.ts +++ b/packages/nx-quarkus/src/generators/project/lib/prompt-multi-module-support.ts @@ -1,8 +1,8 @@ -import { logger, createProjectGraphAsync, ProjectGraph, Tree, readCachedProjectGraph } from "@nx/devkit"; +import { logger, createProjectGraphAsync, ProjectGraph, Tree } from "@nx/devkit"; import { prompt } from 'enquirer'; import { NormalizedSchema } from "../schema"; -import { addGradleModule, addMavenModule, initGradleParentModule, initMavenParentModule, hasMultiModuleGradleProjectInTree, hasMultiModuleMavenProjectInTree } from "@nxrocks/common-jvm"; +import { addGradleModule, addMavenModule, initGradleParentModule, initMavenParentModule, hasMultiModuleGradleProjectInTree, hasMultiModuleMavenProjectInTree, getAdjustedProjectAndModuleRoot } from "@nxrocks/common-jvm"; export async function promptForMultiModuleSupport(tree: Tree, options: NormalizedSchema) { @@ -49,7 +49,7 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize options.addToExistingParentModule = await prompt({ name: 'addToExistingParentModule', message: - `We found ${multiModuleProjects.length} existing ${buildSystemName} multi-module projects in your workaspace${multiModuleProjects.length === 1 ? `('${multiModuleProjects[0].name}')` : ''}.\nWould you like to add this new project ${multiModuleProjects.length === 1 ? 'to it?' : 'into one of them?'}`, + `We found ${multiModuleProjects.length} existing ${buildSystemName} multi-module projects in your workaspace${multiModuleProjects.length === 1 ? `('${multiModuleProjects[0].name}')` : ''}.\nWould you like to add this new project ${multiModuleProjects.length === 1 ? 'to it?' : 'into one of them?'}`, type: 'confirm', initial: false }).then((a) => a['addToExistingParentModule']); @@ -62,7 +62,7 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize options.parentModuleName = await prompt({ name: 'parentModuleName', message: - 'Which parent module would you like to add the new project into?', + 'Which parent module would you like to add the new project into?', type: 'select', choices: multiModuleProjects.map(p => p.name), }).then((a) => a['parentModuleName']); @@ -72,46 +72,32 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize } } - if((options.transformIntoMultiModule || options.addToExistingParentModule) && options.parentModuleName){ - const helpComment = `For more information about ${buildSystemName} multi-modules projects, go to: ${options.buildSystem === 'MAVEN' ? 'https://maven.apache.org/guides/mini/guide-multiple-modules-4.html' : 'https://docs.gradle.org/current/userguide/intro_multi_project_builds.html'}`; + if ((options.transformIntoMultiModule || options.addToExistingParentModule) && options.parentModuleName) { + const isMavenProject = options.buildSystem === 'MAVEN'; + const helpComment = `For more information about ${buildSystemName} multi-modules projects, go to: ${isMavenProject ? 'https://maven.apache.org/guides/mini/guide-multiple-modules-4.html' : 'https://docs.gradle.org/current/userguide/intro_multi_project_builds.html'}`; - await adjustOptionsForMultiModules(options); + const opts = await getAdjustedProjectAndModuleRoot(options, isMavenProject); - if(options.transformIntoMultiModule){ + options.projectRoot = opts.projectRoot; + options.moduleRoot = opts.moduleRoot; + + if (options.transformIntoMultiModule) { // add the root module - if(options.buildSystem === 'MAVEN'){ + if (isMavenProject) { initMavenParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, ``); } else { - initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, options. buildSystem === 'GRADLE_KOTLIN_DSL', `// ${helpComment}`); + initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, opts.offsetFromRoot, options.buildSystem === 'GRADLE_KOTLIN_DSL', `// ${helpComment}`); } } - else if(options.addToExistingParentModule){ + else if (options.addToExistingParentModule) { // add to the chosen root module - if(options.buildSystem === 'MAVEN'){ + if (isMavenProject) { addMavenModule(tree, options.moduleRoot, options.projectName); } else { - addGradleModule(tree, options.moduleRoot, options.projectName, options. buildSystem === 'GRADLE_KOTLIN_DSL'); + addGradleModule(tree, options.moduleRoot, options.projectName, opts.offsetFromRoot, options.buildSystem === 'GRADLE_KOTLIN_DSL'); } } } } - -async function adjustOptionsForMultiModules(options: NormalizedSchema) { - - const projectGraph: ProjectGraph = process.env.NX_INTERACTIVE === 'true' ? readCachedProjectGraph() : await createProjectGraphAsync(); - - if(options.addToExistingParentModule && !projectGraph.nodes[options.parentModuleName]){ - throw new Error(`No parent module project named '${options.parentModuleName}' was found in this workspace! Make sure the project exists.`); - } - const lastIndexOfPathSlash = options.projectRoot.lastIndexOf('/'); - if(options.addToExistingParentModule){ - options.moduleRoot = projectGraph.nodes[options.parentModuleName].data.root; - } - else { - const rootFolder = options.projectRoot.substring(0, lastIndexOfPathSlash); - options.moduleRoot = `${rootFolder}/${options.parentModuleName}`; - } - options.projectRoot = `${options.moduleRoot}/${options.projectRoot.substring(lastIndexOfPathSlash + 1)}`; -} \ No newline at end of file diff --git a/packages/nx-spring-boot/src/generators/project/lib/prompt-multi-module-support.ts b/packages/nx-spring-boot/src/generators/project/lib/prompt-multi-module-support.ts index 63116e3d..2bd2108e 100644 --- a/packages/nx-spring-boot/src/generators/project/lib/prompt-multi-module-support.ts +++ b/packages/nx-spring-boot/src/generators/project/lib/prompt-multi-module-support.ts @@ -1,8 +1,8 @@ -import { logger, createProjectGraphAsync, ProjectGraph, Tree, readCachedProjectGraph } from "@nx/devkit"; +import { logger, createProjectGraphAsync, ProjectGraph, Tree } from "@nx/devkit"; import { prompt } from 'enquirer'; import { NormalizedSchema } from "../schema"; -import { addGradleModule, addMavenModule, initGradleParentModule, initMavenParentModule, hasMultiModuleGradleProjectInTree, hasMultiModuleMavenProjectInTree } from "@nxrocks/common-jvm"; +import { addGradleModule, addMavenModule, initGradleParentModule, initMavenParentModule, hasMultiModuleGradleProjectInTree, hasMultiModuleMavenProjectInTree, getAdjustedProjectAndModuleRoot } from "@nxrocks/common-jvm"; export async function promptForMultiModuleSupport(tree: Tree, options: NormalizedSchema) { if ( @@ -71,46 +71,32 @@ export async function promptForMultiModuleSupport(tree: Tree, options: Normalize } } - if((options.transformIntoMultiModule || options.addToExistingParentModule) && options.parentModuleName){ + if ((options.transformIntoMultiModule || options.addToExistingParentModule) && options.parentModuleName) { const helpComment = 'For more information about Spring boot multi-modules projects, go to: https://spring.io/guides/gs/multi-module/'; - await adjustOptionsForMultiModules(options); + const isMavenProject = options.buildSystem === 'maven-project'; + const opts = await getAdjustedProjectAndModuleRoot(options, isMavenProject); - if(options.transformIntoMultiModule){ + options.projectRoot = opts.projectRoot; + options.moduleRoot = opts.moduleRoot; + + if (options.transformIntoMultiModule) { // add the root module - if(options.buildSystem === 'maven-project'){ + if (isMavenProject) { initMavenParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, ``); } else { - initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, options. buildSystem === 'gradle-project-kotlin', `// ${helpComment}`); + initGradleParentModule(tree, options.moduleRoot, options.groupId, options.parentModuleName, options.projectName, opts.offsetFromRoot, options.buildSystem === 'gradle-project-kotlin', `// ${helpComment}`); } } - else if(options.addToExistingParentModule){ + else if (options.addToExistingParentModule) { // add to the chosen root module - if(options.buildSystem === 'maven-project'){ + if (isMavenProject) { addMavenModule(tree, options.moduleRoot, options.projectName); } else { - addGradleModule(tree, options.moduleRoot, options.projectName, options. buildSystem === 'gradle-project-kotlin'); + addGradleModule(tree, options.moduleRoot, options.projectName, opts.offsetFromRoot, options.buildSystem === 'gradle-project-kotlin'); } } } } - -async function adjustOptionsForMultiModules(options: NormalizedSchema) { - - const projectGraph: ProjectGraph = process.env.NX_INTERACTIVE === 'true' ? readCachedProjectGraph() : await createProjectGraphAsync(); - - if(options.addToExistingParentModule && !projectGraph.nodes[options.parentModuleName]){ - throw new Error(`No parent module project named '${options.parentModuleName}' was found in this workspace! Make sure the project exists.`); - } - const lastIndexOfPathSlash = options.projectRoot.lastIndexOf('/'); - if(options.addToExistingParentModule){ - options.moduleRoot = projectGraph.nodes[options.parentModuleName].data.root; - } - else { - const rootFolder = options.projectRoot.substring(0, lastIndexOfPathSlash); - options.moduleRoot = `${rootFolder}/${options.parentModuleName}`; - } - options.projectRoot = `${options.moduleRoot}/${options.projectRoot.substring(lastIndexOfPathSlash + 1)}`; -} \ No newline at end of file