Skip to content

Commit

Permalink
fix(nx-boot-maven): refactor maven dep graph (#206)
Browse files Browse the repository at this point in the history
* refactor: refactor maven dep graph [skip ci]

* refactor: refactor maven dep graph [skip ci]
  • Loading branch information
khalilou88 authored May 16, 2023
1 parent 2524b1a commit 0a704a4
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 86 deletions.
18 changes: 17 additions & 1 deletion packages/common/src/lib/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as path from 'path';
import * as stream from 'stream';
import { promisify } from 'util';
import { GetVersionFunction } from '../types';
import { readNxJson } from 'nx/src/config/configuration';
import { readNxJson, workspaceLayout } from 'nx/src/config/configuration';
import { execSync } from 'child_process';

export function getProject(context: ExecutorContext) {
Expand Down Expand Up @@ -183,3 +183,19 @@ function isSameDir(path1: string, path2: string) {
const relative = path.relative(path1, path2);
return !relative;
}

export function getProjectGraphNodeType(
projectRoot: string
): 'app' | 'e2e' | 'lib' {
if (!projectRoot) {
return 'lib';
}

const layout = workspaceLayout();

if (projectRoot.startsWith(layout.appsDir)) {
return 'app';
}

return 'lib';
}
160 changes: 84 additions & 76 deletions packages/maven/src/lib/graph/index.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,68 @@
import { getProjectGraphNodeType } from '@jnxplus/common';
import {
Hasher,
ProjectGraphBuilder,
ProjectGraphProjectNode,
joinPathFragments,
workspaceRoot,
} from '@nx/devkit';
import { workspaceLayout } from 'nx/src/config/configuration';
import * as fs from 'fs';
import { fileExists } from 'nx/src/utils/fileutils';
import * as path from 'path';
import { join } from 'path';
import { XmlDocument } from 'xmldoc';
import { readXml } from '../xml/index';

export function addProjects(
type MavenProjectType = {
name?: string;
artifactId: string;
projectDirPath: string;
};

export function addProjectsAndDependencies(
builder: ProjectGraphBuilder,
hasher: Hasher,
pluginName: string
) {
const projects: MavenProjectType[] = [];
addProjects(builder, hasher, projects, pluginName, '');
addDependencies(builder, projects);
}

function addProjects(
builder: ProjectGraphBuilder,
hasher: Hasher,
projects: MavenProjectType[],
pluginName: string,
projectRoot: string
) {
const projectJson = join(workspaceRoot, projectRoot, 'project.json');
const pomXmlPath = join(workspaceRoot, projectRoot, 'pom.xml');
//projectDirPath
const projectDirPath = join(workspaceRoot, projectRoot);
const projectJsonPath = join(projectDirPath, 'project.json');
const pomXmlPath = join(projectDirPath, 'pom.xml');
const pomXmlContent = readXml(pomXmlPath);

if (!fileExists(projectJson)) {
const projectName =
pomXmlContent.childNamed('artifactId')?.val ?? 'missingArtifactId';
//artifactId
const artifactIdXml = pomXmlContent.childNamed('artifactId');
if (artifactIdXml === undefined) {
throw new Error(`artifactId not found in pom.xml ${pomXmlPath}`);
}
const artifactId = artifactIdXml.val;

//isProjectJsonExists
const isProjectJsonExists = fileExists(projectJsonPath);

//name
let projectName;
if (isProjectJsonExists) {
const projectJson = JSON.parse(fs.readFileSync(projectJsonPath, 'utf8'));
projectName = projectJson.name;
}

//add project to graph
if (!isProjectJsonExists) {
const projectGraphNodeType = getProjectGraphNodeType(projectRoot);
builder.addNode({
name: projectName,
name: artifactId,
type: projectGraphNodeType,
data: {
root: projectRoot,
Expand All @@ -40,20 +76,21 @@ export function addProjects(
},
},
files: [
projectRoot === ''
? {
file: 'pom.xml',
hash: hasher.hashFile('pom.xml'),
}
: {
file: `${projectRoot}/pom.xml`,
hash: hasher.hashFile(`${projectRoot}/pom.xml`),
},
{
file: joinPathFragments(projectRoot, 'pom.xml'),
hash: hasher.hashFile(joinPathFragments(projectRoot, 'pom.xml')),
},
],
},
});
}

projects.push({
name: projectName,
artifactId: artifactId,
projectDirPath: projectDirPath,
});

const modulesXmlElement = pomXmlContent.childNamed('modules');
if (modulesXmlElement === undefined) {
return;
Expand All @@ -65,60 +102,44 @@ export function addProjects(
}

for (const moduleXmlElement of moduleXmlElementArray) {
const moduleRoot = join(projectRoot, moduleXmlElement.val).replace(
/\\/g,
'/'
);
addProjects(builder, hasher, pluginName, moduleRoot);
const moduleRoot = joinPathFragments(projectRoot, moduleXmlElement.val);
addProjects(builder, hasher, projects, pluginName, moduleRoot);
}
}

export function addDependencies(builder: ProjectGraphBuilder) {
const projects = getManagedProjects(builder.graph.nodes);

function addDependencies(
builder: ProjectGraphBuilder,
projects: MavenProjectType[]
) {
for (const project of projects) {
const pomXmlPath = join(workspaceRoot, project.data.root, 'pom.xml');
const pomXmlPath = join(project.projectDirPath, 'pom.xml');
const pomXmlContent = readXml(pomXmlPath);
const dependencies = getDependencies(pomXmlContent, projects);

const projectRoot = path.relative(workspaceRoot, project.projectDirPath);

for (const dependency of dependencies) {
builder.addStaticDependency(
project.name,
dependency.name,
join(project.data.root, 'pom.xml').replace(/\\/g, '/')
project.name ?? project.artifactId,
dependency.name ?? dependency.artifactId,
joinPathFragments(projectRoot, 'pom.xml')
);
}

const projectAbsolutePath = join(workspaceRoot, project.data.root);
const modules = getModules(projectAbsolutePath, pomXmlContent, projects);

const modules = getModules(project.projectDirPath, pomXmlContent, projects);
for (const module of modules) {
const moduleRoot = path.relative(workspaceRoot, module.projectDirPath);

builder.addStaticDependency(
module.name,
project.name,
join(module.data.root, 'pom.xml').replace(/\\/g, '/')
module.name ?? module.artifactId,
project.name ?? project.artifactId,
joinPathFragments(moduleRoot, 'pom.xml')
);
}
}
}

function getManagedProjects(nodes: Record<string, ProjectGraphProjectNode>) {
return Object.entries(nodes)
.filter((node) => isManagedProject(node[1]))
.map((node) => node[1]);
}

function isManagedProject(projectGraphNode: ProjectGraphProjectNode): boolean {
const pomXmlPath = join(workspaceRoot, projectGraphNode.data.root, 'pom.xml');
return (
(projectGraphNode.type === 'app' || projectGraphNode.type === 'lib') &&
fileExists(pomXmlPath)
);
}

function getDependencies(
pomXml: XmlDocument,
projects: ProjectGraphProjectNode[]
) {
function getDependencies(pomXml: XmlDocument, projects: MavenProjectType[]) {
const dependenciesXml = pomXml.childNamed('dependencies');
if (dependenciesXml === undefined) {
return [];
Expand All @@ -130,40 +151,27 @@ function getDependencies(
return dependencyXmlElement.childNamed('artifactId')?.val;
});

return projects.filter((project) => dependencies.includes(project.name));
return projects.filter((project) =>
dependencies.includes(project.artifactId)
);
}

function getModules(
projectAbsolutePath: string,
projectDirPath: string,
pomXml: XmlDocument,
projects: ProjectGraphProjectNode[]
projects: MavenProjectType[]
) {
const modulesXml = pomXml.childNamed('modules');
if (modulesXml === undefined) {
return [];
}

const modules = modulesXml.childrenNamed('module').map((moduleXmlElement) => {
const moduleRoot = join(projectAbsolutePath, moduleXmlElement.val);
const modulePomXmlPath = join(moduleRoot, 'pom.xml');
const moduleDirPath = join(projectDirPath, moduleXmlElement.val);
const modulePomXmlPath = join(moduleDirPath, 'pom.xml');
const modulePomXmlContent = readXml(modulePomXmlPath);
const moduleProjectName = modulePomXmlContent.childNamed('artifactId')?.val;
return moduleProjectName;
return modulePomXmlContent.childNamed('artifactId')?.val;
});

return projects.filter((project) => modules.includes(project.name));
}

function getProjectGraphNodeType(projectRoot: string): 'app' | 'e2e' | 'lib' {
if (projectRoot === '') {
return 'lib';
}

const layout = workspaceLayout();

if (projectRoot.startsWith(layout.appsDir)) {
return 'app';
}

return 'lib';
return projects.filter((project) => modules.includes(project.artifactId));
}
5 changes: 2 additions & 3 deletions packages/nx-boot-maven/src/dep-graph/lookup-deps.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { addProjectsAndDependencies } from '@jnxplus/maven';
import {
Hasher,
ProjectGraph,
ProjectGraphBuilder,
ProjectGraphProcessorContext,
} from '@nx/devkit';
import { addDependencies, addProjects } from '@jnxplus/maven';

export function processProjectGraph(
graph: ProjectGraph,
context: ProjectGraphProcessorContext
): ProjectGraph {
const builder = new ProjectGraphBuilder(graph);
const hasher = new Hasher(graph, context.nxJsonConfiguration, {});
addProjects(builder, hasher, '@jnxplus/nx-boot-maven', '');
addDependencies(builder);
addProjectsAndDependencies(builder, hasher, '@jnxplus/nx-boot-maven');
return builder.getUpdatedProjectGraph();
}
5 changes: 2 additions & 3 deletions packages/nx-maven/src/dep-graph/lookup-deps.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { addProjectsAndDependencies } from '@jnxplus/maven';
import {
Hasher,
ProjectGraph,
ProjectGraphBuilder,
ProjectGraphProcessorContext,
} from '@nx/devkit';
import { addDependencies, addProjects } from '@jnxplus/maven';

export function processProjectGraph(
graph: ProjectGraph,
context: ProjectGraphProcessorContext
): ProjectGraph {
const builder = new ProjectGraphBuilder(graph);
const hasher = new Hasher(graph, context.nxJsonConfiguration, {});
addProjects(builder, hasher, '@jnxplus/nx-maven', '');
addDependencies(builder);
addProjectsAndDependencies(builder, hasher, '@jnxplus/nx-maven');
return builder.getUpdatedProjectGraph();
}
5 changes: 2 additions & 3 deletions packages/nx-quarkus-maven/src/dep-graph/lookup-deps.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { addProjectsAndDependencies } from '@jnxplus/maven';
import {
Hasher,
ProjectGraph,
ProjectGraphBuilder,
ProjectGraphProcessorContext,
} from '@nx/devkit';
import { addDependencies, addProjects } from '@jnxplus/maven';

export function processProjectGraph(
graph: ProjectGraph,
context: ProjectGraphProcessorContext
): ProjectGraph {
const builder = new ProjectGraphBuilder(graph);
const hasher = new Hasher(graph, context.nxJsonConfiguration, {});
addProjects(builder, hasher, '@jnxplus/nx-quarkus-maven', '');
addDependencies(builder);
addProjectsAndDependencies(builder, hasher, '@jnxplus/nx-quarkus-maven');
return builder.getUpdatedProjectGraph();
}

0 comments on commit 0a704a4

Please sign in to comment.