diff --git a/packages/nx/src/native/index.d.ts b/packages/nx/src/native/index.d.ts index 73ec54f479d4e..6db4dd8c9ecf9 100644 --- a/packages/nx/src/native/index.d.ts +++ b/packages/nx/src/native/index.d.ts @@ -103,15 +103,9 @@ export const enum WorkspaceErrors { ParseError = 'ParseError', Generic = 'Generic' } -export interface ConfigurationParserResult { - projectNodes: Record - externalNodes: Record -} export interface NxWorkspaceFiles { projectFileMap: Record> globalFiles: Array - projectConfigurations: Record - externalNodes: Record } export class ImportResult { file: string @@ -140,9 +134,9 @@ export class Watcher { export class WorkspaceContext { workspaceRoot: string constructor(workspaceRoot: string) - getWorkspaceFiles(globs: Array, parseConfigurations: (arg0: Array) => ConfigurationParserResult): NxWorkspaceFiles + getWorkspaceFiles(globs: Array, parseConfigurations: (arg0: Array) => Record): NxWorkspaceFiles glob(globs: Array): Array - getProjectConfigurations(globs: Array, parseConfigurations: (arg0: Array) => ConfigurationParserResult): ConfigurationParserResult + getProjectConfigurations(globs: Array, parseConfigurations: (arg0: Array) => Record): Record incrementalUpdate(updatedFiles: Array, deletedFiles: Array): Record allFileData(): Array } diff --git a/packages/nx/src/native/tests/workspace_files.spec.ts b/packages/nx/src/native/tests/workspace_files.spec.ts index cd5b716b3d00c..84e1d58ca92b8 100644 --- a/packages/nx/src/native/tests/workspace_files.spec.ts +++ b/packages/nx/src/native/tests/workspace_files.spec.ts @@ -10,15 +10,9 @@ describe('workspace files', () => { const res = {}; for (const filename of filenames) { const json = readJsonFile(join(tempDir, filename)); - res[json.name] = { - ...json, - root: dirname(filename), - }; + res[dirname(filename)] = json.name; } - return { - projectNodes: res, - externalNodes: {}, - }; + return res; }; } @@ -57,14 +51,9 @@ describe('workspace files', () => { let globs = ['project.json', '**/project.json', 'libs/*/package.json']; const context = new WorkspaceContext(fs.tempDir); - let { projectFileMap, projectConfigurations, globalFiles } = - context.getWorkspaceFiles( - globs, - createParseConfigurationsFunction(fs.tempDir) - ); - - let sortedConfigs = Object.values(projectConfigurations).sort((a, b) => - a['name'].localeCompare(b['name']) + let { projectFileMap, globalFiles } = context.getWorkspaceFiles( + globs, + createParseConfigurationsFunction(fs.tempDir) ); expect(projectFileMap).toMatchInlineSnapshot(` @@ -121,30 +110,6 @@ describe('workspace files', () => { ], } `); - expect(sortedConfigs).toMatchInlineSnapshot(` - [ - { - "name": "nested-project", - "root": "libs/nested/project", - }, - { - "name": "package-project", - "root": "libs/package-project", - }, - { - "name": "project1", - "root": "libs/project1", - }, - { - "name": "project2", - "root": "libs/project2", - }, - { - "name": "project3", - "root": "libs/project3", - }, - ] - `); expect(globalFiles).toMatchInlineSnapshot(` [ { @@ -215,57 +180,6 @@ describe('workspace files', () => { `); }); - it('should dedupe configuration files', async () => { - const fs = new TempFs('workspace-files'); - const nxJson: NxJsonConfiguration = {}; - await fs.createFiles({ - './nx.json': JSON.stringify(nxJson), - './package.json': JSON.stringify({ - name: 'repo-name', - version: '0.0.0', - dependencies: {}, - }), - './project.json': JSON.stringify({ - name: 'repo-name', - }), - './libs/project1/project.json': JSON.stringify({ - name: 'project1', - }), - './libs/project1/package.json': JSON.stringify({ - name: 'project1', - }), - './libs/project1/index.js': '', - }); - - const context = new WorkspaceContext(fs.tempDir); - let globs = ['project.json', '**/project.json', '**/package.json']; - - let nodes = context.getProjectConfigurations(globs, (filenames) => { - const res = {}; - for (const filename of filenames) { - const json = readJsonFile(join(fs.tempDir, filename)); - res[json.name] = { - ...json, - root: dirname(filename), - }; - } - return { - externalNodes: {}, - projectNodes: res, - }; - }); - expect(nodes.projectNodes).toEqual({ - project1: { - name: 'project1', - root: 'libs/project1', - }, - 'repo-name': expect.objectContaining({ - name: 'repo-name', - root: '.', - }), - }); - }); - // describe('errors', () => { // it('it should infer names of configuration files without a name', async () => { // const fs = new TempFs('workspace-files'); diff --git a/packages/nx/src/native/workspace/config_files.rs b/packages/nx/src/native/workspace/config_files.rs index 230498d67abe8..5f32fc2634518 100644 --- a/packages/nx/src/native/workspace/config_files.rs +++ b/packages/nx/src/native/workspace/config_files.rs @@ -1,6 +1,6 @@ use crate::native::utils::glob::build_glob_set; use crate::native::utils::path::Normalize; -use crate::native::workspace::types::ConfigurationParserResult; +use std::collections::HashMap; use crate::native::workspace::errors::{InternalWorkspaceErrors, WorkspaceErrors}; use rayon::prelude::*; @@ -12,7 +12,7 @@ pub(super) fn glob_files( files: Option<&[(PathBuf, String)]>, ) -> napi::Result, WorkspaceErrors> { let Some(files) = files else { - return Ok(Default::default()) + return Ok(Default::default()); }; let globs = @@ -29,12 +29,11 @@ pub(super) fn get_project_configurations( globs: Vec, files: Option<&[(PathBuf, String)]>, parse_configurations: ConfigurationParser, -) -> napi::Result +) -> napi::Result> where - ConfigurationParser: Fn(Vec) -> napi::Result, + ConfigurationParser: Fn(Vec) -> napi::Result>, { - let config_paths = - glob_files(globs, files).map_err(anyhow::Error::from)?; + let config_paths = glob_files(globs, files).map_err(anyhow::Error::from)?; parse_configurations(config_paths) } diff --git a/packages/nx/src/native/workspace/context.rs b/packages/nx/src/native/workspace/context.rs index 0fe836ced56dc..717865ebcfc08 100644 --- a/packages/nx/src/native/workspace/context.rs +++ b/packages/nx/src/native/workspace/context.rs @@ -18,8 +18,6 @@ use crate::native::workspace::errors::WorkspaceErrors; use crate::native::workspace::workspace_files::NxWorkspaceFiles; use crate::native::workspace::{config_files, workspace_files}; -use crate::native::workspace::types::ConfigurationParserResult; - #[napi] pub struct WorkspaceContext { pub workspace_root: String, @@ -70,7 +68,7 @@ impl FilesWorker { pub fn get_files(&self) -> Option> { let Some(files_sync) = &self.0 else { trace!("there were no files because the workspace root did not exist"); - return None + return None; }; let (files_lock, cvar) = &files_sync.deref(); @@ -93,7 +91,7 @@ impl FilesWorker { ) -> HashMap { let Some(files_sync) = &self.0 else { trace!("there were no files because the workspace root did not exist"); - return HashMap::new(); + return HashMap::new(); }; let (files_lock, _) = &files_sync.deref(); @@ -108,8 +106,8 @@ impl FilesWorker { .par_iter() .filter_map(|path| { let full_path = workspace_root_path.join(path); - let Ok( content ) = std::fs::read(full_path) else { - trace!( "could not read file: ?full_path"); + let Ok(content) = std::fs::read(full_path) else { + trace!("could not read file: ?full_path"); return None; }; Some((path.to_string(), xxh3::xxh3_64(&content).to_string())) @@ -153,7 +151,7 @@ impl WorkspaceContext { parse_configurations: ConfigurationParser, ) -> napi::Result where - ConfigurationParser: Fn(Vec) -> napi::Result, + ConfigurationParser: Fn(Vec) -> napi::Result>, { workspace_files::get_files( globs, @@ -166,10 +164,7 @@ impl WorkspaceContext { } #[napi] - pub fn glob( - &self, - globs: Vec, - ) -> napi::Result, WorkspaceErrors> { + pub fn glob(&self, globs: Vec) -> napi::Result, WorkspaceErrors> { config_files::glob_files( globs, self.files_worker @@ -184,9 +179,9 @@ impl WorkspaceContext { &self, globs: Vec, parse_configurations: ConfigurationParser, - ) -> napi::Result + ) -> napi::Result> where - ConfigurationParser: Fn(Vec) -> napi::Result, + ConfigurationParser: Fn(Vec) -> napi::Result>, { config_files::get_project_configurations( globs, diff --git a/packages/nx/src/native/workspace/types.rs b/packages/nx/src/native/workspace/types.rs index a588d52fb0526..dc460dabcec66 100644 --- a/packages/nx/src/native/workspace/types.rs +++ b/packages/nx/src/native/workspace/types.rs @@ -1,15 +1,5 @@ -use std::collections::HashMap; - -use napi::JsObject; - #[derive(Debug, Eq, PartialEq)] pub enum FileLocation { Global, Project(String), } - -#[napi(object)] -pub struct ConfigurationParserResult { - pub project_nodes: HashMap, - pub external_nodes: HashMap, -} diff --git a/packages/nx/src/native/workspace/workspace_files.rs b/packages/nx/src/native/workspace/workspace_files.rs index 891b1fe1302c1..64c61b38bcbbf 100644 --- a/packages/nx/src/native/workspace/workspace_files.rs +++ b/packages/nx/src/native/workspace/workspace_files.rs @@ -1,4 +1,3 @@ -use napi::JsObject; use std::collections::HashMap; use std::path::{Path, PathBuf}; @@ -9,15 +8,13 @@ use crate::native::types::FileData; use crate::native::utils::path::Normalize; use crate::native::workspace::config_files; use crate::native::workspace::errors::{InternalWorkspaceErrors, WorkspaceErrors}; -use crate::native::workspace::types::{ConfigurationParserResult, FileLocation}; +use crate::native::workspace::types::FileLocation; #[napi(object)] #[derive(Default)] pub struct NxWorkspaceFiles { pub project_file_map: HashMap>, pub global_files: Vec, - pub project_configurations: HashMap, - pub external_nodes: HashMap, } pub(super) fn get_files( @@ -26,18 +23,17 @@ pub(super) fn get_files( file_data: Option<&[(PathBuf, String)]>, ) -> napi::Result where - ConfigurationParser: Fn(Vec) -> napi::Result, + ConfigurationParser: Fn(Vec) -> napi::Result>, { let Some(file_data) = file_data else { - return Ok(Default::default()) + return Ok(Default::default()); }; trace!("{globs:?}"); - let parsed_graph_nodes = + let root_map = transform_root_map( config_files::get_project_configurations(globs, Some(file_data), parse_configurations) - .map_err(|e| InternalWorkspaceErrors::ParseError(e.to_string()))?; - - let root_map = create_root_map(&parsed_graph_nodes.project_nodes); + .map_err(|e| InternalWorkspaceErrors::ParseError(e.to_string()))?, + ); trace!(?root_map); @@ -89,19 +85,12 @@ where Ok(NxWorkspaceFiles { project_file_map, global_files, - external_nodes: parsed_graph_nodes.external_nodes, - project_configurations: parsed_graph_nodes.project_nodes, }) } -fn create_root_map( - project_configurations: &HashMap, -) -> hashbrown::HashMap { - project_configurations - .iter() - .map(|(project_name, project_configuration)| { - let root: String = project_configuration.get("root").unwrap().unwrap(); - (PathBuf::from(root), project_name.clone()) - }) +fn transform_root_map(root_map: HashMap) -> hashbrown::HashMap { + root_map + .into_iter() + .map(|(project_root, project_name)| (PathBuf::from(project_root), project_name)) .collect() } diff --git a/packages/nx/src/project-graph/utils/project-configuration-utils.ts b/packages/nx/src/project-graph/utils/project-configuration-utils.ts index d821ec0ac9ff1..2f34174ebbb44 100644 --- a/packages/nx/src/project-graph/utils/project-configuration-utils.ts +++ b/packages/nx/src/project-graph/utils/project-configuration-utils.ts @@ -96,6 +96,7 @@ export function buildProjectsConfigurationsFromProjectPathsAndPlugins( ): { projects: Record; externalNodes: Record; + rootMap: Record; } { const projectRootMap: Map = new Map(); const externalNodes: Record = {}; @@ -133,9 +134,12 @@ export function buildProjectsConfigurationsFromProjectPathsAndPlugins( } } + const rootMap = createRootMap(projectRootMap); + return { projects: readProjectConfigurationsFromRootMap(projectRootMap), externalNodes, + rootMap, }; } @@ -290,3 +294,10 @@ export function readTargetDefaultsForTarget( return targetDefaults?.[targetName]; } } +function createRootMap(projectRootMap: Map) { + const map: Record = {}; + for (const [projectRoot, { name: projectName }] of projectRootMap) { + map[projectRoot] = projectName; + } + return map; +} diff --git a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts index af3bb2c0a38ea..8e36a2f5acea9 100644 --- a/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts +++ b/packages/nx/src/project-graph/utils/retrieve-workspace-files.ts @@ -60,25 +60,26 @@ export async function retrieveWorkspaceFiles( ); performance.mark('get-workspace-files:start'); + let projects: Record; + let externalNodes: Record; - const { projectConfigurations, projectFileMap, globalFiles, externalNodes } = - getNxWorkspaceFilesFromContext( - workspaceRoot, - globs, - (configs: string[]) => { - const projectConfigurations = createProjectConfigurations( - workspaceRoot, - nxJson, - configs, - plugins - ); - - return { - projectNodes: projectConfigurations.projects, - externalNodes: projectConfigurations.externalNodes, - }; - } - ) as NxWorkspaceFiles; + const { projectFileMap, globalFiles } = getNxWorkspaceFilesFromContext( + workspaceRoot, + globs, + (configs: string[]) => { + const projectConfigurations = createProjectConfigurations( + workspaceRoot, + nxJson, + configs, + plugins + ); + + projects = projectConfigurations.projects; + + externalNodes = projectConfigurations.externalNodes; + return projectConfigurations.rootMap; + } + ) as NxWorkspaceFiles; performance.mark('get-workspace-files:end'); performance.measure( 'get-workspace-files', @@ -94,9 +95,9 @@ export async function retrieveWorkspaceFiles( }, projectConfigurations: { version: 2, - projects: projectConfigurations, + projects, } as ProjectsConfigurations, - externalNodes: externalNodes as Record, + externalNodes, }; } @@ -176,26 +177,30 @@ function _retrieveProjectConfigurations( externalNodes: Record; projectNodes: Record; } { - return getProjectConfigurationsFromContext( + let result: { + externalNodes: Record; + projectNodes: Record; + }; + getProjectConfigurationsFromContext( workspaceRoot, globs, (configs: string[]) => { - const projectConfigurations = createProjectConfigurations( + const { projects, externalNodes, rootMap } = createProjectConfigurations( workspaceRoot, nxJson, configs, plugins ); - return { - projectNodes: projectConfigurations.projects, - externalNodes: projectConfigurations.externalNodes, + result = { + projectNodes: projects, + externalNodes: externalNodes, }; + + return rootMap; } - ) as { - externalNodes: Record; - projectNodes: Record; - }; + ); + return result; } export async function retrieveProjectConfigurationPaths( @@ -232,24 +237,28 @@ export function retrieveProjectConfigurationsWithoutPluginInference( return projectsWithoutPluginCache.get(cacheKey); } - const projectConfigurations = getProjectConfigurationsFromContext( + let projects: Record; + getProjectConfigurationsFromContext( root, projectGlobPatterns, (configs: string[]) => { - const { projects } = createProjectConfigurations(root, nxJson, configs, [ - { plugin: getNxPackageJsonWorkspacesPlugin(root) }, - { plugin: CreateProjectJsonProjectsPlugin }, - ]); - return { - projectNodes: projects, - externalNodes: {}, - }; + const projectConfigurations = createProjectConfigurations( + root, + nxJson, + configs, + [ + { plugin: getNxPackageJsonWorkspacesPlugin(root) }, + { plugin: CreateProjectJsonProjectsPlugin }, + ] + ); + projects = projectConfigurations.projects; + return projectConfigurations.rootMap; } - ).projectNodes as Record; + ); - projectsWithoutPluginCache.set(cacheKey, projectConfigurations); + projectsWithoutPluginCache.set(cacheKey, projects); - return projectConfigurations; + return projects; } function buildAllWorkspaceFiles( @@ -279,10 +288,11 @@ export function createProjectConfigurations( ): { projects: Record; externalNodes: Record; + rootMap: Record; } { performance.mark('build-project-configs:start'); - const { projects, externalNodes } = + const { projects, externalNodes, rootMap } = buildProjectsConfigurationsFromProjectPathsAndPlugins( nxJson, configFiles, @@ -302,6 +312,7 @@ export function createProjectConfigurations( return { projects: projectConfigurations, externalNodes, + rootMap, }; } diff --git a/packages/nx/src/utils/workspace-context.ts b/packages/nx/src/utils/workspace-context.ts index d7a275aaa1018..57dc8a91ae233 100644 --- a/packages/nx/src/utils/workspace-context.ts +++ b/packages/nx/src/utils/workspace-context.ts @@ -1,4 +1,4 @@ -import type { ConfigurationParserResult, WorkspaceContext } from '../native'; +import type { WorkspaceContext } from '../native'; import { performance } from 'perf_hooks'; let workspaceContext: WorkspaceContext | undefined; @@ -19,7 +19,7 @@ export function setupWorkspaceContext(workspaceRoot: string) { export function getNxWorkspaceFilesFromContext( workspaceRoot: string, globs: string[], - parseConfigurations: (files: string[]) => ConfigurationParserResult + parseConfigurations: (files: string[]) => Record ) { ensureContextAvailable(workspaceRoot); return workspaceContext.getWorkspaceFiles(globs, parseConfigurations); @@ -36,7 +36,7 @@ export function globWithWorkspaceContext( export function getProjectConfigurationsFromContext( workspaceRoot: string, globs: string[], - parseConfigurations: (files: string[]) => ConfigurationParserResult + parseConfigurations: (files: string[]) => Record ) { ensureContextAvailable(workspaceRoot); return workspaceContext.getProjectConfigurations(globs, parseConfigurations);