diff --git a/docs/generated/devkit/ProjectGraphExternalNode.md b/docs/generated/devkit/ProjectGraphExternalNode.md index df774d2ba0..52324003d2 100644 --- a/docs/generated/devkit/ProjectGraphExternalNode.md +++ b/docs/generated/devkit/ProjectGraphExternalNode.md @@ -14,8 +14,8 @@ while allowing tracking of the full tree of different nested versions ### Properties - [data](../../devkit/documents/ProjectGraphExternalNode#data): Object -- [name](../../devkit/documents/ProjectGraphExternalNode#name): `npm:${string}` -- [type](../../devkit/documents/ProjectGraphExternalNode#type): "npm" +- [name](../../devkit/documents/ProjectGraphExternalNode#name): string +- [type](../../devkit/documents/ProjectGraphExternalNode#type): string ## Properties @@ -35,10 +35,10 @@ while allowing tracking of the full tree of different nested versions ### name -• **name**: \`npm:$\{string}\` +• **name**: `string` --- ### type -• **type**: `"npm"` +• **type**: `string` diff --git a/packages/eslint-plugin/src/rules/enforce-module-boundaries.ts b/packages/eslint-plugin/src/rules/enforce-module-boundaries.ts index 1535330c6c..9ac1269f1f 100644 --- a/packages/eslint-plugin/src/rules/enforce-module-boundaries.ts +++ b/packages/eslint-plugin/src/rules/enforce-module-boundaries.ts @@ -50,6 +50,7 @@ import { matchImportWithWildcard, stringifyTags, } from '../utils/runtime-lint-utils'; +import { isProjectGraphProjectNode } from 'nx/src/config/project-graph'; export type Options = [ { @@ -525,6 +526,11 @@ export default ESLintUtils.RuleCreator( return; } + if (!isProjectGraphProjectNode(targetProject)) { + return; + } + targetProject = targetProject as ProjectGraphProjectNode; + // check constraints between libs and apps // check for circular dependency const circularPath = checkCircularPath( diff --git a/packages/js/src/utils/buildable-libs-utils.spec.ts b/packages/js/src/utils/buildable-libs-utils.spec.ts index f9cb121e31..709851c3c1 100644 --- a/packages/js/src/utils/buildable-libs-utils.spec.ts +++ b/packages/js/src/utils/buildable-libs-utils.spec.ts @@ -14,7 +14,7 @@ describe('updatePaths', () => { const deps: DependentBuildableProjectNode[] = [ { name: '@proj/lib', - node: { data: { root: 'libs/lib' } } as any, + node: { type: 'lib', data: { root: 'libs/lib' } } as any, outputs: ['dist/libs/lib'], }, ]; diff --git a/packages/js/src/utils/buildable-libs-utils.ts b/packages/js/src/utils/buildable-libs-utils.ts index d09048487a..6107594199 100644 --- a/packages/js/src/utils/buildable-libs-utils.ts +++ b/packages/js/src/utils/buildable-libs-utils.ts @@ -9,7 +9,6 @@ import { parseTargetString, readJsonFile, stripIndents, - workspaceRoot, writeJsonFile, } from '@nx/devkit'; import { unlinkSync } from 'fs'; @@ -20,6 +19,10 @@ import { dirname, join, relative, extname, resolve } from 'path'; import type * as ts from 'typescript'; import { readTsConfigPaths } from './typescript/ts-config'; import { randomUUID } from 'crypto'; +import { + isProjectGraphExternalNode, + isProjectGraphProjectNode, +} from 'nx/src/config/project-graph'; function isBuildable(target: string, node: ProjectGraphProjectNode): boolean { return ( @@ -112,7 +115,7 @@ export function calculateProjectDependencies( .map(({ name: dep, isTopLevel }) => { let project: DependentBuildableProjectNode = null; const depNode = projGraph.nodes[dep] || projGraph.externalNodes[dep]; - if (depNode.type === 'lib') { + if (isProjectGraphProjectNode(depNode) && depNode.type === 'lib') { if (isBuildable(targetName, depNode)) { const libPackageJsonPath = join( root, @@ -138,7 +141,7 @@ export function calculateProjectDependencies( } else { nonBuildableDependencies.push(dep); } - } else if (depNode.type === 'npm') { + } else if (isProjectGraphExternalNode(depNode)) { project = { name: depNode.data.packageName, outputs: [], @@ -530,54 +533,52 @@ export function updatePaths( ) { const pathsKeys = Object.keys(paths); // For each registered dependency - dependencies.forEach((dep) => { - if (dep.node.type === 'npm') { - return; - } + dependencies + .filter((dep) => isProjectGraphProjectNode(dep.node)) + .forEach((dep) => { + // If there are outputs + if (dep.outputs && dep.outputs.length > 0) { + // Directly map the dependency name to the output paths (dist/packages/..., etc.) + paths[dep.name] = dep.outputs; - // If there are outputs - if (dep.outputs && dep.outputs.length > 0) { - // Directly map the dependency name to the output paths (dist/packages/..., etc.) - paths[dep.name] = dep.outputs; + // check for secondary entrypoints + // For each registered path + for (const path of pathsKeys) { + const nestedName = `${dep.name}/`; - // check for secondary entrypoints - // For each registered path - for (const path of pathsKeys) { - const nestedName = `${dep.name}/`; + // If the path points to the current dependency and is nested (/) + if (path.startsWith(nestedName)) { + const nestedPart = path.slice(nestedName.length); - // If the path points to the current dependency and is nested (/) - if (path.startsWith(nestedName)) { - const nestedPart = path.slice(nestedName.length); + // Bind potential secondary endpoints for ng-packagr projects + let mappedPaths = dep.outputs.map( + (output) => `${output}/${nestedPart}` + ); - // Bind potential secondary endpoints for ng-packagr projects - let mappedPaths = dep.outputs.map( - (output) => `${output}/${nestedPart}` - ); + const { root } = (dep.node as ProjectGraphProjectNode).data; + // Update nested mappings to point to the dependency's output paths + mappedPaths = mappedPaths.concat( + paths[path].flatMap((p) => + dep.outputs.flatMap((output) => { + const basePath = p.replace(root, output); + return [ + // extension-less path to support compiled output + basePath.replace( + new RegExp(`${extname(basePath)}$`, 'gi'), + '' + ), + // original path with the root re-mapped to the output path + basePath, + ]; + }) + ) + ); - const { root } = dep.node.data; - // Update nested mappings to point to the dependency's output paths - mappedPaths = mappedPaths.concat( - paths[path].flatMap((p) => - dep.outputs.flatMap((output) => { - const basePath = p.replace(root, output); - return [ - // extension-less path to support compiled output - basePath.replace( - new RegExp(`${extname(basePath)}$`, 'gi'), - '' - ), - // original path with the root re-mapped to the output path - basePath, - ]; - }) - ) - ); - - paths[path] = mappedPaths; + paths[path] = mappedPaths; + } } } - } - }); + }); } /** @@ -630,7 +631,10 @@ export function updateBuildableProjectPackageJsonDependencies( ) { try { let depVersion; - if (entry.node.type === 'lib') { + if ( + isProjectGraphProjectNode(entry.node) && + entry.node.type === 'lib' + ) { const outputs = getOutputsForTargetAndConfiguration( { project: projectName, diff --git a/packages/nx/src/config/project-graph.ts b/packages/nx/src/config/project-graph.ts index 8de2e25d1e..091ed54972 100644 --- a/packages/nx/src/config/project-graph.ts +++ b/packages/nx/src/config/project-graph.ts @@ -103,6 +103,12 @@ export interface ProjectGraphProjectNode { }; } +export function isProjectGraphProjectNode( + node: ProjectGraphProjectNode | ProjectGraphExternalNode +): node is ProjectGraphProjectNode { + return node.type === 'app' || node.type === 'e2e' || node.type === 'lib'; +} + /** * A node describing an external dependency * `name` has as form of: @@ -114,8 +120,8 @@ export interface ProjectGraphProjectNode { * */ export interface ProjectGraphExternalNode { - type: 'npm'; - name: `npm:${string}`; + type: string; // not app, e2e, or lib + name: string; data: { version: string; packageName: string; @@ -123,6 +129,12 @@ export interface ProjectGraphExternalNode { }; } +export function isProjectGraphExternalNode( + node: ProjectGraphProjectNode | ProjectGraphExternalNode +): node is ProjectGraphExternalNode { + return isProjectGraphProjectNode(node) === false; +} + /** * A dependency between two projects */