diff --git a/packages/devkit/src/generators/project-configuration.ts b/packages/devkit/src/generators/project-configuration.ts index 4816cf336ae3c..13eaf30f05c01 100644 --- a/packages/devkit/src/generators/project-configuration.ts +++ b/packages/devkit/src/generators/project-configuration.ts @@ -135,6 +135,7 @@ export function updateWorkspaceConfiguration( generators, implicitDependencies, plugins, + pluginsConfig, npmScope, targetDependencies, workspaceLayout, @@ -146,6 +147,7 @@ export function updateWorkspaceConfiguration( const nxJson: Required = { implicitDependencies, plugins, + pluginsConfig, npmScope, targetDependencies, workspaceLayout, diff --git a/packages/tao/src/shared/nx.ts b/packages/tao/src/shared/nx.ts index fe4c3aeeeea10..279989aa83ba4 100644 --- a/packages/tao/src/shared/nx.ts +++ b/packages/tao/src/shared/nx.ts @@ -92,6 +92,12 @@ export interface NxJsonConfiguration { * Plugins for extending the project graph */ plugins?: string[]; + + /** + * Configuration for Nx Plugins + */ + pluginsConfig?: Record; + /** * Default project. When project isn't provided, the default project * will be used. Convenient for small workspaces with one main application. diff --git a/packages/tao/src/shared/workspace.spec.ts b/packages/tao/src/shared/workspace.spec.ts index 6e4d0cc86e87b..ef41ca03c6f48 100644 --- a/packages/tao/src/shared/workspace.spec.ts +++ b/packages/tao/src/shared/workspace.spec.ts @@ -2,18 +2,9 @@ import { toProjectName, Workspaces } from './workspace'; import { NxJsonConfiguration } from './nx'; import { vol } from 'memfs'; -jest.mock('fs', () => require('memfs').fs); +import * as fastGlob from 'fast-glob'; -jest.mock('fast-glob', () => ({ - sync: () => [ - 'libs/lib1/package.json', - 'libs/lib1/project.json', - 'libs/lib2/package.json', - 'libs/domain/lib3/package.json', - 'libs/domain/lib4/project.json', - 'libs/domain/lib4/package.json', - ], -})); +jest.mock('fs', () => require('memfs').fs); const libConfig = (name) => ({ root: `libs/${name}`, @@ -26,7 +17,21 @@ const packageLibConfig = (root) => ({ }); describe('Workspaces', () => { + let globResults: string[]; + beforeEach(() => { + globResults = [ + 'libs/lib1/package.json', + 'libs/lib1/project.json', + 'libs/lib2/package.json', + 'libs/domain/lib3/package.json', + 'libs/domain/lib4/project.json', + 'libs/domain/lib4/package.json', + ]; + jest.spyOn(fastGlob, 'sync').mockImplementation(() => globResults); + }); + afterEach(() => { + jest.resetAllMocks(); vol.reset(); }); @@ -136,5 +141,27 @@ describe('Workspaces', () => { expect(appResults).toEqual('directory-my-app'); expect(libResults).toEqual('directory-mylib'); }); + + it('should use the workspace globs in package.json', () => { + globResults = ['packages/my-package/package.json']; + vol.fromJSON( + { + 'packages/my-package/package.json': JSON.stringify({ + name: 'my-package', + }), + 'package.json': JSON.stringify({ + workspaces: ['packages/**'], + }), + }, + '/root2' + ); + + const workspaces = new Workspaces('/root2'); + const resolved = workspaces.readWorkspaceConfiguration(); + expect(resolved.projects['my-package']).toEqual({ + root: 'packages/my-package', + sourceRoot: 'packages/my-package', + }); + }); }); }); diff --git a/packages/tao/src/shared/workspace.ts b/packages/tao/src/shared/workspace.ts index 2db0eb7527c68..eb629887663be 100644 --- a/packages/tao/src/shared/workspace.ts +++ b/packages/tao/src/shared/workspace.ts @@ -666,22 +666,58 @@ export function toProjectName( let projectGlobCache: string[]; let projectGlobCacheKey: string; -export function globForProjectFiles(root, nxJson?: NxJsonConfiguration) { + +function getGlobPatternsFromPlugins(nxJson: NxJsonConfiguration): string[] { + const plugins = loadNxPlugins(nxJson?.plugins); + + const patterns = []; + for (const plugin of plugins) { + if (!plugin.projectFilePatterns) { + continue; + } + for (const filePattern of plugin.projectFilePatterns) { + patterns.push('**/' + filePattern); + } + } + + return patterns; +} + +/** + * Get the package.json globs from package manager workspaces + */ +function getGlobPatternsFromPackageManagerWorkspaces(root: string): string[] { + // TODO: add support for pnpm + try { + const { workspaces } = readJsonFile(join(root, 'package.json')); + + return ( + workspaces?.map((pattern) => pattern + '/package.json') ?? [ + '**/package.json', + ] + ); + } catch { + return ['**/package.json']; + } +} + +export function globForProjectFiles( + root: string, + nxJson?: NxJsonConfiguration +) { // Deal w/ Caching const cacheKey = [root, ...(nxJson?.plugins || [])].join(','); if (projectGlobCache && cacheKey === projectGlobCacheKey) return projectGlobCache; projectGlobCacheKey = cacheKey; - // Load plugins - const plugins = loadNxPlugins(nxJson?.plugins).filter( - (x) => !!x.projectFilePatterns - ); - let combinedProjectGlobPattern = `**/+(project.json|package.json${ - plugins.length - ? '|' + plugins.map((x) => x.projectFilePatterns.join('|')).join('|') - : '' - })`; + const projectGlobPatterns: string[] = [ + '**/project.json', + ...getGlobPatternsFromPackageManagerWorkspaces(root), + ...getGlobPatternsFromPlugins(nxJson), + ]; + + const combinedProjectGlobPattern = '{' + projectGlobPatterns.join(',') + '}'; performance.mark('start-glob-for-projects'); /** diff --git a/packages/workspace/src/core/project-graph/build-project-graph.ts b/packages/workspace/src/core/project-graph/build-project-graph.ts index 007e3473b8620..de0c943c940bd 100644 --- a/packages/workspace/src/core/project-graph/build-project-graph.ts +++ b/packages/workspace/src/core/project-graph/build-project-graph.ts @@ -169,12 +169,13 @@ async function buildProjectGraphUsingContext( return r; } -function jsPluginConfig(nxJson: any) { - if (nxJson?.pluginsConfig?.['@nrwl/js']) { - return nxJson?.pluginsConfig['@nrwl/js']; - } else { - return {}; - } +interface NrwlJsPluginConfig { + analyzeSourceFiles?: boolean; + analyzePackageJson?: boolean; +} + +function jsPluginConfig(nxJson: NxJsonConfiguration): NrwlJsPluginConfig { + return nxJson?.pluginsConfig?.['@nrwl/js'] ?? {}; } function buildExplicitDependencies(